diff options
-rw-r--r-- | src/hir/type.cpp | 76 | ||||
-rw-r--r-- | src/hir/type.hpp | 6 | ||||
-rw-r--r-- | src/hir_typeck/expr.cpp | 35 |
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; } } |