summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hir/type.cpp76
-rw-r--r--src/hir/type.hpp6
-rw-r--r--src/hir_typeck/expr.cpp35
3 files changed, 97 insertions, 20 deletions
diff --git a/src/hir/type.cpp b/src/hir/type.cpp
index 489cf2a5..8d62de90 100644
--- a/src/hir/type.cpp
+++ b/src/hir/type.cpp
@@ -264,10 +264,8 @@ bool ::HIR::TypeRef::operator==(const ::HIR::TypeRef& x) const
}
-typedef ::std::function<void(unsigned int, const ::HIR::TypeRef&)> t_cb_match_generics;
-
namespace {
- bool match_generics_pp(const Span& sp, const ::HIR::PathParams& t, const ::HIR::PathParams& x, ::HIR::t_cb_resolve_type resolve_placeholder, t_cb_match_generics callback)
+ 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)
{
if( t.m_types.size() != x.m_types.size() ) {
return false;
@@ -282,37 +280,80 @@ namespace {
}
}
-void ::HIR::TypeRef::match_generics(const Span& sp, const ::HIR::TypeRef& x_in, t_cb_resolve_type resolve_placeholder, t_cb_match_generics callback) const
+void ::HIR::TypeRef::match_generics(const Span& sp, const ::HIR::TypeRef& x_in, t_cb_resolve_type resolve_placeholder, t_cb_match_generics callback) const {
+ if( match_test_generics(sp, x_in, resolve_placeholder, callback) ) {
+ }
+ else {
+ BUG(sp, "TypeRef::match_generics with mismatched forms - " << *this << " and " << 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
{
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 ;
+ return true;
}
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,
+ switch(xe.ty_class)
+ {
+ case ::HIR::InferClass::None:
+ break;
+ case ::HIR::InferClass::Integer:
+ TU_IFLET(::HIR::TypeRef::Data, m_data, Primitive, te,
+ switch(te)
+ {
+ case ::HIR::CoreType::I8: case ::HIR::CoreType::U8:
+ case ::HIR::CoreType::I16: case ::HIR::CoreType::U16:
+ 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;
+ default:
+ break;
+ }
+ )
+ break;
+ case ::HIR::InferClass::Float:
+ TU_IFLET(::HIR::TypeRef::Data, m_data, Primitive, te,
+ switch(te)
+ {
+ case ::HIR::CoreType::F32:
+ case ::HIR::CoreType::F64:
+ return true;
+ default:
+ break;
+ }
+ )
+ break;
+ }
+ )
if( m_data.tag() != x.m_data.tag() ) {
- BUG(sp, "TypeRef::match_generics with mismatched forms - " << *this << " and " << x);
+ return false;
}
TU_MATCH(::HIR::TypeRef::Data, (m_data, x.m_data), (te, xe),
(Infer, throw "";),
(Generic, throw "";),
(Primitive,
+ return true;
),
(Diverge,
+ return true;
),
(Path,
if( te.path.m_data.tag() != xe.path.m_data.tag() ) {
- BUG(sp, "TypeRef::match_generics with mismatched forms - " << *this << " and " << x);
+ return false;
}
TU_MATCH(::HIR::Path::Data, (te.path.m_data, xe.path.m_data), (tpe, xpe),
(Generic,
if( tpe.m_path != xpe.m_path ) {
- BUG(sp, "TypeRef::match_generics with mismatched forms - " << *this << " and " << x);
+ return false;
}
if( !match_generics_pp(sp, tpe.m_params, xpe.m_params, resolve_placeholder, callback) ) {
- BUG(sp, "TypeRef::match_generics with mismatched forms - " << *this << " and " << x);
+ return false;
}
),
(UfcsKnown,
@@ -330,23 +371,27 @@ void ::HIR::TypeRef::match_generics(const Span& sp, const ::HIR::TypeRef& x_in,
TODO(sp, "TraitObject");
),
(Array,
- te.inner->match_generics( sp, *xe.inner, resolve_placeholder, callback );
+ return te.inner->match_test_generics( sp, *xe.inner, resolve_placeholder, callback );
),
(Slice,
- te.inner->match_generics( sp, *xe.inner, resolve_placeholder, callback );
+ return te.inner->match_test_generics( sp, *xe.inner, resolve_placeholder, callback );
),
(Tuple,
if( te.size() != xe.size() ) {
- BUG(sp, "TypeRef::match_generics with mismatched forms - " << *this << " and " << x);
+ return false;
}
for(unsigned int i = 0; i < te.size(); i ++ )
- te[i].match_generics( sp, xe[i], resolve_placeholder, callback );
+ if( !te[i].match_test_generics( sp, xe[i], resolve_placeholder, callback ) ) return false;
),
(Pointer,
- te.inner->match_generics( sp, *xe.inner, resolve_placeholder, callback );
+ if( te.type != xe.type )
+ return false;
+ return te.inner->match_test_generics( sp, *xe.inner, resolve_placeholder, callback );
),
(Borrow,
- te.inner->match_generics( sp, *xe.inner, resolve_placeholder, callback );
+ if( te.type != xe.type )
+ return false;
+ return te.inner->match_test_generics( sp, *xe.inner, resolve_placeholder, callback );
),
(Function,
TODO(sp, "Function");
@@ -355,6 +400,7 @@ void ::HIR::TypeRef::match_generics(const Span& sp, const ::HIR::TypeRef& x_in,
TODO(sp, "Closure");
)
)
+ return true;
}
namespace {
diff --git a/src/hir/type.hpp b/src/hir/type.hpp
index 3ee4e65c..b09d3f40 100644
--- a/src/hir/type.hpp
+++ b/src/hir/type.hpp
@@ -12,9 +12,11 @@ namespace HIR {
class Struct;
class Enum;
+struct ExprNode_Closure;
class TypeRef;
-struct ExprNode_Closure;
+
+typedef ::std::function<void(unsigned int, const ::HIR::TypeRef&)> t_cb_match_generics;
enum class InferClass
{
@@ -176,6 +178,8 @@ public:
// Raises a bug against `sp` if there is a form mismatch or `this` has an infer
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;
+
// Compares this type with another, using `resolve_placeholder` to get replacements for generics/infers in `x`
Compare compare_with_paceholders(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 7e81a878..667129bc 100644
--- a/src/hir_typeck/expr.cpp
+++ b/src/hir_typeck/expr.cpp
@@ -682,14 +682,41 @@ namespace typeck {
const ::HIR::TraitImpl* impl_ptr = nullptr;
unsigned int count = 0;
const auto& ops_trait = this->context.m_crate.get_lang_item_path(node.span(), item_name);
+ DEBUG("Searching for impl " << ops_trait << "< " << ty_left << "> for " << ty_right);
bool found_exact = this->context.m_crate.find_trait_impls(ops_trait, ty_left, this->context.callback_resolve_infer(),
[&](const auto& impl) {
// TODO: Check how concretely the types matched
assert( impl.m_trait_args.m_types.size() == 1 );
const auto& arg_type = impl.m_trait_args.m_types[0];
- // TODO: What if the trait arguments depend on a generic parameter?
- if( monomorphise_type_needed(arg_type) )
- TODO(node.span(), "Compare ops trait type when it contains generics - " << arg_type);
+
+ // 1. Match arg_type with ty_right into impl block params
+ bool fail = false;
+ ::std::vector< const ::HIR::TypeRef*> impl_params;
+ impl_params.resize( impl.m_params.m_types.size() );
+ auto cb =[&](auto idx, const auto& ty) {
+ assert( idx < impl_params.size() );
+ if( impl_params[idx] ) {
+ if( *impl_params[idx] != ty ) {
+ fail = true;
+ }
+ }
+ else {
+ impl_params[idx] = &ty;
+ }
+ };
+ fail |= !arg_type .match_test_generics(node.span(), ty_right, this->context.callback_resolve_infer(), cb);
+ fail |= !impl.m_type.match_test_generics(node.span(), ty_left , this->context.callback_resolve_infer(), cb);
+ for(const auto& ty : impl_params)
+ assert( ty );
+ if( fail ) {
+ DEBUG("- (fail) impl" << impl.m_params.fmt_args() << " " << ops_trait << "<" << arg_type << "> for " << impl.m_type);
+ return false;
+ }
+ // TODO: handle a generic somehow
+ if( monomorphise_type_needed(arg_type) ) {
+ return true;
+ //TODO(node.span(), "Compare ops trait type when it contains generics - " << arg_type << " == " << ty_right);
+ }
auto cmp = arg_type.compare_with_paceholders(node.span(), ty_right, this->context.callback_resolve_infer());
if( cmp == ::HIR::Compare::Unequal ) {
return false;
@@ -701,7 +728,7 @@ namespace typeck {
return true;
}
else {
- DEBUG("Operator fuzzy exact match - '"<<item_name<<"' - " << arg_type << " == " << ty_right);
+ DEBUG("Operator impl fuzzy match - '"<<item_name<<"' - " << arg_type << " == " << ty_right);
return false;
}
}