summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-06-12 17:27:28 +0800
committerJohn Hodge <tpg@mutabah.net>2016-06-12 17:27:28 +0800
commitb182c3780e0398921372ecef6780de3d0f89b016 (patch)
tree87a83a61c4c7ecbc2477386d4dc6f0cfbaef708a
parentbcbb256dfe65fcec89de375ca0d4bf80125713e9 (diff)
downloadmrust-b182c3780e0398921372ecef6780de3d0f89b016.tar.gz
HIR Typecheck - Fix edge case where monomorph was used on local type
-rw-r--r--src/hir_typeck/expr.cpp27
-rw-r--r--src/hir_typeck/expr_context.cpp4
2 files changed, 25 insertions, 6 deletions
diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp
index c81b7f8f..e800a784 100644
--- a/src/hir_typeck/expr.cpp
+++ b/src/hir_typeck/expr.cpp
@@ -1513,7 +1513,7 @@ namespace typeck {
DEBUG("RV " << cache.m_arg_types.back());
this->context.apply_equality(sp, res_type, cache.m_arg_types.back(), &this_node_ptr);
- // TODO: Check generic bounds (after links between args and params are known)
+ // Check generic bounds (after links between args and params are known)
// - HACK! Below just handles closures and fn traits.
// - TODO: Make this FAR more generic than it is
for(const auto& bound : cache.m_fcn_params->m_bounds)
@@ -1525,6 +1525,21 @@ namespace typeck {
),
(TraitBound,
auto real_type = monomorphise_type_with(sp, be.type, cache.m_monomorph_cb);
+ auto real_trait = monomorphise_genericpath_with(sp, be.trait.m_path, cache.m_monomorph_cb, false);
+ DEBUG("Bound " << be.type << " (" << real_type << ") : " << be.trait << " (" << real_trait << ")");
+ auto monomorph_bound = [&](const auto& gt)->const auto& {
+ return gt;
+ // TODO: Should this expand to the impl type?
+ // - Probably not, as that's `find_trait_impls`'s job
+ /*
+ const auto& ge = gt.m_data.as_Generic();
+ if( ge.binding == 0xFFFF )
+ return real_type;
+ else {
+ TODO(sp, "visit_call::monomorph_bound - Handle generic " << gt);
+ }
+ */
+ };
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) {
@@ -1533,12 +1548,16 @@ namespace typeck {
}
if( pp.m_types.size() > 0 )
{
- //TODO(sp, "Check equality of " << pp << " and " << trait_params << "(once monomorphed)");
+ DEBUG("Check equality of " << pp << " and " << trait_params << " (once monomorphed)");
// HACK! Just assume it's good and match.
// - This could have a false negative (if there's multiple impls of the trait with different params)
// - OR, it could false positive (Possible? Specialisation)
- for(unsigned int i = 0; i < pp.m_types.size(); i ++ )
- this->context.apply_equality(sp, pp.m_types[i], [](const auto&x)->const auto&{return x;}, trait_params.m_types[i], cache.m_monomorph_cb, nullptr);
+ for(unsigned int i = 0; i < pp.m_types.size(); i ++ ) {
+ auto l = monomorphise_type_with(sp, pp.m_types[i], monomorph_bound);
+ auto r = monomorphise_type_with(sp, trait_params.m_types[i], cache.m_monomorph_cb);
+ DEBUG(i << " " << l << " and " << r);
+ this->context.apply_equality(sp, pp.m_types[i], monomorph_bound, trait_params.m_types[i], cache.m_monomorph_cb, nullptr);
+ }
}
return true;
});
diff --git a/src/hir_typeck/expr_context.cpp b/src/hir_typeck/expr_context.cpp
index 01f70ec6..56fbe654 100644
--- a/src/hir_typeck/expr_context.cpp
+++ b/src/hir_typeck/expr_context.cpp
@@ -755,10 +755,10 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR
)
else {
// If generic replacement happened, clear the callback
- if( left.m_data.is_Generic() ) {
+ if( left.m_data.is_Generic() || left.m_data.is_Infer() ) {
cb_left = [](const auto& x)->const auto&{return x;};
}
- if( right.m_data.is_Generic() ) {
+ if( right.m_data.is_Generic() || right.m_data.is_Infer() ) {
cb_right = [](const auto& x)->const auto&{return x;};
}