diff options
author | John Hodge <tpg@mutabah.net> | 2016-09-29 15:31:59 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-09-29 15:31:59 +0800 |
commit | 3a31e6b5f85436d9b239e23cfcb6bf39e5ad052d (patch) | |
tree | f8cbae6cc7d75cfdad7ea44005a3e3f52ee3d594 /src | |
parent | a19bd7137b56c92f3363ea2eb6e2e4ed0a0fd271 (diff) | |
download | mrust-3a31e6b5f85436d9b239e23cfcb6bf39e5ad052d.tar.gz |
HIR Typecheck Expr - Draft auto trait impl search
Diffstat (limited to 'src')
-rw-r--r-- | src/hir/hir.cpp | 20 | ||||
-rw-r--r-- | src/hir/hir.hpp | 3 | ||||
-rw-r--r-- | src/hir_typeck/helpers.cpp | 44 |
3 files changed, 66 insertions, 1 deletions
diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp index aa3344eb..40ad9f86 100644 --- a/src/hir/hir.cpp +++ b/src/hir/hir.cpp @@ -560,6 +560,26 @@ bool ::HIR::Crate::find_trait_impls(const ::HIR::SimplePath& trait, const ::HIR: } return false; } +bool ::HIR::Crate::find_auto_trait_impls(const ::HIR::SimplePath& trait, const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::MarkerImpl&)> callback) const +{ + auto its = this->m_marker_impls.equal_range( trait ); + for( auto it = its.first; it != its.second; ++ it ) + { + const auto& impl = it->second; + if( impl.matches_type(type, ty_res) ) { + if( callback(impl) ) { + return true; + } + } + } + for( const auto& ec : this->m_ext_crates ) + { + if( ec.second->find_auto_trait_impls(trait, type, ty_res, callback) ) { + return true; + } + } + return false; +} bool ::HIR::Crate::find_type_impls(const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::TypeImpl&)> callback) const { for( const auto& impl : this->m_type_impls ) diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index e1406067..c439960a 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -190,7 +190,7 @@ struct Trait ::std::string m_lifetime; ::std::vector< ::HIR::TraitPath > m_parent_traits; - bool m_is_marker; + bool m_is_marker; // aka OIBIT ::std::unordered_map< ::std::string, AssociatedType > m_types; ::std::unordered_map< ::std::string, TraitValueItem > m_values; @@ -361,6 +361,7 @@ public: } bool find_trait_impls(const ::HIR::SimplePath& path, const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::TraitImpl&)> callback) const; + bool find_auto_trait_impls(const ::HIR::SimplePath& path, const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::MarkerImpl&)> callback) const; bool find_type_impls(const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::TypeImpl&)> callback) const; }; diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index e9276601..14c6085f 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -1881,6 +1881,50 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, { TRACE_FUNCTION_F(trait << FMT_CB(ss, if(params_ptr) { ss << *params_ptr; } else { ss << "<?>"; }) << " for " << type); + // Handle auto traits (aka OIBITs) + if( m_crate.get_trait_by_path(sp, trait).m_is_marker ) + { + // NOTE: Expected behavior is for Ivars to return false + // TODO: Should they return Compare::Fuzzy instead? + if( type.m_data.is_Infer() ) { + return false; + } + + // - Search for positive impls for this type + bool positive_found = this->m_crate.find_auto_trait_impls(trait, type, this->m_ivars.callback_resolve_infer(), + [&](const auto& impl) { + // Skip any negative impls on this pass + if( impl.is_positive != true ) + return false; + TODO(sp, "Matching positive impl " << trait << " for " << type); + }); + if( positive_found ) { + // A positive impl was found, so return true (callback should have been called) + return true; + } + + // - Search for negative impls for this type + bool negative_found = this->m_crate.find_auto_trait_impls(trait, type, this->m_ivars.callback_resolve_infer(), + [&](const auto& impl) { + // Skip any positive impls + if( impl.is_positive != false ) + return false; + TODO(sp, "Matching negative impl !" << trait << " for " << type); + }); + if( negative_found ) { + // A negative impl _was_ found, so return false + return false; + } + + // - If the type is a path (struct/enum/...), search for impls for all contained types. + TU_IFLET( ::HIR::TypeRef::Data, type.m_data, Path, e, + ) + // Otherwise, there's no negative so it must be positive + else { + return true; + } + } + return this->m_crate.find_trait_impls(trait, type, this->m_ivars.callback_resolve_infer(), [&](const auto& impl) { DEBUG("[find_trait_impls_crate] Found impl" << impl.m_params.fmt_args() << " " << trait << impl.m_trait_args << " for " << impl.m_type << " " << impl.m_params.fmt_bounds()); |