diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hir/path.hpp | 14 | ||||
-rw-r--r-- | src/hir/type.cpp | 69 | ||||
-rw-r--r-- | src/hir/type.hpp | 1 | ||||
-rw-r--r-- | src/hir_typeck/expr.cpp | 22 | ||||
-rw-r--r-- | src/hir_typeck/expr_context.cpp | 25 |
5 files changed, 87 insertions, 44 deletions
diff --git a/src/hir/path.hpp b/src/hir/path.hpp index 177a5ada..eb88317d 100644 --- a/src/hir/path.hpp +++ b/src/hir/path.hpp @@ -19,6 +19,20 @@ enum Compare { Fuzzy, Unequal, }; +static inline Compare& operator &=(Compare& x, const Compare& y) { + if(x == Compare::Unequal) { + } + else if(y == Compare::Unequal) { + x = Compare::Unequal; + } + else if(y == Compare::Fuzzy) { + x = Compare::Fuzzy; + } + else { + // keep as-is + } + return x; +} /// Simple path - Absolute with no generic parameters struct SimplePath diff --git a/src/hir/type.cpp b/src/hir/type.cpp index fd082606..998314fa 100644 --- a/src/hir/type.cpp +++ b/src/hir/type.cpp @@ -265,18 +265,21 @@ bool ::HIR::TypeRef::operator==(const ::HIR::TypeRef& x) const namespace { - bool match_generics_pp(const Span& sp, const ::HIR::PathParams& t, const ::HIR::PathParams& x, ::HIR::t_cb_resolve_type resolve_placeholder, ::HIR::t_cb_match_generics callback) + ::HIR::Compare match_generics_pp(const Span& sp, const ::HIR::PathParams& t, const ::HIR::PathParams& x, ::HIR::t_cb_resolve_type resolve_placeholder, ::HIR::t_cb_match_generics callback) { if( t.m_types.size() != x.m_types.size() ) { - return false; + return ::HIR::Compare::Unequal; } + auto rv = ::HIR::Compare::Equal; for(unsigned int i = 0; i < t.m_types.size(); i ++ ) { - t.m_types[i].match_generics( sp, x.m_types[i], resolve_placeholder, callback ); + rv &= t.m_types[i].match_test_generics_fuzz( sp, x.m_types[i], resolve_placeholder, callback ); + if( rv == ::HIR::Compare::Unequal ) + return rv; } - return true; + return rv; } } @@ -289,12 +292,17 @@ void ::HIR::TypeRef::match_generics(const Span& sp, const ::HIR::TypeRef& x_in, } bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x_in, t_cb_resolve_type resolve_placeholder, t_cb_match_generics callback) const { + return this->match_test_generics_fuzz(sp, x_in, resolve_placeholder, callback) == ::HIR::Compare::Equal; +} +::HIR::Compare HIR::TypeRef::match_test_generics_fuzz(const Span& sp, const ::HIR::TypeRef& x_in, t_cb_resolve_type resolve_placeholder, t_cb_match_generics callback) const +{ if( m_data.is_Infer() ) { BUG(sp, "Encountered '_' as this - " << *this); } if( m_data.is_Generic() ) { callback(m_data.as_Generic().binding, x_in); - return true; + // - TODO: Allow callback to return a match form + return Compare::Equal; } const auto& x = (x_in.m_data.is_Infer() || x_in.m_data.is_Generic() ? resolve_placeholder(x_in) : x_in); TU_IFLET(::HIR::TypeRef::Data, x.m_data, Infer, xe, @@ -303,7 +311,7 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x case ::HIR::InferClass::None: // - If right is generic infer, assume it's good //return true; - return false; + return Compare::Fuzzy; case ::HIR::InferClass::Integer: TU_IFLET(::HIR::TypeRef::Data, m_data, Primitive, te, switch(te) @@ -313,10 +321,11 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x case ::HIR::CoreType::I32: case ::HIR::CoreType::U32: case ::HIR::CoreType::I64: case ::HIR::CoreType::U64: case ::HIR::CoreType::Isize: case ::HIR::CoreType::Usize: - return true; + return Compare::Fuzzy; + //return true; default: DEBUG("- Fuzz fail"); - break; + return Compare::Unequal; } ) break; @@ -326,10 +335,11 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x { case ::HIR::CoreType::F32: case ::HIR::CoreType::F64: - return true; + return Compare::Fuzzy; + //return true; default: DEBUG("- Fuzz fail"); - break; + return Compare::Unequal; } ) break; @@ -337,29 +347,27 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x ) if( m_data.tag() != x.m_data.tag() ) { DEBUG("- Tag mismatch " << *this << " and " << x); - return false; + return Compare::Unequal; } TU_MATCH(::HIR::TypeRef::Data, (m_data, x.m_data), (te, xe), (Infer, throw "";), (Generic, throw "";), (Primitive, - return true; + return (te == xe ? Compare::Equal : Compare::Unequal); ), (Diverge, - return true; + return Compare::Equal; ), (Path, if( te.path.m_data.tag() != xe.path.m_data.tag() ) { - return false; + return Compare::Unequal; } TU_MATCH(::HIR::Path::Data, (te.path.m_data, xe.path.m_data), (tpe, xpe), (Generic, if( tpe.m_path != xpe.m_path ) { - return false; - } - if( !match_generics_pp(sp, tpe.m_params, xpe.m_params, resolve_placeholder, callback) ) { - return false; + return Compare::Unequal; } + return match_generics_pp(sp, tpe.m_params, xpe.m_params, resolve_placeholder, callback); ), (UfcsKnown, TODO(sp, "Path UfcsKnown - " << *this << " and " << x); @@ -376,27 +384,32 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x TODO(sp, "TraitObject"); ), (Array, - return te.inner->match_test_generics( sp, *xe.inner, resolve_placeholder, callback ); + return te.inner->match_test_generics_fuzz( sp, *xe.inner, resolve_placeholder, callback ); ), (Slice, - return te.inner->match_test_generics( sp, *xe.inner, resolve_placeholder, callback ); + return te.inner->match_test_generics_fuzz( sp, *xe.inner, resolve_placeholder, callback ); ), (Tuple, if( te.size() != xe.size() ) { - return false; + return Compare::Unequal; + } + auto rv = Compare::Equal; + for(unsigned int i = 0; i < te.size(); i ++ ) { + rv &= te[i].match_test_generics_fuzz( sp, xe[i], resolve_placeholder, callback ); + if(rv == Compare::Unequal) + return Compare::Unequal; } - for(unsigned int i = 0; i < te.size(); i ++ ) - if( !te[i].match_test_generics( sp, xe[i], resolve_placeholder, callback ) ) return false; + return rv; ), (Pointer, if( te.type != xe.type ) - return false; - return te.inner->match_test_generics( sp, *xe.inner, resolve_placeholder, callback ); + return Compare::Unequal; + return te.inner->match_test_generics_fuzz( sp, *xe.inner, resolve_placeholder, callback ); ), (Borrow, if( te.type != xe.type ) - return false; - return te.inner->match_test_generics( sp, *xe.inner, resolve_placeholder, callback ); + return Compare::Unequal; + return te.inner->match_test_generics_fuzz( sp, *xe.inner, resolve_placeholder, callback ); ), (Function, TODO(sp, "Function"); @@ -405,7 +418,7 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x TODO(sp, "Closure"); ) ) - return true; + throw ""; } ::HIR::TypeRef::TypePathBinding HIR::TypeRef::TypePathBinding::clone() const { diff --git a/src/hir/type.hpp b/src/hir/type.hpp index 27757d45..02effd9c 100644 --- a/src/hir/type.hpp +++ b/src/hir/type.hpp @@ -200,6 +200,7 @@ public: void match_generics(const Span& sp, const ::HIR::TypeRef& x, t_cb_resolve_type resolve_placeholder, ::std::function<void(unsigned int, const ::HIR::TypeRef&)> callback) const; bool match_test_generics(const Span& sp, const ::HIR::TypeRef& x, t_cb_resolve_type resolve_placeholder, ::std::function<void(unsigned int, const ::HIR::TypeRef&)> callback) const; + ::HIR::Compare match_test_generics_fuzz(const Span& sp, const ::HIR::TypeRef& x_in, t_cb_resolve_type resolve_placeholder, t_cb_match_generics callback) const; // Compares this type with another, using `resolve_placeholder` to get replacements for generics/infers in `x` Compare compare_with_placeholders(const Span& sp, const ::HIR::TypeRef& x, t_cb_resolve_type resolve_placeholder) const; diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp index 2a0d7b60..07dc00b4 100644 --- a/src/hir_typeck/expr.cpp +++ b/src/hir_typeck/expr.cpp @@ -698,13 +698,13 @@ namespace typeck { trait_path_pp.m_types.push_back( ty_right.clone() ); + ::HIR::TypeRef possible_right_type; unsigned int count = 0; bool rv = this->context.find_trait_impls(node.span(), trait_path,trait_path_pp, ty_left, [&](const auto& args, const auto& a_types) { assert( args.m_types.size() == 1 ); const auto& impl_right = args.m_types[0]; - TODO(node.span(), "Check " << impl_right << " vs " << ty_right); - + // NOTE: `find_trait_impls` has already done this (and did it better)! Need to get that info off it auto cmp = impl_right.compare_with_placeholders(node.span(), ty_right, this->context.callback_resolve_infer()); if( cmp == ::HIR::Compare::Unequal) return false; @@ -712,18 +712,26 @@ namespace typeck { if( cmp == ::HIR::Compare::Equal ) { return true; } - //DEBUG("TODO: Handle fuzzy match index operator " << impl_index); + + possible_right_type = impl_right.clone(); return false; }); - this->context.dump(); - TODO(node.span(), "Search for implementation of " << trait_path << "<" << ty_right << "> for " << ty_left); - if( rv ) { + // True - Concrete impl located, both types should be fully known + } + else if( count > 1 ) { + // Multiple options - Leave as-is } - else if( count > 0 ) { + else if( count == 1 ) { + // Only possible match, assume it's the correct one. + assert( !possible_right_type.m_data.is_Infer() ); + this->context.apply_equality( node.span(), ty_right, possible_right_type ); } else { + // TODO: is this an error? + this->context.dump(); + TODO(node.span(), "Search for implementation of " << trait_path << "<" << ty_right << "> for " << ty_left); } } else { diff --git a/src/hir_typeck/expr_context.cpp b/src/hir_typeck/expr_context.cpp index e424d08a..8bb60835 100644 --- a/src/hir_typeck/expr_context.cpp +++ b/src/hir_typeck/expr_context.cpp @@ -1400,8 +1400,11 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR // TODO: Check `types` return true; }); - if(!succ) - ERROR(sp, E0000, "Trait " << e.m_trait << " isn't implemented for " << right_inner_res ); + if(!succ) { + // XXX: Debugging - Resolves to the correct type in a failing case + auto ty2 = this->expand_associated_types(sp, this->expand_associated_types(sp, right_inner_res.clone()) ); + ERROR(sp, E0000, "Trait " << e.m_trait << " isn't implemented for " << right_inner_res << "(" << FmtType(*this, right_inner_res) << " - "<<ty2<<")" ); + } for(const auto& marker : e.m_markers) { TODO(sp, "Check for marker trait impls ("<<marker<<") when unsizing to " << left_inner_res << " from " << right_inner_res); @@ -1955,8 +1958,7 @@ bool typeck::TypecheckContext::find_trait_impls_crate(const Span& sp, [&](const auto& impl) { DEBUG("[find_trait_impls_crate] Found impl" << impl.m_params.fmt_args() << " " << trait << impl.m_trait_args << " for " << impl.m_type); // Compare with `params` - // - TODO: Would prefer a fuzzy compare, but match is easiest - bool fail = false; + auto match = ::HIR::Compare::Equal; ::std::vector< const ::HIR::TypeRef*> impl_params; impl_params.resize( impl.m_params.m_types.size() ); auto cb = [&](auto idx, const auto& ty) { @@ -1966,17 +1968,19 @@ bool typeck::TypecheckContext::find_trait_impls_crate(const Span& sp, impl_params[idx] = &ty; } else if( *impl_params[idx] != ty ) { - fail = true; + // Strict equality is OK, as all types should be sane + // - TODO: What if there's an un-expanded associated? + match = ::HIR::Compare::Unequal; } else { } }; assert( impl.m_trait_args.m_types.size() == params.m_types.size() ); // TODO: Use a fuzzy-able generic match - fail |= !impl.m_type.match_test_generics(sp, type , this->callback_resolve_infer(), cb); + match &= impl.m_type.match_test_generics_fuzz(sp, type , this->callback_resolve_infer(), cb); for(unsigned int i = 0; i < impl.m_trait_args.m_types.size(); i ++) - fail |= !impl.m_trait_args.m_types[i].match_test_generics(sp, params.m_types[i], this->callback_resolve_infer(), cb); - if( fail ) { + match &= impl.m_trait_args.m_types[i].match_test_generics_fuzz(sp, params.m_types[i], this->callback_resolve_infer(), cb); + if( match == ::HIR::Compare::Unequal ) { DEBUG("- Failed to match parameters - " << impl.m_trait_args << " != " << params); return false; } @@ -2048,7 +2052,10 @@ bool typeck::TypecheckContext::find_trait_impls_crate(const Span& sp, } DEBUG("[find_trait_impls_crate] callback(args=" << args_mono << ", assoc={" << types << "})"); - return callback(args_mono, types); + //if( match == ::HIR::Compare::Fuzzy ) { + // TODO(sp, "- Pass on fuzzy match status"); + //} + return callback(args_mono, types/*, (match == ::HIR::Compare::Fuzzy)*/); } ); } |