diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index 82634fbc..97b3f3de 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -549,7 +549,7 @@ class TypeImpl bool matches_type(const ::HIR::TypeRef& tr, t_cb_resolve_type ty_res) const; bool matches_type(const ::HIR::TypeRef& tr) const { - return matches_type(tr, [](const auto& x)->const auto&{ return x; }); + return matches_type(tr, ResolvePlaceholdersNop()); } }; @@ -579,7 +579,7 @@ class TraitImpl bool matches_type(const ::HIR::TypeRef& tr, t_cb_resolve_type ty_res) const; bool matches_type(const ::HIR::TypeRef& tr) const { - return matches_type(tr, [](const auto& x)->const auto&{ return x; }); + return matches_type(tr, ResolvePlaceholdersNop()); } bool more_specific_than(const TraitImpl& x) const; @@ -598,7 +598,7 @@ class MarkerImpl bool matches_type(const ::HIR::TypeRef& tr, t_cb_resolve_type ty_res) const; bool matches_type(const ::HIR::TypeRef& tr) const { - return matches_type(tr, [](const auto& x)->const auto&{ return x; }); + return matches_type(tr, ResolvePlaceholdersNop()); } }; diff --git a/src/hir/hir_ops.cpp b/src/hir/hir_ops.cpp index b5b0a23b..bc83b7a4 100644 --- a/src/hir/hir_ops.cpp +++ b/src/hir/hir_ops.cpp @@ -47,7 +47,7 @@ namespace { bool matches_type_int(const ::HIR::TypeRef& left, const ::HIR::TypeRef& right_in, ::HIR::t_cb_resolve_type ty_res, bool expand_generic) { assert(! left.data().is_Infer() ); - const auto& right = (right_in.data().is_Infer() ? ty_res(right_in) : right_in); + const auto& right = (right_in.data().is_Infer() ? ty_res.get_type(Span(), right_in) : right_in); if( right_in.data().is_Generic() ) expand_generic = false; @@ -823,7 +823,7 @@ bool ::HIR::TraitImpl::overlaps_with(const Crate& crate, const ::HIR::TraitImpl& // TODO: Detect `impl Foo for Bar` vs `impl Foo<&T> for Bar` // > Create values for impl params from the type, then check if the trait params are compatible // > Requires two lists, and telling which one to use by the end - auto cb_ident = [](const ::HIR::TypeRef& x)->const ::HIR::TypeRef& { return x; }; + auto cb_ident = ResolvePlaceholdersNop(); bool is_reversed = false; ImplTyMatcher matcher; matcher.reinit(this->m_params); @@ -926,10 +926,10 @@ bool ::HIR::TraitImpl::overlaps_with(const Crate& crate, const ::HIR::TraitImpl& } else { // Search the crate for an impl - bool rv = crate.find_trait_impls(trait.m_path.m_path, ty, [](const auto&t)->const auto&{ return t; }, [&](const ::HIR::TraitImpl& ti)->bool { + auto cb_ident = ResolvePlaceholdersNop(); + bool rv = crate.find_trait_impls(trait.m_path.m_path, ty, cb_ident, [&](const ::HIR::TraitImpl& ti)->bool { DEBUG("impl" << ti.m_params.fmt_args() << " " << trait.m_path.m_path << ti.m_trait_args << " for " << ti.m_type << ti.m_params.fmt_bounds()); - auto cb_ident = [](const ::HIR::TypeRef& x)->const ::HIR::TypeRef& { return x; }; ImplTyMatcher matcher; matcher.reinit(ti.m_params); // 1. Triple-check the type matches (and get generics) diff --git a/src/hir/inherent_cache.cpp b/src/hir/inherent_cache.cpp index 8454dcc1..01a32260 100644 --- a/src/hir/inherent_cache.cpp +++ b/src/hir/inherent_cache.cpp @@ -112,7 +112,7 @@ void HIR::InherentCache::Inner::insert(const Span& sp, const HIR::TypeRef& cur_t } void HIR::InherentCache::Inner::find(const Span& sp, const HIR::TypeRef& cur_ty_act, t_cb_resolve_type ty_res, InherentCache::inner_callback_t& cb) const { - const auto& cur_ty = ty_res(cur_ty_act); + const auto& cur_ty = ty_res.get_type(sp, cur_ty_act); m_byvalue.iterate(cur_ty, cb); const Inner* inner = nullptr; @@ -202,7 +202,6 @@ void HIR::InherentCache::insert_all(const Span& sp, const HIR::TypeImpl& impl, c void HIR::InherentCache::find(const Span& sp, const RcString& name, const HIR::TypeRef& ty, t_cb_resolve_type ty_res, callback_t cb) const { TRACE_FUNCTION_F(name << ", " << ty); - auto cb_resolve = [](const HIR::TypeRef& t)->const HIR::TypeRef& { return t; }; // Callback that ensures that a potential impl fully matches the required receiver type inner_callback_t inner_cb = [&](const HIR::TypeRef& rough_self_ty, const HIR::TypeImpl& impl) { DEBUG("- " << rough_self_ty); @@ -224,7 +223,7 @@ void HIR::InherentCache::find(const Span& sp, const RcString& name, const HIR::T } getself; if( fcn.m_receiver == HIR::Function::Receiver::Custom ) { - if( fcn.m_receiver_type.match_test_generics(sp, ty, cb_resolve, getself) ) { + if( fcn.m_receiver_type.match_test_generics(sp, ty, ResolvePlaceholdersNop(), getself) ) { ASSERT_BUG(sp, getself.detected_self_ty, "Unable to determine receiver type when matching " << fcn.m_receiver_type << " and " << ty); cb(*getself.detected_self_ty, impl); } diff --git a/src/hir/path.cpp b/src/hir/path.cpp index 5d3fcc3c..4745c362 100644 --- a/src/hir/path.cpp +++ b/src/hir/path.cpp @@ -309,6 +309,10 @@ ::HIR::Compare HIR::PathParams::match_test_generics_fuzz(const Span& sp, const P return Compare::Unequal; } else { + // TODO: Look up the the ivars? + if( this->m_values[i].is_Infer() ) { + return Compare::Fuzzy; + } if( this->m_values[i] != x.m_values[i] ) { return Compare::Unequal; } diff --git a/src/hir/type.cpp b/src/hir/type.cpp index bed0a3e6..f0c6416b 100644 --- a/src/hir/type.cpp +++ b/src/hir/type.cpp @@ -562,8 +562,8 @@ ::HIR::Compare HIR::TypeRef::match_test_generics_fuzz(const Span& sp, const ::HI if( const auto* e = data().opt_Generic() ) { return callback.match_ty(*e, x_in, resolve_placeholder); } - const auto& v = (this->data().is_Infer() ? resolve_placeholder(*this) : *this); - const auto& x = (x_in.data().is_Infer() || x_in.data().is_Generic() ? resolve_placeholder(x_in) : x_in); + const auto& v = (this->data().is_Infer() ? resolve_placeholder.get_type(sp, *this) : *this); + const auto& x = (x_in.data().is_Infer() || x_in.data().is_Generic() ? resolve_placeholder.get_type(sp, x_in) : x_in); TRACE_FUNCTION_F(*this << ", " << x_in << " -- " << v << ", " << x); // If `x` is an ivar - This can be a fuzzy match. if(const auto* xep = x.data().opt_Infer()) @@ -1059,9 +1059,9 @@ ::HIR::TypeRef HIR::TypeRef::clone_shallow() const ::HIR::Compare HIR::TypeRef::compare_with_placeholders(const Span& sp, const ::HIR::TypeRef& x, t_cb_resolve_type resolve_placeholder) const { //TRACE_FUNCTION_F(*this << " ?= " << x); - const auto& left = (data().is_Infer() || data().is_Generic() ? resolve_placeholder(*this) : *this); + const auto& left = (data().is_Infer() || data().is_Generic() ? resolve_placeholder.get_type(sp, *this) : *this); //const auto& left = *this; - const auto& right = (x.data().is_Infer() ? resolve_placeholder(x) : (x.data().is_Generic() ? resolve_placeholder(x) : x)); + const auto& right = (x.data().is_Infer() || x.data().is_Generic()) ? resolve_placeholder.get_type(sp, x) : x; // If the two types are the same ivar, return equal if( left.data().is_Infer() && left == right ) { diff --git a/src/hir/type_ref.hpp b/src/hir/type_ref.hpp index c5e80454..2198beab 100644 --- a/src/hir/type_ref.hpp +++ b/src/hir/type_ref.hpp @@ -30,7 +30,17 @@ enum Compare { Unequal, }; -typedef ::std::function t_cb_resolve_type; +class ResolvePlaceholders { +public: + virtual const ::HIR::TypeRef& get_type(const Span& sp, const HIR::TypeRef& ty) const = 0; + virtual const ::HIR::ConstGeneric& get_val(const Span& sp, const HIR::ConstGeneric& v) const = 0; +}; +class ResolvePlaceholdersNop: public ResolvePlaceholders { + const ::HIR::TypeRef& get_type(const Span& sp, const HIR::TypeRef& ty) const { return ty; } + const ::HIR::ConstGeneric& get_val(const Span& sp, const HIR::ConstGeneric& v) const { return v; } +}; +//typedef ::std::function t_cb_resolve_type; +typedef const ResolvePlaceholders& t_cb_resolve_type; class MatchGenerics { diff --git a/src/hir_conv/resolve_ufcs.cpp b/src/hir_conv/resolve_ufcs.cpp index a0bd69f4..ead437a7 100644 --- a/src/hir_conv/resolve_ufcs.cpp +++ b/src/hir_conv/resolve_ufcs.cpp @@ -567,7 +567,7 @@ namespace resolve_ufcs { { auto& e = pd.as_UfcsUnknown(); TRACE_FUNCTION_F(e.type); - return m_crate.find_type_impls(e.type, [&](const auto& t)->const auto& { return t; }, [&](const auto& impl) { + return m_crate.find_type_impls(e.type, HIR::ResolvePlaceholdersNop(), [&](const auto& impl) { DEBUG("- matched inherent impl" << impl.m_params.fmt_args() << " " << impl.m_type); // Search for item in this block switch( pc ) @@ -887,7 +887,7 @@ namespace resolve_ufcs { BUG(sp, "UfcsUnknown still in pattern value - " << pat); } TU_ARMA(UfcsInherent, pe) { - bool rv = m_crate.find_type_impls(pe.type, [&](const auto& t)->const auto& { return t; }, [&](const auto& impl) { + bool rv = m_crate.find_type_impls(pe.type, HIR::ResolvePlaceholdersNop(), [&](const auto& impl) { DEBUG("- matched inherent impl" << impl.m_params.fmt_args() << " " << impl.m_type); // Search for item in this block auto it = impl.m_constants.find(pe.item); diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp index a47c0c96..41c95219 100644 --- a/src/hir_typeck/expr_check.cpp +++ b/src/hir_typeck/expr_check.cpp @@ -746,7 +746,7 @@ namespace { TU_ARMA(UfcsInherent, e) { // - Locate function (and impl block) const ::HIR::TypeImpl* impl_ptr = nullptr; - m_resolve.m_crate.find_type_impls(e.type, [&](const auto& ty)->const ::HIR::TypeRef& { return ty; }, + m_resolve.m_crate.find_type_impls(e.type, HIR::ResolvePlaceholdersNop(), [&](const auto& impl) { DEBUG("- impl" << impl.m_params.fmt_args() << " " << impl.m_type); auto it = impl.m_methods.find(e.item); diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index bd8de1ed..3c4cdb0b 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -1959,33 +1959,6 @@ void Context::equate_types_inner(const Span& sp, const ::HIR::TypeRef& li, const set_ivar(l_t, r_t); } else { - auto equality_constgeneric = [&](const ::HIR::ConstGeneric& rl, const ::HIR::ConstGeneric& rr) { - const auto& l = this->m_ivars.get_value(rl); - const auto& r = this->m_ivars.get_value(rr); - if( l != r ) { - DEBUG(l << " != " << r); - if(l.is_Infer()) { - if(r.is_Infer()) { - // Unify ivars - this->m_ivars.ivar_val_unify(l.as_Infer().index, r.as_Infer().index); - } - else { - this->m_ivars.set_ivar_val_to(l.as_Infer().index, r.clone()); - } - } - else { - if(r.is_Infer()) { - this->m_ivars.set_ivar_val_to(r.as_Infer().index, l.clone()); - } - else { - ERROR(sp, E0000, "Value mismatch between " << l << " and " << r); - } - } - } - else { - DEBUG(l << " == " << r); - } - }; // Helper function for Path and TraitObject auto equality_typeparams = [&](const ::HIR::PathParams& l, const ::HIR::PathParams& r) { if( l.m_types.size() != r.m_types.size() ) { @@ -2001,7 +1974,7 @@ void Context::equate_types_inner(const Span& sp, const ::HIR::TypeRef& li, const } for(unsigned int i = 0; i < l.m_values.size(); i ++) { - equality_constgeneric(l.m_values[i], r.m_values[i]); + this->equate_values(sp, l.m_values[i], r.m_values[i]); } }; @@ -2126,15 +2099,15 @@ void Context::equate_types_inner(const Span& sp, const ::HIR::TypeRef& li, const if( !l_e.size.is_Unevaluated() ) { assert(l_e.size.is_Known()); assert(r_e.size.is_Unevaluated()); - equality_constgeneric(HIR::EncodedLiteralPtr(EncodedLiteral::make_usize(l_e.size.as_Known())), r_e.size.as_Unevaluated()); + this->equate_values(sp, HIR::EncodedLiteralPtr(EncodedLiteral::make_usize(l_e.size.as_Known())), r_e.size.as_Unevaluated()); } else if( !r_e.size.is_Unevaluated() ) { assert(l_e.size.is_Unevaluated()); assert(r_e.size.is_Known()); - equality_constgeneric(l_e.size.as_Unevaluated(), HIR::EncodedLiteralPtr(EncodedLiteral::make_usize(r_e.size.as_Known()))); + this->equate_values(sp, l_e.size.as_Unevaluated(), HIR::EncodedLiteralPtr(EncodedLiteral::make_usize(r_e.size.as_Known()))); } else { - equality_constgeneric(l_e.size.as_Unevaluated(), r_e.size.as_Unevaluated()); + this->equate_values(sp, l_e.size.as_Unevaluated(), r_e.size.as_Unevaluated()); } } else { @@ -2194,6 +2167,35 @@ void Context::equate_types_inner(const Span& sp, const ::HIR::TypeRef& li, const } } +void Context::equate_values(const Span& sp, const ::HIR::ConstGeneric& rl, const ::HIR::ConstGeneric& rr) +{ + const auto& l = this->m_ivars.get_value(rl); + const auto& r = this->m_ivars.get_value(rr); + if( l != r ) { + DEBUG(l << " != " << r); + if(l.is_Infer()) { + if(r.is_Infer()) { + // Unify ivars + this->m_ivars.ivar_val_unify(l.as_Infer().index, r.as_Infer().index); + } + else { + this->m_ivars.set_ivar_val_to(l.as_Infer().index, r.clone()); + } + } + else { + if(r.is_Infer()) { + this->m_ivars.set_ivar_val_to(r.as_Infer().index, l.clone()); + } + else { + ERROR(sp, E0000, "Value mismatch between " << l << " and " << r); + } + } + } + else { + DEBUG(l << " == " << r); + } +} + void Context::add_binding_inner(const Span& sp, const ::HIR::PatternBinding& pb, ::HIR::TypeRef type) { assert( pb.is_valid() ); @@ -5206,6 +5208,10 @@ namespace { { context.equate_types(sp, v.params.m_types[i], itp.m_types[i]); } + for(unsigned int i = 0; i < v.params.m_values.size(); i ++) + { + context.equate_values(sp, v.params.m_values[i], itp.m_values[i]); + } return true; } else { @@ -5421,6 +5427,9 @@ namespace { for( unsigned int i = 0; i < possible_params.m_types.size(); i ++ ) { context.equate_types(sp, v.params.m_types[i], possible_params.m_types[i]); } + for( unsigned int i = 0; i < possible_params.m_values.size(); i ++ ) { + context.equate_values(sp, v.params.m_values[i], possible_params.m_values[i]); + } // - Obtain the bounds required for this impl and add those as trait bounds to check/equate if( const auto* ep = best_impl.m_data.opt_TraitImpl() ) { diff --git a/src/hir_typeck/expr_cs.hpp b/src/hir_typeck/expr_cs.hpp index 13de7046..f87ade9b 100644 --- a/src/hir_typeck/expr_cs.hpp +++ b/src/hir_typeck/expr_cs.hpp @@ -184,6 +184,9 @@ struct Context // - Equate a type to an associated type (if name == "", no equation is done, but trait is searched) void equate_types_assoc(const Span& sp, const ::HIR::TypeRef& l, const ::HIR::SimplePath& trait, ::HIR::PathParams params, const ::HIR::TypeRef& impl_ty, const char *name, bool is_op=false); + // Equate const generics (values) + void equate_values(const Span& sp, const ::HIR::ConstGeneric& rl, const ::HIR::ConstGeneric& rr); + /// Adds a `ty: Sized` bound to the contained ivars. void require_sized(const Span& sp, const ::HIR::TypeRef& ty); diff --git a/src/hir_typeck/expr_cs__enum.cpp b/src/hir_typeck/expr_cs__enum.cpp index 63664757..83fc7798 100644 --- a/src/hir_typeck/expr_cs__enum.cpp +++ b/src/hir_typeck/expr_cs__enum.cpp @@ -479,6 +479,10 @@ namespace typecheck { } + void visit_path_params(::HIR::PathParams& pp) + { + this->context.m_ivars.add_ivars_params(pp); + } void visit_type(::HIR::TypeRef& ty) { this->context.add_ivars(ty); diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index d56272cb..2fbb0fe0 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -886,7 +886,7 @@ const ::HIR::ConstGeneric& HMTypeInferrence::get_value(const ::HIR::ConstGeneric } const ::HIR::ConstGeneric& HMTypeInferrence::get_value(unsigned slot) const { - ASSERT_BUG(Span(), slot != ~0u, ""); + ASSERT_BUG(Span(), slot != ~0u, "HMTypeInferrence::get_value: Value generic ivar index not assigned"); auto index = slot; // Limit the iteration count to the number of ivars for(unsigned int count = 0; count < m_values.size(); count ++) @@ -1148,9 +1148,29 @@ bool HMTypeInferrence::types_equal(const ::HIR::TypeRef& rl, const ::HIR::TypeRe // TraitResolution // -------------------------------------------------------------------- +namespace { + ::HIR::Compare compare_value(const Span& sp, const ::HIR::ConstGeneric& left_raw, const ::HIR::ConstGeneric& right_raw, const HMTypeInferrence& infer) + { + const auto& left = left_raw .is_Infer() ? infer.get_value(left_raw .as_Infer().index) : left_raw ; + const auto& right = right_raw.is_Infer() ? infer.get_value(right_raw.as_Infer().index) : right_raw; + if( left == right ) + return ::HIR::Compare::Equal; + if( left.is_Infer() || right.is_Infer() ) { + return ::HIR::Compare::Fuzzy; + } + if( left.is_Generic() && left.as_Generic().is_placeholder() ) + return ::HIR::Compare::Fuzzy; + if( right.is_Generic() && right.as_Generic().is_placeholder() ) + return ::HIR::Compare::Fuzzy; + //TODO(sp, "compare_value: " << left << " == " << right); + return ::HIR::Compare::Unequal; + } +} + ::HIR::Compare TraitResolution::compare_pp(const Span& sp, const ::HIR::PathParams& left, const ::HIR::PathParams& right) const { ASSERT_BUG( sp, left.m_types.size() == right.m_types.size(), "Parameter count mismatch - `"<m_ivars); + if( ord == ::HIR::Compare::Unequal ) + return ord; + } return ord; } @@ -3110,7 +3135,9 @@ ::HIR::Compare TraitResolution::ftic_check_params(const Span& sp, const ::HIR::S ::HIR::Compare match_val(const ::HIR::GenericRef& g, const ::HIR::ConstGeneric& sz) override { ASSERT_BUG(sp, g.binding < out_impl_params.m_values.size(), "Value generic " << g << " out of range (" << out_impl_params.m_values.size() << ")"); - if( out_impl_params.m_values[g.binding].is_Infer() ) + if(sz.is_Infer()) + ASSERT_BUG(sp, sz.as_Infer().index != ~0u, ""); + if( out_impl_params.m_values[g.binding] == HIR::ConstGeneric() ) { DEBUG("[ftic_check_params] Value param " << g.binding << " = " << sz); out_impl_params.m_values[g.binding] = sz.clone(); @@ -3138,9 +3165,7 @@ ::HIR::Compare TraitResolution::ftic_check_params(const Span& sp, const ::HIR::S if( params_ptr ) { const auto& params = *params_ptr; - ASSERT_BUG(sp, impl_trait_args.m_types.size() == params.m_types.size(), "Param count mismatch between `" << impl_trait_args << "` and `" << params << "` for " << trait ); - for(unsigned int i = 0; i < impl_trait_args.m_types.size(); i ++) - match &= impl_trait_args.m_types[i] .match_test_generics_fuzz(sp, params.m_types[i], this->m_ivars.callback_resolve_infer(), get_params); + match &= impl_trait_args.match_test_generics_fuzz(sp, params, this->m_ivars.callback_resolve_infer(), get_params); if( match == ::HIR::Compare::Unequal ) { DEBUG("- Failed to match parameters - " << impl_trait_args << "+" << impl_ty << " != " << params << "+" << type); return ::HIR::Compare::Unequal; @@ -3173,7 +3198,7 @@ ::HIR::Compare TraitResolution::ftic_check_params(const Span& sp, const ::HIR::S } for(unsigned int i = 0; i < out_impl_params.m_values.size(); i ++ ) { - if( out_impl_params.m_values[i].is_Infer() ) + if( out_impl_params.m_values[i] == HIR::ConstGeneric() ) { if( placeholders.m_values.size() == 0 ) placeholders.m_values.resize(out_impl_params.m_values.size()); @@ -3182,31 +3207,7 @@ ::HIR::Compare TraitResolution::ftic_check_params(const Span& sp, const ::HIR::S } } DEBUG("Placeholders: " << placeholders); - auto cb_infer = [&](const auto& ty)->const ::HIR::TypeRef& { - if( ty.data().is_Infer() ) - return this->m_ivars.get_type(ty); - #if 0 - else if( ty.data().is_Generic() && ty.data().as_Generic().binding >> 8 == 2 ) { // Generic group 2 = Placeholders - unsigned int i = ty.data().as_Generic().binding % 256; - ASSERT_BUG(sp, i < impl_params.size(), "Placeholder param out of range - " << i << " >= " << placeholders.size()); - if( impl_params[i] ) - { - DEBUG("[ftic_check_params:cb_infer] " << ty << " = " << *impl_params[i]); - return *impl_params[i]; - } - else - { - ASSERT_BUG(sp, i < placeholders.size(), "Placeholder param out of range - " << i << " >= " << placeholders.size()); - const auto& ph = placeholders[i]; - if( ph.m_data.is_Generic() && ph.m_data.as_Generic().binding == i ) - TODO(sp, "[ftic_check_params:cb_infer] Placeholder " << i << " not yet bound"); - return ph; - } - } - #endif - else - return ty; - }; + auto cb_infer = m_ivars.callback_resolve_infer(); struct Matcher: public ::HIR::MatchGenerics, public Monomorphiser @@ -3265,13 +3266,46 @@ ::HIR::Compare TraitResolution::ftic_check_params(const Span& sp, const ::HIR::S if( ty.data().is_Generic() && ty.data().as_Generic().is_placeholder() ) { return ::HIR::Compare::Fuzzy; } - DEBUG("Unequal generic - " << g << " != " << ty); + DEBUG("Unequal generic type - " << g << " != " << ty); return ::HIR::Compare::Unequal; } } - ::HIR::Compare match_val(const ::HIR::GenericRef& g, const ::HIR::ConstGeneric& sz) override + ::HIR::Compare match_val(const ::HIR::GenericRef& g, const ::HIR::ConstGeneric& v) override { - TODO(Span(), "Matcher::match_val " << g << " with " << sz); + if( const auto* e = v.opt_Generic() ) + { + if( e->binding == g.binding && e->name == g.name ) + { + return ::HIR::Compare::Equal; + } + } + if( g.is_placeholder() && g.name == placeholder_name ) { + auto i = g.idx(); + ASSERT_BUG(sp, impl_params.m_values[i] == HIR::ConstGeneric(), "Placeholder to populated value returned - " << impl_params.m_values[i] << " vs " << v); + auto& ph = placeholders.m_values[i]; + if( ph.is_Generic() && ph.as_Generic().binding == g.binding ) { + DEBUG("[ftic_check_params:cb_match] Bind placeholder " << i << " to " << v); + ph = v.clone(); + return ::HIR::Compare::Equal; + } + else { + DEBUG("[ftic_check_params:cb_match] Compare placeholder " << i << " " << ph << " == " << v); + TODO(Span(), "[ftic_check_params:cb_match] Compare placeholder " << i << " " << ph << " == " << v); + //return ph.compare_with_placeholders(sp, ty, resolve_cb); + } + } + else { + if( g.is_placeholder() ) { + DEBUG("[ftic_check_params:cb_match] External impl param " << g); + return ::HIR::Compare::Fuzzy; + } + // If the RHS is a non-literal ivar, return fuzzy + if( v.is_Infer() ) { + return ::HIR::Compare::Fuzzy; + } + DEBUG("Unequal generic value - " << g << " != " << v); + return ::HIR::Compare::Unequal; + } } ::HIR::TypeRef get_type(const Span& sp, const ::HIR::GenericRef& ge) const override { @@ -3291,7 +3325,7 @@ ::HIR::Compare TraitResolution::ftic_check_params(const Span& sp, const ::HIR::S ::HIR::ConstGeneric get_value(const Span& sp, const ::HIR::GenericRef& val) const override { ASSERT_BUG(sp, val.binding < 256, "Generic value binding in " << val << " out of range (>=256)"); ASSERT_BUG(sp, val.binding < impl_params.m_values.size(), "Generic value binding in " << val << " out of range (>= " << impl_params.m_values.size() << ")"); - if( !impl_params.m_values.at(val.binding).is_Infer() ) { + if( impl_params.m_values.at(val.binding) != HIR::ConstGeneric() ) { return impl_params.m_values.at(val.binding).clone(); } ASSERT_BUG(sp, placeholders.m_values.size() == impl_params.m_values.size(), "Placeholder size mismatch: " << placeholders.m_values.size() << " != " << impl_params.m_values.size()); @@ -3486,14 +3520,18 @@ ::HIR::Compare TraitResolution::ftic_check_params(const Span& sp, const ::HIR::S } } - for(size_t i = 0; i < out_impl_params.m_types.size(); i ++) - { - if( out_impl_params.m_types[i] == HIR::TypeRef() ) - { + for(size_t i = 0; i < out_impl_params.m_types.size(); i ++) { + if( out_impl_params.m_types[i] == HIR::TypeRef() ) { out_impl_params.m_types[i] = std::move(placeholders.m_types[i]); } ASSERT_BUG(sp, out_impl_params.m_types[i] != HIR::TypeRef(), ""); } + for(size_t i = 0; i < out_impl_params.m_values.size(); i ++) { + if( out_impl_params.m_values[i] == HIR::ConstGeneric() ) { + out_impl_params.m_values[i] = std::move(placeholders.m_values[i]); + } + ASSERT_BUG(sp, out_impl_params.m_values[i] != HIR::ConstGeneric(), ""); + } for(size_t i = 0; i < impl_params_def.m_types.size(); i ++) { @@ -3514,11 +3552,6 @@ ::HIR::Compare TraitResolution::ftic_check_params(const Span& sp, const ::HIR::S } } - - //if( match == ::HIR::Compare::Fuzzy ) { - // out_impl_params.placeholder_types = ::std::move(fuzzy_ph); - //} - return match; } diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp index 0a76bdca..ab666df4 100644 --- a/src/hir_typeck/helpers.hpp +++ b/src/hir_typeck/helpers.hpp @@ -124,13 +124,26 @@ class HMTypeInferrence // (helper) Add ivars to path parameters void add_ivars_params(::HIR::PathParams& params); - ::std::function callback_resolve_infer() const { - return [&](const auto& ty)->const auto& { - if( ty.data().is_Infer() ) - return this->get_type(ty); - else - return ty; - }; + struct ResolvePlaceholders: public HIR::ResolvePlaceholders { + const HMTypeInferrence& m_parent; + ResolvePlaceholders(const HMTypeInferrence& parent): m_parent(parent) { + } + + const ::HIR::TypeRef& get_type(const Span& sp, const HIR::TypeRef& ty) const override { + if( ty.data().is_Infer() ) + return m_parent.get_type(ty); + else + return ty; + } + const ::HIR::ConstGeneric& get_val(const Span& sp, const HIR::ConstGeneric& v) const override { + if( v.is_Infer() ) + return m_parent.get_value(v); + else + return v; + } + }; + ResolvePlaceholders callback_resolve_infer() const { + return ResolvePlaceholders(*this); } // Mutation diff --git a/src/hir_typeck/outer.cpp b/src/hir_typeck/outer.cpp index f782b284..14c9a45b 100644 --- a/src/hir_typeck/outer.cpp +++ b/src/hir_typeck/outer.cpp @@ -548,7 +548,7 @@ namespace { { auto& e = pd.as_UfcsUnknown(); const auto& type = e.type; - return this->crate.find_trait_impls(trait_path.m_path, type, [](const auto& x)->const auto&{return x;}, [&](const auto& impl) { + return this->crate.find_trait_impls(trait_path.m_path, type, HIR::ResolvePlaceholdersNop(), [&](const auto& impl) { DEBUG("FOUND impl" << impl.m_params.fmt_args() << " " << trait_path.m_path << impl.m_trait_args << " for " << impl.m_type); // TODO: Check bounds for(const auto& bound : impl.m_params.m_bounds) { @@ -633,7 +633,7 @@ namespace { } else { // 1. Search for applicable inherent methods (COMES FIRST!) - if( this->crate.find_type_impls(e.type, [](const auto& ty)->const auto&{return ty;}, [&](const auto& impl) { + if( this->crate.find_type_impls(e.type, HIR::ResolvePlaceholdersNop(), [&](const auto& impl) { DEBUG("- matched inherent impl " << e.type); // Search for item in this block switch( pc ) diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp index 6976da97..1716ef63 100644 --- a/src/hir_typeck/static.cpp +++ b/src/hir_typeck/static.cpp @@ -18,7 +18,7 @@ bool StaticTraitResolve::find_impl( ) const { TRACE_FUNCTION_F(trait_path << FMT_CB(os, if(trait_params) { os << *trait_params; } else { os << ""; }) << " for " << type); - auto cb_ident = [](const ::HIR::TypeRef&ty)->const ::HIR::TypeRef& { return ty; }; + auto cb_ident = HIR::ResolvePlaceholdersNop(); static ::HIR::GenericParams null_hrls; static ::HIR::PathParams null_params; @@ -162,7 +162,7 @@ bool StaticTraitResolve::find_impl( if(!trait_params) return true; - return target_params.compare_with_placeholders(sp, *trait_params, [](const auto&t)->const ::HIR::TypeRef&{return t;}) != HIR::Compare::Unequal; + return target_params.compare_with_placeholders(sp, *trait_params, HIR::ResolvePlaceholdersNop()) != HIR::Compare::Unequal; } }; @@ -186,7 +186,7 @@ bool StaticTraitResolve::find_impl( } for(unsigned int i = 0; i < des_arg_tys.size(); i ++) { - if( des_arg_tys[i].compare_with_placeholders(sp, e.m_arg_types[i], [](const auto&t)->const ::HIR::TypeRef&{return t;}) == ::HIR::Compare::Unequal ) { + if( des_arg_tys[i].compare_with_placeholders(sp, e.m_arg_types[i], cb_ident) == ::HIR::Compare::Unequal ) { return false; } } @@ -218,7 +218,7 @@ bool StaticTraitResolve::find_impl( } for(unsigned int i = 0; i < des_arg_tys.size(); i ++) { - if( des_arg_tys[i].compare_with_placeholders(sp, e.node->m_args[i].second, [](const auto&t)->const ::HIR::TypeRef&{return t;}) == ::HIR::Compare::Unequal ) { + if( des_arg_tys[i].compare_with_placeholders(sp, e.node->m_args[i].second, HIR::ResolvePlaceholdersNop()) == ::HIR::Compare::Unequal ) { return false; } } @@ -552,7 +552,7 @@ bool StaticTraitResolve::find_impl__bounds( ASSERT_BUG( sp, left.m_types.size() == right.m_types.size(), "Parameter count mismatch between " << left << " and " << right ); for(unsigned int i = 0; i < left.m_types.size(); i ++) { // TODO: Permits fuzzy comparison to handle placeholder params, should instead do a match/test/assign - if( left.m_types[i].compare_with_placeholders(sp, right.m_types[i], [](const auto&t)->const ::HIR::TypeRef&{return t;}) == ::HIR::Compare::Unequal ) { + if( left.m_types[i].compare_with_placeholders(sp, right.m_types[i], HIR::ResolvePlaceholdersNop()) == ::HIR::Compare::Unequal ) { //if( left.m_types[i] != right.m_types[i] ) { return false; } @@ -573,7 +573,7 @@ bool StaticTraitResolve::find_impl__bounds( const auto& b_params = it->first.second.m_params; DEBUG("ivar present: type ?= " << b_type); - if( b_type.compare_with_placeholders(sp, type, [](const auto&t)->const ::HIR::TypeRef&{return t;}) == ::HIR::Compare::Unequal ) { + if( b_type.compare_with_placeholders(sp, type, HIR::ResolvePlaceholdersNop()) == ::HIR::Compare::Unequal ) { continue; } DEBUG(b_type << ": " << "for" << it->second.hrbs.fmt_args() << " " << trait_path << b_params); @@ -741,7 +741,7 @@ bool StaticTraitResolve::find_impl__check_crate_raw( ::std::function found_cb ) const { - auto cb_ident = [](const auto&ty)->const ::HIR::TypeRef&{return ty;}; + auto cb_ident = HIR::ResolvePlaceholdersNop(); TRACE_FUNCTION_F("impl" << impl_params_def.fmt_args() << " " << des_trait_path << impl_trait_params << " for " << impl_type << impl_params_def.fmt_bounds()); // TODO: What if `des_trait_params` already has impl placeholders? @@ -1645,7 +1645,7 @@ bool StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI // - A fuzzy can be caused by an opaque match. // - TODO: Move this logic into `find_impl` if( fuzzy ) { - auto cb_ident = [](const ::HIR::TypeRef& x)->const ::HIR::TypeRef& { return x; }; + auto cb_ident = HIR::ResolvePlaceholdersNop(); DEBUG("[expand_associated_types] - Fuzzy, monomorph+expand and recheck"); auto impl_ty = impl.get_impl_type(); @@ -1800,7 +1800,7 @@ bool StaticTraitResolve::find_named_trait_in_trait(const Span& sp, // monomorphed version) OR, there may be placeholders if( pt.m_path.m_path == des ) { - auto cmp = pt_mono.m_path.m_params.compare_with_placeholders(sp, des_params, [](const auto& t)->const ::HIR::TypeRef&{return t;}); + auto cmp = pt_mono.m_path.m_params.compare_with_placeholders(sp, des_params, HIR::ResolvePlaceholdersNop()); // pt_mono.m_path.m_params == des_params ) if( cmp != ::HIR::Compare::Unequal ) { @@ -3012,14 +3012,14 @@ StaticTraitResolve::ValuePtr StaticTraitResolve::get_value(const Span& sp, const out_params.pp_impl = &pe.impl_params; out_params.pp_method = &pe.params; ValuePtr rv; - m_crate.find_type_impls(pe.type, [](const auto&x)->const ::HIR::TypeRef& { return x; }, [&](const auto& impl) { + m_crate.find_type_impls(pe.type, HIR::ResolvePlaceholdersNop(), [&](const auto& impl) { DEBUG("Found impl" << impl.m_params.fmt_args() << " " << impl.m_type); // Populate pp_impl if not populated if( !pe.impl_params.has_params() ) { GetParams::ParamsSet params_set; GetParams get_params { sp, impl.m_params, out_params.pp_impl_data, params_set }; - auto cb_ident = [](const ::HIR::TypeRef&ty)->const ::HIR::TypeRef& { return ty; }; + auto cb_ident = HIR::ResolvePlaceholdersNop(); impl.m_type.match_test_generics_fuzz(sp, pe.type, cb_ident, get_params); if( !pe.impl_params.m_lifetimes.empty() ) { diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 282d6c49..cc5d7757 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -2415,7 +2415,7 @@ namespace { } TU_ARMA(UfcsInherent, pe) { // 1. Find item in an impl block - auto rv = m_builder.crate().find_type_impls(pe.type, [&](const auto& ty)->const ::HIR::TypeRef& { return ty; }, + auto rv = m_builder.crate().find_type_impls(pe.type, HIR::ResolvePlaceholdersNop(), [&](const auto& impl) { DEBUG("- impl" << impl.m_params.fmt_args() << " " << impl.m_type); // Associated functions diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 98b04daa..34a91f96 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -4263,7 +4263,7 @@ namespace { } TU_ARMA(UfcsInherent, pe) { // Check if the return type is ! - omit_assign |= m_resolve.m_crate.find_type_impls(pe.type, [&](const auto& ty)->const auto& { return ty; }, + omit_assign |= m_resolve.m_crate.find_type_impls(pe.type, HIR::ResolvePlaceholdersNop(), [&](const auto& impl) { // Associated functions {