summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hir/path.hpp14
-rw-r--r--src/hir/type.cpp69
-rw-r--r--src/hir/type.hpp1
-rw-r--r--src/hir_typeck/expr.cpp22
-rw-r--r--src/hir_typeck/expr_context.cpp25
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)*/);
}
);
}