summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-06-12 15:00:24 +0800
committerJohn Hodge <tpg@mutabah.net>2016-06-12 15:00:24 +0800
commit8b607fc8d61f5ada0ad14f91a6cc02ffaa4178b2 (patch)
tree957fdbf96f02169cab3abd7173fa60de217d8f98
parentd7cff94061f2c42095e91ca5c30cffde03974cdc (diff)
downloadmrust-8b607fc8d61f5ada0ad14f91a6cc02ffaa4178b2.tar.gz
HIR Typecheck - Work around monomorph failure when part of associated type
-rw-r--r--src/hir_typeck/expr.cpp50
-rw-r--r--src/hir_typeck/expr_context.cpp86
2 files changed, 114 insertions, 22 deletions
diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp
index 77742b0a..1284e828 100644
--- a/src/hir_typeck/expr.cpp
+++ b/src/hir_typeck/expr.cpp
@@ -127,32 +127,33 @@ namespace typeck {
}
::HIR::TypeRef monomorphise_type_with(const Span& sp, const ::HIR::TypeRef& tpl, t_cb_generic callback, bool allow_infer)
{
- TRACE_FUNCTION_F("tpl = " << tpl);
+ ::HIR::TypeRef rv;
+ TRACE_FUNCTION_FR("tpl = " << tpl, rv);
TU_MATCH(::HIR::TypeRef::Data, (tpl.m_data), (e),
(Infer,
if( allow_infer ) {
- return ::HIR::TypeRef(e);
+ rv = ::HIR::TypeRef(e);
}
else {
BUG(sp, "_ type found in monomorphisation target");
}
),
(Diverge,
- return ::HIR::TypeRef(e);
+ rv = ::HIR::TypeRef(e);
),
(Primitive,
- return ::HIR::TypeRef(e);
+ rv = ::HIR::TypeRef(e);
),
(Path,
TU_MATCH(::HIR::Path::Data, (e.path.m_data), (e2),
(Generic,
- return ::HIR::TypeRef( ::HIR::TypeRef::Data::Data_Path {
+ rv = ::HIR::TypeRef( ::HIR::TypeRef::Data::Data_Path {
monomorphise_genericpath_with(sp, e2, callback, allow_infer),
e.binding.clone()
} );
),
(UfcsKnown,
- return ::HIR::TypeRef( ::HIR::Path::Data::make_UfcsKnown({
+ rv = ::HIR::TypeRef( ::HIR::Path::Data::make_UfcsKnown({
box$( monomorphise_type_with(sp, *e2.type, callback, allow_infer) ),
monomorphise_genericpath_with(sp, e2.trait, callback, allow_infer),
e2.item,
@@ -168,43 +169,43 @@ namespace typeck {
)
),
(Generic,
- return callback(tpl).clone();
+ rv = callback(tpl).clone();
),
(TraitObject,
- ::HIR::TypeRef::Data::Data_TraitObject rv;
- rv.m_trait = monomorphise_traitpath_with(sp, e.m_trait, callback, allow_infer);
+ ::HIR::TypeRef::Data::Data_TraitObject to;
+ to.m_trait = monomorphise_traitpath_with(sp, e.m_trait, callback, allow_infer);
for(const auto& trait : e.m_markers)
{
- rv.m_markers.push_back( monomorphise_genericpath_with(sp, trait, callback, allow_infer) );
+ to.m_markers.push_back( monomorphise_genericpath_with(sp, trait, callback, allow_infer) );
}
- rv.m_lifetime = e.m_lifetime;
- return ::HIR::TypeRef( mv$(rv) );
+ to.m_lifetime = e.m_lifetime;
+ rv = ::HIR::TypeRef( mv$(to) );
),
(Array,
if( e.size_val == ~0u ) {
BUG(sp, "Attempting to clone array with unknown size - " << tpl);
}
- return ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Array({
+ rv = ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Array({
box$( monomorphise_type_with(sp, *e.inner, callback) ),
::HIR::ExprPtr(),
e.size_val
}) );
),
(Slice,
- return ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Slice({ box$(monomorphise_type_with(sp, *e.inner, callback)) }) );
+ rv = ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Slice({ box$(monomorphise_type_with(sp, *e.inner, callback)) }) );
),
(Tuple,
::std::vector< ::HIR::TypeRef> types;
for(const auto& ty : e) {
types.push_back( monomorphise_type_with(sp, ty, callback) );
}
- return ::HIR::TypeRef( mv$(types) );
+ rv = ::HIR::TypeRef( mv$(types) );
),
(Borrow,
- return ::HIR::TypeRef::new_borrow(e.type, monomorphise_type_with(sp, *e.inner, callback));
+ rv = ::HIR::TypeRef::new_borrow(e.type, monomorphise_type_with(sp, *e.inner, callback));
),
(Pointer,
- return ::HIR::TypeRef::new_pointer(e.type, monomorphise_type_with(sp, *e.inner, callback));
+ rv = ::HIR::TypeRef::new_pointer(e.type, monomorphise_type_with(sp, *e.inner, callback));
),
(Function,
::HIR::FunctionType ft;
@@ -213,7 +214,7 @@ namespace typeck {
ft.m_rettype = box$( e.m_rettype->clone() );
for( const auto& arg : e.m_arg_types )
ft.m_arg_types.push_back( arg.clone() );
- return ::HIR::TypeRef( mv$(ft) );
+ rv = ::HIR::TypeRef( mv$(ft) );
),
(Closure,
::HIR::TypeRef::Data::Data_Closure oe;
@@ -221,10 +222,10 @@ namespace typeck {
oe.m_rettype = box$( monomorphise_type_with(sp, *e.m_rettype, callback) );
for(const auto& a : e.m_arg_types)
oe.m_arg_types.push_back( monomorphise_type_with(sp, a, callback) );
- return ::HIR::TypeRef(::HIR::TypeRef::Data::make_Closure( mv$(oe) ));
+ rv = ::HIR::TypeRef(::HIR::TypeRef::Data::make_Closure( mv$(oe) ));
)
)
- assert(!"Fell off end of monomorphise_type_with");
+ return rv;
}
::HIR::TypeRef monomorphise_type(const Span& sp, const ::HIR::GenericParams& params_def, const ::HIR::PathParams& params, const ::HIR::TypeRef& tpl)
@@ -1336,7 +1337,7 @@ namespace typeck {
const auto& path_params = e.m_params;
monomorph_cb = [&](const auto& gt)->const auto& {
const auto& e = gt.m_data.as_Generic();
- if( e.name == "Self" )
+ if( e.name == "Self" || e.binding == 0xFFFF )
TODO(sp, "Handle 'Self' when monomorphising");
if( e.binding < 256 ) {
BUG(sp, "Impl-level parameter on free function (#" << e.binding << " " << e.name << ")");
@@ -1511,6 +1512,7 @@ namespace typeck {
(TraitBound,
auto real_type = monomorphise_type_with(sp, be.type, cache.m_monomorph_cb);
const auto& trait_params = be.trait.m_path.m_params;
+ // TODO: Detect marker traits
auto rv = this->context.find_trait_impls(be.trait.m_path.m_path, real_type, [&](const auto& pp) {
if( pp.m_types.size() != trait_params.m_types.size() ) {
BUG(sp, "Parameter mismatch");
@@ -1533,7 +1535,11 @@ namespace typeck {
}
for( const auto& assoc : be.trait.m_type_bounds ) {
auto ty = ::HIR::TypeRef( ::HIR::Path(::HIR::Path::Data::Data_UfcsKnown { box$(real_type.clone()), be.trait.m_path.clone(), assoc.first, {} }) );
- this->context.apply_equality( sp, ty, [](const auto&x)->const auto&{return x;}, assoc.second, cache.m_monomorph_cb, nullptr );
+ // TODO: I'd like to avoid this copy, but expand_associated_types doesn't use the monomorph callback
+ auto other_ty = monomorphise_type_with(sp, assoc.second, cache.m_monomorph_cb, true);
+ DEBUG("Checking associated type bound " << assoc.first << " (" << ty << ") = " << assoc.second << " (" << other_ty << ")");
+ //this->context.apply_equality( sp, ty, [](const auto&x)->const auto&{return x;}, assoc.csecond, cache.m_monomorph_cb, nullptr );
+ this->context.apply_equality( sp, ty, other_ty );
}
),
diff --git a/src/hir_typeck/expr_context.cpp b/src/hir_typeck/expr_context.cpp
index 06f7d3d3..01f70ec6 100644
--- a/src/hir_typeck/expr_context.cpp
+++ b/src/hir_typeck/expr_context.cpp
@@ -811,6 +811,92 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR
// - If tags don't match, error
if( l_t.m_data.tag() != r_t.m_data.tag() ) {
+
+ // If either side is UFCS, and still contains unconstrained ivars - don't error
+ struct H {
+ static bool pathparams_contain_ivars(const TypecheckContext& context, const ::HIR::PathParams& pps) {
+ for( const auto& ty : pps.m_types ) {
+ if(H::type_contains_ivars(context, ty))
+ return true;
+ }
+ return false;
+ }
+ static bool type_contains_ivars(const TypecheckContext& context, const ::HIR::TypeRef& ty) {
+ TU_MATCH(::HIR::TypeRef::Data, (context.get_type(ty).m_data), (e),
+ (Infer, return true; ),
+ (Primitive, return false; ),
+ (Diverge, return false; ),
+ (Generic, return false; ),
+ (Path,
+ TU_MATCH(::HIR::Path::Data, (e.path.m_data), (pe),
+ (Generic,
+ return H::pathparams_contain_ivars(context, pe.m_params);
+ ),
+ (UfcsKnown,
+ if( H::type_contains_ivars(context, *pe.type) )
+ return true;
+ if( H::pathparams_contain_ivars(context, pe.trait.m_params) )
+ return true;
+ return H::pathparams_contain_ivars(context, pe.params);
+ ),
+ (UfcsInherent,
+ if( H::type_contains_ivars(context, *pe.type) )
+ return true;
+ return H::pathparams_contain_ivars(context, pe.params);
+ ),
+ (UfcsUnknown,
+ BUG(Span(), "UfcsUnknown");
+ )
+ )
+ ),
+ (Borrow,
+ return type_contains_ivars(context, *e.inner);
+ ),
+ (Pointer,
+ return type_contains_ivars(context, *e.inner);
+ ),
+ (Slice,
+ return type_contains_ivars(context, *e.inner);
+ ),
+ (Array,
+ return type_contains_ivars(context, *e.inner);
+ ),
+ (Closure,
+ TODO(Span(), "Closure");
+ ),
+ (Function,
+ TODO(Span(), "Closure");
+ ),
+ (TraitObject,
+ for(const auto& marker : e.m_markers)
+ if( H::pathparams_contain_ivars(context, marker.m_params) )
+ return true;
+ return H::pathparams_contain_ivars(context, e.m_trait.m_path.m_params);
+ ),
+ (Tuple,
+ for(const auto& st : e)
+ if( type_contains_ivars(context, st) )
+ return true;
+ return false;
+ )
+ )
+ throw "";
+ }
+ static bool type_is_free_ufcs(const TypecheckContext& context, const ::HIR::TypeRef& ty) {
+ TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Path, e,
+ if( e.path.m_data.is_Generic() ) {
+ return false;
+ }
+ return type_contains_ivars(context, ty);
+ )
+ return false;
+ }
+ };
+
+ if( H::type_is_free_ufcs(*this, l_t) || H::type_is_free_ufcs(*this, r_t) ) {
+ return ;
+ }
+
// Type error
this->dump();
ERROR(sp, E0000, "Type mismatch between " << l_t << " and " << r_t);