diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hir/hir.hpp | 2 | ||||
-rw-r--r-- | src/hir/type.cpp | 64 | ||||
-rw-r--r-- | src/hir/type.hpp | 6 | ||||
-rw-r--r-- | src/hir_typeck/expr.cpp | 95 |
4 files changed, 132 insertions, 35 deletions
diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index c6dec6c8..3447aaa0 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -204,8 +204,6 @@ TAGGED_UNION(ValueItem, Import, // -------------------------------------------------------------------- -typedef ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> t_cb_resolve_type; - class TypeImpl { public: diff --git a/src/hir/type.cpp b/src/hir/type.cpp index dfaf9d1d..e4931dbf 100644 --- a/src/hir/type.cpp +++ b/src/hir/type.cpp @@ -241,17 +241,38 @@ bool ::HIR::TypeRef::operator==(const ::HIR::TypeRef& x) const ) throw ""; } -void ::HIR::TypeRef::match_generics(const Span& sp, const ::HIR::TypeRef& x, ::std::function<void(unsigned int, const ::HIR::TypeRef&)> callback) 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) + { + if( t.m_types.size() != x.m_types.size() ) { + return false; + } + + 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 ); + } + + return true; + } +} + +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( m_data.is_Infer() ) { - BUG(sp, ""); + BUG(sp, "Encountered '_' as this - " << *this); } if( m_data.is_Generic() ) { - callback(m_data.as_Generic().binding, x); + callback(m_data.as_Generic().binding, x_in); return ; } + const auto& x = (x_in.m_data.is_Infer() || x_in.m_data.is_Generic() ? resolve_placeholder(x_in) : x_in); if( m_data.tag() != x.m_data.tag() ) { - BUG(sp, ""); + BUG(sp, "TypeRef::match_generics with mismatched forms - " << *this << " and " << x); } TU_MATCH(::HIR::TypeRef::Data, (m_data, x.m_data), (te, xe), (Infer, throw "";), @@ -261,29 +282,50 @@ void ::HIR::TypeRef::match_generics(const Span& sp, const ::HIR::TypeRef& x, ::s (Diverge, ), (Path, - TODO(sp, "Path"); + if( te.path.m_data.tag() != xe.path.m_data.tag() ) { + BUG(sp, "TypeRef::match_generics with mismatched forms - " << *this << " and " << x); + } + 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); + } + 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); + } + ), + (UfcsKnown, + TODO(sp, "Path UfcsKnown - " << *this << " and " << x); + ), + (UfcsUnknown, + TODO(sp, "Path UfcsUnknown - " << *this << " and " << x); + ), + (UfcsInherent, + TODO(sp, "Path UfcsInherent - " << *this << " and " << x); + ) + ) ), (TraitObject, TODO(sp, "TraitObject"); ), (Array, - te.inner->match_generics( sp, *xe.inner, callback ); + te.inner->match_generics( sp, *xe.inner, resolve_placeholder, callback ); ), (Slice, - te.inner->match_generics( sp, *xe.inner, callback ); + te.inner->match_generics( sp, *xe.inner, resolve_placeholder, callback ); ), (Tuple, if( te.size() != xe.size() ) { - BUG(sp, ""); + BUG(sp, "TypeRef::match_generics with mismatched forms - " << *this << " and " << x); } for(unsigned int i = 0; i < te.size(); i ++ ) - te[i].match_generics( sp, xe[i], callback ); + te[i].match_generics( sp, xe[i], resolve_placeholder, callback ); ), (Pointer, - te.inner->match_generics( sp, *xe.inner, callback ); + te.inner->match_generics( sp, *xe.inner, resolve_placeholder, callback ); ), (Borrow, - te.inner->match_generics( sp, *xe.inner, callback ); + te.inner->match_generics( sp, *xe.inner, resolve_placeholder, callback ); ), (Function, TODO(sp, "Function"); diff --git a/src/hir/type.hpp b/src/hir/type.hpp index 75cf4485..adb48df0 100644 --- a/src/hir/type.hpp +++ b/src/hir/type.hpp @@ -15,6 +15,8 @@ class Enum; class TypeRef; +typedef ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> t_cb_resolve_type; + enum class InferClass { None, @@ -168,7 +170,7 @@ public: // Match generics in `this` with types from `x` // 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, ::std::function<void(unsigned int, const ::HIR::TypeRef&)> callback) const; + 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; enum Compare { Equal, @@ -176,7 +178,7 @@ public: Unequal, }; // 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, ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> resolve_placeholder) const; + Compare compare_with_paceholders(const Span& sp, const ::HIR::TypeRef& x, t_cb_resolve_type resolve_placeholder) const; }; extern ::std::ostream& operator<<(::std::ostream& os, const ::HIR::TypeRef& ty); diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp index 19dfdda7..5446a299 100644 --- a/src/hir_typeck/expr.cpp +++ b/src/hir_typeck/expr.cpp @@ -1117,8 +1117,11 @@ namespace { ::HIR::TypeRef expand_associated_types(const Span& sp, ::HIR::TypeRef input) const { + TRACE_FUNCTION_F(input); TU_MATCH(::HIR::TypeRef::Data, (input.m_data), (e), (Infer, + //auto& ty = this->get_type(input); + //return ty.clone(); ), (Diverge, ), @@ -1127,27 +1130,89 @@ namespace { (Path, TU_MATCH(::HIR::Path::Data, (e.path.m_data), (e2), (Generic, + for(auto& arg : e2.m_params.m_types) + arg = expand_associated_types(sp, mv$(arg)); ), (UfcsInherent, TODO(sp, "Path - UfcsInherent - " << e.path); ), (UfcsKnown, + DEBUG("Checking UFCS types for " << e.path); // HACK - Shortcut to prevent expensive search if the type is a parameter if( e2.type->m_data.is_Generic() ) { return input; } + *e2.type = expand_associated_types(sp, mv$(*e2.type)); + // Search for a matching trait impl const ::HIR::TraitImpl* impl_ptr = nullptr; - bool rv = this->m_crate.find_trait_impls(e2.trait.m_path, *e2.type, - [&](const auto& ty)->const auto& { + ::std::vector< const ::HIR::TypeRef*> impl_args; + + auto cb_get_infer = [&](const auto& ty)->const auto& { if( ty.m_data.is_Infer() ) return this->get_type(ty); else return ty; - }, + }; + + bool rv = this->m_crate.find_trait_impls(e2.trait.m_path, *e2.type, cb_get_infer, [&](const auto& impl) { - DEBUG("Found impl - " << e2.trait.m_path << impl.m_trait_args << " for " << impl.m_type); + DEBUG("Found impl" << impl.m_params.fmt_args() << " " << e2.trait.m_path << impl.m_trait_args << " for " << impl.m_type); + // - Populate the impl's type arguments + impl_args.clear(); + impl_args.resize( impl.m_params.m_types.size() ); + // - Match with `Self` + auto cb_res = [&](unsigned int slot, const ::HIR::TypeRef& ty) { + DEBUG("Set " << slot << " = " << ty); + if( slot >= impl_args.size() ) { + BUG(sp, "Impl parameter out of range - " << slot); + } + auto& slot_r = impl_args.at(slot); + if( slot_r != nullptr ) { + DEBUG("- Match " << slot_r << " == " << ty); + } + else { + slot_r = &ty; + } + }; + impl.m_type.match_generics(sp, *e2.type, cb_get_infer, cb_res); + for( unsigned int i = 0; i < impl.m_trait_args.m_types.size(); i ++ ) + { + impl.m_trait_args.m_types[i].match_generics(sp, e2.trait.m_params.m_types.at(i), cb_get_infer, cb_res); + } + for( const auto& bound : impl.m_params.m_bounds ) + { + TU_MATCH_DEF(::HIR::GenericBound, (bound), (be), + ( + ), + (TraitBound, + bool rv2 = this->m_crate.find_trait_impls(be.trait.m_path.m_path, be.type, + [&](const auto& ty)->const auto& { + if( ty.m_data.is_Infer() ) + return this->get_type(ty); + else TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Generic, e, + assert( impl_args.at(e.binding) ); + return *impl_args.at(e.binding); + ) + else + return ty; + }, + [&](const auto& impl) { + DEBUG("- Bound " << be.type << " : " << be.trait.m_path << " satisfied by impl" << impl.m_params.fmt_args()); + // TODO: Recursively check + return true; + } + ); + if( !rv2 ) { + DEBUG("- Bound " << be.type << " : " << be.trait.m_path << " failed"); + return false; + } + ) + ) + } + // TODO: Bounds check? (here or elsewhere?) + // - Need to check bounds before picking this impl, because the bound could be preventing false matches if( impl.m_trait_args.m_types.size() > 0 ) { TODO(sp, "Check trait type parameters in expand_associated_types"); @@ -1160,19 +1225,6 @@ namespace { // An impl was found: assert(impl_ptr); - // - Populate the impl's type arguments - ::std::vector< const ::HIR::TypeRef*> impl_args; - impl_args.resize( impl_ptr->m_params.m_types.size() ); - - // 1. Match impl_ptr->m_type with *e2.type - impl_ptr->m_type.match_generics(sp, *e2.type, [&](unsigned int slot, const ::HIR::TypeRef& ty) { - DEBUG("Set " << slot << " = " << ty); - if( slot >= impl_args.size() ) { - BUG(sp, "Impl parameter out of range - " << slot); - } - impl_args.at(slot) = &ty; - }); - // 2. Match impl_ptr->m_trait_args with e2.trait.m_params // - Monomorphise the output type auto new_type = monomorphise_type_with(sp, impl_ptr->m_types.at( e2.item ), [&](const auto& ty)->const auto& { @@ -1180,7 +1232,7 @@ namespace { assert(ge.binding < impl_args.size()); return *impl_args[ge.binding]; }); - DEBUG("Converted UfcsKnown - " << e.path << " = " << new_type); + DEBUG("Converted UfcsKnown - " << e.path << " = " << new_type << " using " << e2.item << " = " << impl_ptr->m_types.at( e2.item )); return new_type; ), (UfcsUnknown, @@ -1229,7 +1281,6 @@ namespace { for(const auto& b : p->m_bounds) { TU_IFLET(::HIR::GenericBound, b, TraitBound, e, - DEBUG("Bound " << e.type << " : " << e.trait.m_path); if( e.type == type && e.trait.m_path.m_path == trait ) { if( callback(e.trait.m_path.m_params) ) { return true; @@ -1352,6 +1403,7 @@ namespace { } } while( current_ty ); // Dereference failed! This is a hard error (hitting _ is checked above and returns ~0) + this->dump(); TODO(sp, "Error when no method could be found, but type is known - (: " << top_ty << ")." << method_name); } @@ -2203,7 +2255,7 @@ namespace { //} //else { //} - TODO(sp, "Monomorphise for trait method - " << ge.name << " " << ge.binding); + TODO(sp, "Monomorphise for trait method "<<path<<" - Param " << ge.name << " (" << ge.binding << ")"); }; ), (UfcsUnknown, @@ -2280,6 +2332,9 @@ namespace { this->context.apply_equality(sp, arg_ty, arg_expr_ptr->m_res_type, &arg_expr_ptr); } + // HACK: Expand UFCS again + arg_types.back() = this->context.expand_associated_types(sp, mv$(arg_types.back())); + DEBUG("RV " << arg_types.back()); this->context.apply_equality(sp, res_type, arg_types.back(), &this_node_ptr); } |