summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-08-15 18:02:45 +0800
committerJohn Hodge <tpg@mutabah.net>2016-08-15 18:02:45 +0800
commitf2fb4b2385c0f91133ce61707c4a590753583ee2 (patch)
treec8afd18279582dd25777740c345fb8e631b4f1f8
parenta00403c78198205769046de68c72974f34c9b863 (diff)
downloadmrust-f2fb4b2385c0f91133ce61707c4a590753583ee2.tar.gz
HIR Typecheck Static - Cleaning up quirks in trait res
-rw-r--r--src/hir_typeck/static.cpp235
-rw-r--r--src/hir_typeck/static.hpp11
2 files changed, 149 insertions, 97 deletions
diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp
index 0ff6a892..0e0468f3 100644
--- a/src/hir_typeck/static.cpp
+++ b/src/hir_typeck/static.cpp
@@ -122,104 +122,136 @@ bool StaticTraitResolve::find_impl(
// Search the crate for impls
ret = m_crate.find_trait_impls(trait_path, type, cb_ident, [&](const auto& impl) {
- DEBUG("[find_impl] - impl" << impl.m_params.fmt_args() << " " << trait_path << impl.m_trait_args << " for " << impl.m_type << impl.m_params.fmt_bounds());
-
- ::std::vector< const ::HIR::TypeRef*> impl_params;
- impl_params.resize( impl.m_params.m_types.size() );
-
- auto cb = [&impl_params,&sp,cb_ident](auto idx, const auto& ty) {
- assert( idx < impl_params.size() );
- if( ! impl_params[idx] ) {
- impl_params[idx] = &ty;
+ return this->find_impl__check_crate(sp, trait_path, trait_params, type, found_cb, impl);
+ });
+ if(ret)
+ return true;
+
+ return false;
+}
+
+bool StaticTraitResolve::find_impl__check_crate(
+ const Span& sp,
+ const ::HIR::SimplePath& trait_path, const ::HIR::PathParams* trait_params,
+ const ::HIR::TypeRef& type,
+ t_cb_find_impl found_cb,
+ const ::HIR::TraitImpl& impl
+ ) const
+{
+ auto cb_ident = [](const auto&ty)->const auto&{return ty;};
+ DEBUG("impl" << impl.m_params.fmt_args() << " " << trait_path << impl.m_trait_args << " for " << impl.m_type << impl.m_params.fmt_bounds());
+
+ ::std::vector< const ::HIR::TypeRef*> impl_params;
+ impl_params.resize( impl.m_params.m_types.size() );
+
+ auto cb = [&impl_params,&sp,cb_ident](auto idx, const auto& ty) {
+ assert( idx < impl_params.size() );
+ if( ! impl_params[idx] ) {
+ impl_params[idx] = &ty;
+ return ::HIR::Compare::Equal;
+ }
+ else {
+ return impl_params[idx]->compare_with_placeholders(sp, ty, cb_ident);
+ }
+ };
+ auto match = impl.m_type.match_test_generics_fuzz(sp, type, cb_ident, cb);
+ if( trait_params )
+ {
+ assert( trait_params->m_types.size() == impl.m_trait_args.m_types.size() );
+ for( unsigned int i = 0; i < impl.m_trait_args.m_types.size(); i ++ )
+ {
+ const auto& l = impl.m_trait_args.m_types[i];
+ const auto& r = trait_params->m_types[i];
+ match &= l.match_test_generics_fuzz(sp, r, cb_ident, cb);
+ }
+ }
+ if( match != ::HIR::Compare::Equal ) {
+ DEBUG("[find_impl] > Type mismatch");
+ // TODO: Support fuzzy matches for some edge cases
+ return false;
+ }
+
+ ::std::vector< ::HIR::TypeRef> placeholders;
+ for(unsigned int i = 0; i < impl_params.size(); i ++ ) {
+ if( !impl_params[i] ) {
+ if( placeholders.size() == 0 )
+ placeholders.resize(impl_params.size());
+ placeholders[i] = ::HIR::TypeRef("impl_?", 2*256 + i);
+ }
+ }
+ // Callback that matches placeholders to concrete types
+ auto cb_match = [&](unsigned int idx, const auto& ty) {
+ if( ty.m_data.is_Generic() && ty.m_data.as_Generic().binding == idx )
+ return ::HIR::Compare::Equal;
+ if( idx >> 8 == 2 ) {
+ auto i = idx % 256;
+ ASSERT_BUG(sp, !impl_params[i], "Placeholder to populated type returned");
+ auto& ph = placeholders[i];
+ if( ph.m_data.is_Generic() && ph.m_data.as_Generic().binding == idx ) {
+ DEBUG("Bind placeholder " << i << " to " << ty);
+ ph = ty.clone();
return ::HIR::Compare::Equal;
}
else {
- return impl_params[idx]->compare_with_placeholders(sp, ty, cb_ident);
- }
- };
- auto match = impl.m_type.match_test_generics_fuzz(sp, type, cb_ident, cb);
- if( trait_params )
- {
- assert( trait_params->m_types.size() == impl.m_trait_args.m_types.size() );
- for( unsigned int i = 0; i < impl.m_trait_args.m_types.size(); i ++ )
- {
- const auto& l = impl.m_trait_args.m_types[i];
- const auto& r = trait_params->m_types[i];
- match &= l.match_test_generics_fuzz(sp, r, cb_ident, cb);
+ TODO(sp, "Compare placeholder " << i << " " << ph << " == " << ty);
}
}
- if( match != ::HIR::Compare::Equal ) {
- DEBUG("[find_impl] > Type mismatch");
- // TODO: Support fuzzy matches for some edge cases
- return false;
+ else {
+ return ::HIR::Compare::Unequal;
}
-
- ::std::vector< ::HIR::TypeRef> placeholders;
- for(unsigned int i = 0; i < impl_params.size(); i ++ ) {
- if( !impl_params[i] ) {
- if( placeholders.size() == 0 )
- placeholders.resize(impl_params.size());
- placeholders[i] = ::HIR::TypeRef("impl_?", 2*256 + i);
+ };
+ // Callback that returns monomorpisation results
+ auto cb_monomorph = [&](const auto& gt)->const auto& {
+ const auto& ge = gt.m_data.as_Generic();
+ ASSERT_BUG(sp, ge.binding >> 8 != 2, "");
+ assert( ge.binding < impl_params.size() );
+ if( !impl_params[ge.binding] ) {
+ return placeholders[ge.binding];
}
- }
- //auto cb_match = [&](unsigned int idx, const auto& ty) {
- // if( ty.m_data.is_Generic() && ty.m_data.as_Generic().binding == idx )
- // return ::HIR::Compare::Equal;
- // if( idx >> 8 == 2 ) {
- // auto i = idx % 256;
- // ASSERT_BUG(sp, !impl_params[i], "Placeholder to populated type returned");
- // auto& ph = placeholders[i];
- // if( ph.m_data.is_Generic() && ph.m_data.as_Generic().binding == idx ) {
- // DEBUG("Bind placeholder " << i << " to " << ty);
- // ph = ty.clone();
- // return ::HIR::Compare::Equal;
- // }
- // else {
- // TODO(sp, "Compare placeholder " << i << " " << ph << " == " << ty);
- // }
- // }
- // else {
- // return ::HIR::Compare::Unequal;
- // }
- // };
- auto cb_monomorph = [&](const auto& gt)->const auto& {
- const auto& ge = gt.m_data.as_Generic();
- ASSERT_BUG(sp, ge.binding >> 8 != 2, "");
- assert( ge.binding < impl_params.size() );
- if( !impl_params[ge.binding] ) {
- return placeholders[ge.binding];
- }
- return *impl_params[ge.binding];
- };
-
- // Bounds
- for(const auto& bound : impl.m_params.m_bounds) {
- TU_MATCH_DEF(::HIR::GenericBound, (bound), (e),
- (
- ),
- (TraitBound,
- DEBUG("Trait bound " << e.type << " : " << e.trait);
- auto b_ty_mono = monomorphise_type_with(sp, e.type, cb_monomorph);
- auto b_tp_mono = monomorphise_traitpath_with(sp, e.trait, cb_monomorph, false);
- DEBUG("- b_ty_mono = " << b_ty_mono << ", b_tp_mono = " << b_tp_mono);
- // HACK: If the type is '_', assume the bound passes
- if( b_ty_mono.m_data.is_Infer() ) {
- continue ;
- }
- if( !this->find_impl(sp, b_tp_mono.m_path.m_path, b_tp_mono.m_path.m_params, b_ty_mono, [](const auto&){return true;}) ) {
- DEBUG("> Fail - " << b_ty_mono << ": " << b_tp_mono);
- return false;
+ return *impl_params[ge.binding];
+ };
+
+ // Bounds
+ for(const auto& bound : impl.m_params.m_bounds) {
+ TU_MATCH_DEF(::HIR::GenericBound, (bound), (e),
+ (
+ ),
+ (TraitBound,
+ DEBUG("[find_impl] Trait bound " << e.type << " : " << e.trait);
+ auto b_ty_mono = monomorphise_type_with(sp, e.type, cb_monomorph);
+ auto b_tp_mono = monomorphise_traitpath_with(sp, e.trait, cb_monomorph, false);
+ for(auto& assoc_bound : b_tp_mono.m_type_bounds) {
+ this->expand_associated_types(sp, assoc_bound.second);
+ }
+ DEBUG("[find_impl] - b_ty_mono = " << b_ty_mono << ", b_tp_mono = " << b_tp_mono);
+ // HACK: If the type is '_', assume the bound passes
+ if( b_ty_mono.m_data.is_Infer() ) {
+ continue ;
+ }
+ auto rv = this->find_impl(sp, b_tp_mono.m_path.m_path, b_tp_mono.m_path.m_params, b_ty_mono, [&](const auto& impl) {
+
+ for(const auto& assoc_bound : b_tp_mono.m_type_bounds) {
+ const char* name = assoc_bound.first.c_str();
+ const ::HIR::TypeRef& exp = assoc_bound.second;
+ ::HIR::TypeRef have = impl.get_type(name);
+ // TODO: Returning `_` means unset associated type, should that still be compared?
+ if( have != ::HIR::TypeRef() )
+ {
+ auto cmp = have .match_test_generics_fuzz(sp, exp, cb_ident, cb_match);
+ ASSERT_BUG(sp, cmp == ::HIR::Compare::Equal, "Assoc ty " << name << " mismatch, " << have << " != des " << exp);
+ }
}
- )
+ return true;
+ });
+ if( !rv ) {
+ DEBUG("[find_impl] > Fail - " << b_ty_mono << ": " << b_tp_mono);
+ return false;
+ }
)
- }
-
- return found_cb( ImplRef(impl_params, impl) );
- });
- if(ret)
- return true;
+ )
+ }
- return false;
+ return found_cb( ImplRef(impl_params, impl) );
}
void StaticTraitResolve::expand_associated_types(const Span& sp, ::HIR::TypeRef& input) const
@@ -404,7 +436,7 @@ void StaticTraitResolve::expand_associated_types(const Span& sp, ::HIR::TypeRef&
//e2.trait = mv$(trait_path);
rv = this->find_impl(sp, trait_path.m_path, trait_path.m_params, *e2.type, [&](const auto& impl) {
- DEBUG("Found impl" << impl);
+ DEBUG("[expand_associated_types] Found " << impl);
auto nt = impl.get_type( e2.item.c_str() );
DEBUG("Converted UfcsKnown - " << e.path << " = " << nt);
@@ -697,7 +729,7 @@ bool ImplRef::type_is_specializable(const char* name) const
static Span sp;
TU_MATCH(Data, (this->m_data), (e),
(TraitImpl,
- DEBUG(*this);
+ DEBUG("name=" << name << " " << *this);
auto it = e.impl->m_types.find(name);
if( it == e.impl->m_types.end() )
return ::HIR::TypeRef();
@@ -754,18 +786,27 @@ bool ImplRef::type_is_specializable(const char* name) const
for( unsigned int i = 0; i < e.impl->m_params.m_types.size(); i ++ )
{
const auto& ty_d = e.impl->m_params.m_types[i];
- os << ty_d.m_name << " = ";
- if( e.params[i] ) {
- os << *e.params[i];
- }
- else {
- os << "?";
- }
+ os << ty_d.m_name;
os << ",";
}
os << ">";
}
os << " ?" << e.impl->m_trait_args << " for " << e.impl->m_type << e.impl->m_params.fmt_bounds();
+ os << " {";
+ for( unsigned int i = 0; i < e.impl->m_params.m_types.size(); i ++ )
+ {
+ const auto& ty_d = e.impl->m_params.m_types[i];
+ os << ty_d.m_name;
+ os << ty_d.m_name << " = ";
+ if( e.params[i] ) {
+ os << *e.params[i];
+ }
+ else {
+ os << "?";
+ }
+ os << ",";
+ }
+ os << "}";
}
),
(BoundedPtr,
diff --git a/src/hir_typeck/static.hpp b/src/hir_typeck/static.hpp
index 8d4046a8..69eb2ba3 100644
--- a/src/hir_typeck/static.hpp
+++ b/src/hir_typeck/static.hpp
@@ -78,6 +78,17 @@ public:
const ::HIR::TypeRef& type,
t_cb_find_impl found_cb
) const;
+
+private:
+ bool find_impl__check_crate(
+ const Span& sp,
+ const ::HIR::SimplePath& trait_path, const ::HIR::PathParams* trait_params,
+ const ::HIR::TypeRef& type,
+ t_cb_find_impl found_cb,
+ const ::HIR::TraitImpl& impl
+ ) const;
+
+public:
void expand_associated_types(const Span& sp, ::HIR::TypeRef& input) const;
/// \}