summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-10-22 19:22:16 +0800
committerJohn Hodge <tpg@mutabah.net>2016-10-22 19:22:16 +0800
commit1806e3626bd756811ab9cbbba8ee8d418089a0a7 (patch)
tree56bf7c3383022443f5447862ccf7e1a7e0ca64a6 /src
parent47512820a4e4eecc1c76096f4a9e9f82a0a4f9eb (diff)
downloadmrust-1806e3626bd756811ab9cbbba8ee8d418089a0a7.tar.gz
HIR Typecheck Expr - Error earlier if an impl can't be found
Diffstat (limited to 'src')
-rw-r--r--src/hir/type.cpp30
-rw-r--r--src/hir_typeck/expr_cs.cpp14
-rw-r--r--src/hir_typeck/helpers.cpp46
-rw-r--r--src/main.cpp4
4 files changed, 73 insertions, 21 deletions
diff --git a/src/hir/type.cpp b/src/hir/type.cpp
index 6f465c44..812e01e4 100644
--- a/src/hir/type.cpp
+++ b/src/hir/type.cpp
@@ -575,6 +575,11 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x
DEBUG("- Fuzzy match due to opaque");
return Compare::Fuzzy;
}
+ // HACK: If RHS is unbound, fuzz it
+ if( x.m_data.is_Path() && x.m_data.as_Path().binding.is_Unbound() ) {
+ DEBUG("- Fuzzy match due to unbound");
+ return Compare::Fuzzy;
+ }
// HACK: If the RHS is a placeholder generic, allow it.
if( x.m_data.is_Generic() && (x.m_data.as_Generic().binding >> 8) == 2 ) {
DEBUG("- Fuzzy match due to placeholder");
@@ -854,6 +859,9 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x
return Compare::Unequal;
}
)
+ else TU_IFLET(::HIR::TypeRef::Data, right.m_data, Path, oe,
+ return oe.binding.is_Unbound() ? Compare::Fuzzy : Compare::Unequal;
+ )
else {
return Compare::Unequal;
}
@@ -879,6 +887,9 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x
return Compare::Unequal;
}
)
+ else TU_IFLET(::HIR::TypeRef::Data, right.m_data, Path, oe,
+ return oe.binding.is_Unbound() ? Compare::Fuzzy : Compare::Unequal;
+ )
else {
return Compare::Unequal;
}
@@ -907,6 +918,9 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x
return Compare::Unequal;
}
)
+ else TU_IFLET(::HIR::TypeRef::Data, left.m_data, Path, oe,
+ return oe.binding.is_Unbound() ? Compare::Fuzzy : Compare::Unequal;
+ )
else {
return Compare::Unequal;
}
@@ -921,6 +935,9 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x
return Compare::Unequal;
}
)
+ else TU_IFLET(::HIR::TypeRef::Data, left.m_data, Path, oe,
+ return oe.binding.is_Unbound() ? Compare::Fuzzy : Compare::Unequal;
+ )
else {
return Compare::Unequal;
}
@@ -938,6 +955,12 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x
if( right.m_data.is_Path() && right.m_data.as_Path().binding.is_Unbound() ) {
return Compare::Fuzzy;
}
+ if( left.m_data.is_Generic() && (left.m_data.as_Generic().binding >> 8) == 2 ) {
+ return Compare::Fuzzy;
+ }
+ if( right.m_data.is_Generic() && (right.m_data.as_Generic().binding >> 8) == 2 ) {
+ return Compare::Fuzzy;
+ }
return Compare::Unequal;
}
TU_MATCH(::HIR::TypeRef::Data, (left.m_data, right.m_data), (le, re),
@@ -952,8 +975,13 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x
return le.path.compare_with_placeholders( sp, re.path, resolve_placeholder );
),
(Generic,
- if( le.binding != re.binding )
+ if( le.binding != re.binding ) {
+ if( (le.binding >> 8) == 2 )
+ return Compare::Fuzzy;
+ if( (re.binding >> 8) == 2 )
+ return Compare::Fuzzy;
return Compare::Unequal;
+ }
return Compare::Equal;
),
(TraitObject,
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index b0d8f0b5..14b40cc8 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -4579,13 +4579,19 @@ namespace {
// No applicable impl
// - TODO: This should really only fire when there isn't an impl. But it currently fires when _
DEBUG("No impl of " << v.trait << context.m_ivars.fmt(v.params) << " for " << context.m_ivars.fmt_type(v.impl_ty));
- //bool is_known = !context.get_type(v.impl_ty).m_data.is_Infer();
- bool is_known = !context.m_ivars.type_contains_ivars(v.impl_ty);
- for(const auto& t : v.params.m_types)
- is_known &= !context.m_ivars.type_contains_ivars(t);
+
+ const auto& ty = context.get_type(v.impl_ty);
+ bool is_known = !ty.m_data.is_Infer() && !(ty.m_data.is_Path() && ty.m_data.as_Path().binding.is_Unbound());
+ //bool is_known = !context.m_ivars.type_contains_ivars(v.impl_ty);
+ //for(const auto& t : v.params.m_types)
+ // is_known &= !context.m_ivars.type_contains_ivars(t);
if( is_known ) {
ERROR(sp, E0000, "Failed to find an impl of " << v.trait << context.m_ivars.fmt(v.params) << " for " << context.m_ivars.fmt_type(v.impl_ty));
}
+
+ //if( v.trait == context.m_crate.get_lang_item_path(sp, "unsize") )
+ //{
+ //}
return false;
}
else if( count == 1 ) {
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp
index ccedfb07..500f6b79 100644
--- a/src/hir_typeck/helpers.cpp
+++ b/src/hir_typeck/helpers.cpp
@@ -1897,30 +1897,40 @@ bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::Simple
assoc_info = &pe;
)
)
+
+ if( m_ivars.get_type(type).m_data.is_Infer() )
+ return false;
// TODO: A bound can imply something via its associated types. How deep can this go?
// E.g. `T: IntoIterator<Item=&u8>` implies `<T as IntoIterator>::IntoIter : Iterator<Item=&u8>`
return this->iterate_bounds([&](const auto& b) {
TU_IFLET(::HIR::GenericBound, b, TraitBound, e,
const auto& b_params = e.trait.m_path.m_params;
+
+ auto cmp = e.type .compare_with_placeholders(sp, type, m_ivars.callback_resolve_infer());
+ if( cmp == ::HIR::Compare::Unequal )
+ return false;
+
+ if( e.trait.m_path.m_path == trait ) {
+ // Check against `params`
+ DEBUG("Checking " << params << " vs " << b_params);
+ auto ord = cmp;
+ ord &= this->compare_pp(sp, b_params, params);
+ if( ord == ::HIR::Compare::Unequal )
+ return false;
+ if( ord == ::HIR::Compare::Fuzzy ) {
+ DEBUG("Fuzzy match");
+ }
+ // Hand off to the closure, and return true if it does
+ // TODO: The type bounds are only the types that are specified.
+ if( callback( ImplRef(&e.type, &e.trait.m_path.m_params, &e.trait.m_type_bounds), ord) ) {
+ return true;
+ }
+ }
+
// TODO: Allow fuzzy equality?
- if( e.type == type )
+ if( cmp == ::HIR::Compare::Equal )
{
- if( e.trait.m_path.m_path == trait ) {
- // Check against `params`
- DEBUG("Checking " << params << " vs " << b_params);
- auto ord = this->compare_pp(sp, b_params, params);
- if( ord == ::HIR::Compare::Unequal )
- return false;
- if( ord == ::HIR::Compare::Fuzzy ) {
- DEBUG("Fuzzy match");
- }
- // Hand off to the closure, and return true if it does
- // TODO: The type bounds are only the types that are specified.
- if( callback( ImplRef(&e.type, &e.trait.m_path.m_params, &e.trait.m_type_bounds), ord) ) {
- return true;
- }
- }
// HACK: The wrapping closure takes associated types from this bound and applies them to the returned set
// - XXX: This is actually wrong (false-positive) in many cases. FIXME
bool rv = this->find_named_trait_in_trait(sp,
@@ -2416,6 +2426,10 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
const auto& real_trait_path = real_trait.m_path;
DEBUG("[find_trait_impls_crate] - bound mono " << real_type << " : " << real_trait);
bool found_fuzzy_match = false;
+ if( real_type.m_data.is_Path() && real_type.m_data.as_Path().binding.is_Unbound() ) {
+ DEBUG("- Bounded type is unbound UFCS, assuming fuzzy match");
+ found_fuzzy_match = true;
+ }
auto rv = this->find_trait_impls(sp, real_trait_path.m_path, real_trait_path.m_params, real_type, [&](auto impl, auto impl_cmp) {
auto cmp = impl_cmp;
for(const auto& assoc_bound : real_trait.m_type_bounds) {
diff --git a/src/main.cpp b/src/main.cpp
index b8ba315d..24a5ad57 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -312,6 +312,10 @@ int main(int argc, char *argv[])
ConvertHIR_ConstantEvaluate(*hir_crate);
});
+ CompilePhaseV("Dump HIR", [&]() {
+ ::std::ofstream os (FMT(params.outfile << "_2_hir.rs"));
+ HIR_Dump( os, *hir_crate );
+ });
// === Type checking ===
// - This can recurse and call the MIR lower to evaluate constants