summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-07-07 17:59:55 +1000
committerJohn Hodge <tpg@mutabah.net>2016-07-07 17:59:55 +1000
commit5ef1f59ce1ba4e0c96206775a72facae0ce744da (patch)
treec8b07641cb4b69a383c5f5f7d1f89e0ddb03d022 /src
parentdca7fb1c1da918a46fb40e18745e420a16627b8e (diff)
downloadmrust-5ef1f59ce1ba4e0c96206775a72facae0ce744da.tar.gz
HIR Typecheck CS - Associated type bounds, hacky handling of deferred type equalities (associated types)
Diffstat (limited to 'src')
-rw-r--r--src/hir_typeck/expr_cs.cpp72
-rw-r--r--src/hir_typeck/helpers.cpp73
-rw-r--r--src/hir_typeck/helpers.hpp4
3 files changed, 131 insertions, 18 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index eba4eef0..0d9b1344 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -43,7 +43,7 @@ struct Context
::HIR::SimplePath trait;
::HIR::PathParams params;
::HIR::TypeRef impl_ty;
- const char* name; // if "", no type is used (and left is ignored) - Just does trait selection
+ ::std::string name; // if "", no type is used (and left is ignored) - Just does trait selection
friend ::std::ostream& operator<<(::std::ostream& os, const Associated& v) {
os << v.left_ty << " = " << "<" << v.impl_ty << " as " << v.trait << v.params << ">::" << v.name;
@@ -304,7 +304,14 @@ namespace {
DEBUG("Bound " << be.type << ": " << be.trait);
DEBUG("= (" << real_type << ": " << real_trait << ")");
const auto& trait_params = real_trait.m_params;
- context.equate_types_assoc(sp, ::HIR::TypeRef(), be.trait.m_path.m_path, mv$(trait_params.clone().m_types), real_type, "");
+
+ const auto& trait_path = be.trait.m_path.m_path;
+ context.equate_types_assoc(sp, ::HIR::TypeRef(), trait_path, mv$(trait_params.clone().m_types), real_type, "");
+
+ for( const auto& assoc : be.trait.m_type_bounds ) {
+ auto other_ty = monomorphise_type_with(sp, assoc.second, cache.m_monomorph_cb, true);
+ context.equate_types_assoc(sp, other_ty, trait_path, mv$(trait_params.clone().m_types), real_type, assoc.first.c_str());
+ }
),
(TypeEquality,
auto real_type_left = context.m_resolve.expand_associated_types(sp, monomorphise_type_with(sp, be.type, cache.m_monomorph_cb));
@@ -1612,6 +1619,32 @@ void Context::equate_types(const Span& sp, const ::HIR::TypeRef& li, const ::HIR
return ;
)
+ // - If the destructuring would fail
+ if( l_t.compare_with_placeholders(sp, r_t, this->m_ivars.callback_resolve_infer()) == ::HIR::Compare::Unequal )
+ {
+ // BUT! It was due to an unknown associated type
+ TU_IFLET(::HIR::TypeRef::Data, r_t.m_data, Path, r_e,
+ TU_IFLET(::HIR::Path::Data, r_e.path.m_data, UfcsKnown, rpe,
+ if( r_e.binding.is_Unbound() ) {
+ // TODO: Try this operation again later?
+ this->equate_types_assoc(sp, l_t, rpe.trait.m_path, rpe.trait.m_params.clone().m_types, *rpe.type, rpe.item.c_str());
+ return ;
+ //TODO(sp, "Defer structural equality of unknown associated type");
+ }
+ )
+ )
+ TU_IFLET(::HIR::TypeRef::Data, l_t.m_data, Path, l_e,
+ TU_IFLET(::HIR::Path::Data, l_e.path.m_data, UfcsKnown, lpe,
+ if( l_e.binding.is_Unbound() ) {
+ // TODO: Try this operation again later?
+ this->equate_types_assoc(sp, r_t, lpe.trait.m_path, lpe.trait.m_params.clone().m_types, *lpe.type, lpe.item.c_str());
+ return ;
+ //TODO(sp, "Defer structural equality of unknown associated type");
+ }
+ )
+ )
+ }
+
if( l_t.m_data.tag() != r_t.m_data.tag() ) {
ERROR(sp, E0000, "Type mismatch between " << this->m_ivars.fmt_type(l_t) << " and " << this->m_ivars.fmt_type(r_t));
}
@@ -2565,20 +2598,20 @@ namespace {
DEBUG("- (fail) bounded impl " << v.trait << v.params << " (ty_right = " << context.m_ivars.fmt_type(v.impl_ty));
return false;
}
+
+ if( v.name != "" ) {
+ if( assoc.count(v.name) == 0 )
+ BUG(sp, "Getting associated type '" << v.name << "' which isn't in list");
+ output_type = assoc.at(v.name).clone();
+ }
count += 1;
if( cmp == ::HIR::Compare::Equal ) {
- if( v.name[0] ) {
- output_type = assoc.at(v.name).clone();
- }
return true;
}
else {
if( possible_impl_ty == ::HIR::TypeRef() ) {
possible_impl_ty = impl_ty.clone();
possible_params = args.clone();
- if( v.name[0] ) {
- output_type = assoc.at(v.name).clone();
- }
}
return false;
@@ -2586,7 +2619,7 @@ namespace {
});
if( found ) {
// Fully-known impl
- if( v.name[0] ) {
+ if( v.name != "" ) {
context.equate_types(sp, v.left_ty, output_type);
}
return true;
@@ -2603,7 +2636,7 @@ namespace {
else if( count == 1 ) {
DEBUG("Only one impl " << v.trait << possible_params << " for " << possible_impl_ty << " - params=" << possible_params << ", ty=" << possible_impl_ty << ", out=" << output_type);
// Only one possible impl
- if( v.name[0] ) {
+ if( v.name != "" ) {
context.equate_types(sp, v.left_ty, output_type);
}
assert( possible_impl_ty != ::HIR::TypeRef() );
@@ -2665,13 +2698,18 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR:
}
// 3. Check associated type rules
DEBUG("--- Associated types");
- for(auto it = context.link_assoc.begin(); it != context.link_assoc.end(); ) {
- if( check_associated(context, *it) ) {
- DEBUG("- Consumed associated type rule - " << *it);
- it = context.link_assoc.erase(it);
+ //for(auto it = context.link_assoc.begin(); it != context.link_assoc.end(); ) {
+ // const auto& rule = *it;
+ for(unsigned int i = 0; i < context.link_assoc.size(); ) {
+ const auto& rule = context.link_assoc[i];
+ if( check_associated(context, rule) ) {
+ DEBUG("- Consumed associated type rule - " << rule);
+ context.link_assoc.erase( context.link_assoc.begin() + i );
+ //it = context.link_assoc.erase(it);
}
else {
- ++ it;
+ //++ it;
+ i ++;
}
}
// 4. Revisit nodes that require revisiting
@@ -2751,13 +2789,13 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR:
}
// - Validate typeck
- expr = ::HIR::ExprPtr( mv$(root_ptr) );
{
DEBUG("==== VALIDATE ====");
context.dump();
ExprVisitor_Apply visitor { context.m_ivars };
- expr->visit( visitor );
+ root_ptr->visit( visitor );
}
+ expr = ::HIR::ExprPtr( mv$(root_ptr) );
}
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp
index 9e9467b0..3d069dde 100644
--- a/src/hir_typeck/helpers.cpp
+++ b/src/hir_typeck/helpers.cpp
@@ -269,6 +269,7 @@ void HMTypeInferrence::compact_ivars()
if( !v.is_alias() ) {
//auto nt = this->expand_associated_types(Span(), v.type->clone());
auto nt = v.type->clone();
+
DEBUG("- " << i << " " << *v.type << " -> " << nt);
*v.type = mv$(nt);
}
@@ -418,6 +419,77 @@ void HMTypeInferrence::print_type(::std::ostream& os, const ::HIR::TypeRef& tr)
)
}
+void HMTypeInferrence::expand_ivars(::HIR::TypeRef& type)
+{
+ TU_MATCH(::HIR::TypeRef::Data, (type.m_data), (e),
+ (Infer,
+ const auto& t = this->get_type(type);
+ if( &t != &type ) {
+ type = t.clone();
+ }
+ ),
+ (Diverge,
+ ),
+ (Primitive,
+ ),
+ (Path,
+ // Iterate all arguments
+ TU_MATCH(::HIR::Path::Data, (e.path.m_data), (e2),
+ (Generic,
+ this->expand_ivars_params(e2.m_params);
+ ),
+ (UfcsKnown,
+ this->expand_ivars(*e2.type);
+ this->expand_ivars_params(e2.trait.m_params);
+ this->expand_ivars_params(e2.params);
+ ),
+ (UfcsUnknown,
+ this->expand_ivars(*e2.type);
+ this->expand_ivars_params(e2.params);
+ ),
+ (UfcsInherent,
+ this->expand_ivars(*e2.type);
+ this->expand_ivars_params(e2.params);
+ )
+ )
+ ),
+ (Generic,
+ ),
+ (TraitObject,
+ // TODO: Iterate all paths
+ ),
+ (Array,
+ this->expand_ivars(*e.inner);
+ ),
+ (Slice,
+ this->expand_ivars(*e.inner);
+ ),
+ (Tuple,
+ for(auto& ty : e)
+ this->expand_ivars(ty);
+ ),
+ (Borrow,
+ this->expand_ivars(*e.inner);
+ ),
+ (Pointer,
+ this->expand_ivars(*e.inner);
+ ),
+ (Function,
+ // No ivars allowed?
+ ),
+ (Closure,
+ this->expand_ivars(*e.m_rettype);
+ for(auto& ty : e.m_arg_types)
+ this->expand_ivars(ty);
+ )
+ )
+}
+void HMTypeInferrence::expand_ivars_params(::HIR::PathParams& params)
+{
+ for(auto& arg : params.m_types)
+ expand_ivars(arg);
+}
+
void HMTypeInferrence::add_ivars(::HIR::TypeRef& type)
{
TU_MATCH(::HIR::TypeRef::Data, (type.m_data), (e),
@@ -887,6 +959,7 @@ void TraitResolution::compact_ivars(HMTypeInferrence& m_ivars)
for(auto& v : m_ivars.m_ivars)
{
if( !v.is_alias() ) {
+ m_ivars.expand_ivars( *v.type );
// Don't expand unless it is needed
if( this->has_associated_type(*v.type) ) {
// TODO: cloning is expensive, BUT printing below is nice
diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp
index 93fe8cf9..56106cf1 100644
--- a/src/hir_typeck/helpers.hpp
+++ b/src/hir_typeck/helpers.hpp
@@ -99,6 +99,9 @@ public:
// Lookup
::HIR::TypeRef& get_type(::HIR::TypeRef& type);
const ::HIR::TypeRef& get_type(const ::HIR::TypeRef& type) const;
+
+ void expand_ivars(::HIR::TypeRef& type);
+ void expand_ivars_params(::HIR::PathParams& params);
// Helpers
bool pathparams_contain_ivars(const ::HIR::PathParams& pps) const;
@@ -110,7 +113,6 @@ private:
};
-// NOTE: impl is in expr_context.cpp
class TraitResolution
{
const HMTypeInferrence& m_ivars;