summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-09-29 15:31:59 +0800
committerJohn Hodge <tpg@mutabah.net>2016-09-29 15:31:59 +0800
commit3a31e6b5f85436d9b239e23cfcb6bf39e5ad052d (patch)
treef8cbae6cc7d75cfdad7ea44005a3e3f52ee3d594 /src
parenta19bd7137b56c92f3363ea2eb6e2e4ed0a0fd271 (diff)
downloadmrust-3a31e6b5f85436d9b239e23cfcb6bf39e5ad052d.tar.gz
HIR Typecheck Expr - Draft auto trait impl search
Diffstat (limited to 'src')
-rw-r--r--src/hir/hir.cpp20
-rw-r--r--src/hir/hir.hpp3
-rw-r--r--src/hir_typeck/helpers.cpp44
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());