diff options
author | John Hodge <tpg@mutabah.net> | 2016-07-21 23:10:00 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-07-21 23:10:00 +0800 |
commit | 717e518629c7e4b7a4c5db4a1b4a520bc217e5ee (patch) | |
tree | bf5bb70f920c230ef9e61947d5f31bf63e6cb8dd /src | |
parent | 3fab1f6071718b5456d4c6b33fa5afe8f9a43f71 (diff) | |
download | mrust-717e518629c7e4b7a4c5db4a1b4a520bc217e5ee.tar.gz |
HIR Typecheck - BROKEN: Switch to ImplRef everywhere
Diffstat (limited to 'src')
-rw-r--r-- | src/hir_typeck/expr_context.cpp | 14 | ||||
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 46 | ||||
-rw-r--r-- | src/hir_typeck/expr_simple.cpp | 44 | ||||
-rw-r--r-- | src/hir_typeck/expr_simple.hpp | 13 | ||||
-rw-r--r-- | src/hir_typeck/helpers.cpp | 56 | ||||
-rw-r--r-- | src/hir_typeck/helpers.hpp | 8 | ||||
-rw-r--r-- | src/hir_typeck/impl_ref.hpp | 57 | ||||
-rw-r--r-- | src/hir_typeck/outer.cpp | 2 | ||||
-rw-r--r-- | src/hir_typeck/static.cpp | 109 | ||||
-rw-r--r-- | src/hir_typeck/static.hpp | 67 |
10 files changed, 249 insertions, 167 deletions
diff --git a/src/hir_typeck/expr_context.cpp b/src/hir_typeck/expr_context.cpp index 07dddc45..05faf069 100644 --- a/src/hir_typeck/expr_context.cpp +++ b/src/hir_typeck/expr_context.cpp @@ -915,9 +915,10 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR // Allow cases where `right`: ::core::marker::Unsize<`left`> ::HIR::PathParams pp; pp.m_types.push_back( left_inner_res.clone() ); - bool succ = this->find_trait_impls(sp, this->m_crate.get_lang_item_path(sp, "unsize"), pp, right_inner_res, [&](const auto& args, const auto& ) { - DEBUG("- Found unsizing with args " << args); - return args.m_types[0] == left_inner_res; + bool succ = this->find_trait_impls(sp, this->m_crate.get_lang_item_path(sp, "unsize"), pp, right_inner_res, [&](auto impl, auto match) { + DEBUG("- Found unsizing " << impl); + //return args.m_types[0] == left_inner_res; + return match == ::HIR::Compare::Equal;//args.m_types[0] == left_inner_res; }); if( succ ) { auto span = node_ptr->span(); @@ -975,11 +976,8 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR // 1. Search for an implementation of the data trait for this type auto r = this->expand_associated_types(sp, right_inner_res.clone()); //bool succ = this->find_trait_impls(sp, e.m_trait.m_path.m_path, e.m_trait.m_path.m_params, right_inner_res, [&](const auto& args,const auto& types) { - bool succ = this->find_trait_impls(sp, e.m_trait.m_path.m_path, e.m_trait.m_path.m_params, r, [&](const auto& args,const auto& types) { - if( args.m_types.size() > 0 ) - TODO(sp, "Handle unsizing to traits with params"); - // TODO: Check `types` - return true; + bool succ = this->find_trait_impls(sp, e.m_trait.m_path.m_path, e.m_trait.m_path.m_params, r, [&](auto impl, auto match) { + return match == ::HIR::Compare::Equal; }); if(!succ) { // XXX: Debugging - Resolves to the correct type in a failing case diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 86304b4a..c420b388 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -1446,20 +1446,13 @@ namespace { ::HIR::TypeRef possible_index_type; ::HIR::TypeRef possible_res_type; unsigned int count = 0; - bool rv = this->context.m_resolve.find_trait_impls(node.span(), lang_Index, trait_pp, ty, [&](const auto& ty, const auto& args, const auto& assoc) { - assert( args.m_types.size() == 1 ); - const auto& impl_index = args.m_types[0]; - - auto cmp = impl_index.compare_with_placeholders(node.span(), trait_pp.m_types[0], this->context.m_ivars.callback_resolve_infer()); - if( cmp == ::HIR::Compare::Unequal) { - return false; - } - possible_res_type = assoc.at("Output").clone(); + bool rv = this->context.m_resolve.find_trait_impls(node.span(), lang_Index, trait_pp, ty, [&](auto impl, auto cmp) { + possible_res_type = impl.get_type("Output"); count += 1; if( cmp == ::HIR::Compare::Equal ) { return true; } - possible_index_type = impl_index.clone(); + possible_index_type = impl.get_trait_ty_param(0); return false; }); if( rv ) { @@ -1557,11 +1550,11 @@ namespace { } trait_pp.m_types.push_back( ::HIR::TypeRef( mv$(arg_types) ) ); } - auto was_bounded = this->context.m_resolve.find_trait_impls_bound(node.span(), lang_FnOnce, trait_pp, ty, [&](const auto& , const auto& args, const auto& assoc) { - const auto& tup = args.m_types[0]; + auto was_bounded = this->context.m_resolve.find_trait_impls_bound(node.span(), lang_FnOnce, trait_pp, ty, [&](auto impl, auto cmp) { + auto tup = impl.get_trait_ty_param(0); if( !tup.m_data.is_Tuple() ) ERROR(node.span(), E0000, "FnOnce expects a tuple argument, got " << tup); - fcn_args_tup = tup.clone(); + fcn_args_tup = mv$(tup); return true; }); if( was_bounded ) @@ -3016,26 +3009,14 @@ namespace { unsigned int count = 0; DEBUG("Searching for impl " << v.trait << v.params << " for " << context.m_ivars.fmt_type(v.impl_ty)); bool found = context.m_resolve.find_trait_impls(sp, v.trait, v.params, v.impl_ty, - [&](const auto& impl_ty, const auto& args, const auto& assoc) { - assert( args.m_types.size() == v.params.m_types.size() ); - ::HIR::Compare cmp = impl_ty.compare_with_placeholders(sp, v.impl_ty, context.m_ivars.callback_resolve_infer()); - for( unsigned int i = 0; i < args.m_types.size(); i ++ ) - { - const auto& impl_ty = args.m_types[i]; - const auto& rule_ty = v.params.m_types[i]; - cmp &= impl_ty.compare_with_placeholders(sp, rule_ty, context.m_ivars.callback_resolve_infer()); - } - if( cmp == ::HIR::Compare::Unequal ) { - DEBUG("- (fail) bounded impl " << v.trait << v.params << " (ty_right = " << context.m_ivars.fmt_type(v.impl_ty)); - return false; - } - ::HIR::TypeRef out_ty_o; - if( v.name != "" && assoc.count(v.name) == 0 ) { + [&](auto impl, auto cmp) { + ::HIR::TypeRef out_ty_o = impl.get_type(v.name.c_str()); + if( v.name != "" && out_ty_o == ::HIR::TypeRef() ) { auto ty1 = ::HIR::TypeRef( ::HIR::Path(::HIR::Path( v.impl_ty.clone(), ::HIR::GenericPath(v.trait, v.params.clone()), v.name, ::HIR::PathParams() )) ); out_ty_o = context.m_resolve.expand_associated_types(sp, mv$(ty1)); //BUG(sp, "Getting associated type '" << v.name << "' which isn't in " << v.trait << " (" << ty << ")"); } - const auto& out_ty = (v.name == "" ? v.left_ty : (out_ty_o == ::HIR::TypeRef() ? assoc.at(v.name) : out_ty_o)); + const auto& out_ty = (v.name == "" ? v.left_ty : out_ty_o); // - If we're looking for an associated type, allow it to eliminate impossible impls // > This makes `let v: usize = !0;` work without special cases @@ -3054,11 +3035,11 @@ namespace { } else { if( possible_impl_ty == ::HIR::TypeRef() ) { - possible_impl_ty = impl_ty.clone(); - possible_params = args.clone(); + possible_impl_ty = impl.get_impl_type(); + possible_params = impl.get_trait_params(); } - DEBUG("- (possible) " << v.trait << args << " for " << impl_ty); + DEBUG("- (possible) " << impl); return false; } @@ -3265,6 +3246,7 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR: // - Keep a list in the ivar of what types that ivar could be equated to. DEBUG("--- Coercion checking"); for(auto it = context.link_coerce.begin(); it != context.link_coerce.end(); ) { + it->left_ty = context.m_resolve.expand_associated_types( (*it->right_node_ptr)->span(), mv$(it->left_ty) ); if( check_coerce(context, *it) ) { DEBUG("- Consumed coercion " << it->left_ty << " := " << (**it->right_node_ptr).m_res_type); it = context.link_coerce.erase(it); diff --git a/src/hir_typeck/expr_simple.cpp b/src/hir_typeck/expr_simple.cpp index 5eb8e668..5b6c40b9 100644 --- a/src/hir_typeck/expr_simple.cpp +++ b/src/hir_typeck/expr_simple.cpp @@ -460,9 +460,9 @@ namespace typeck { ::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]; + bool rv = this->context.find_trait_impls(node.span(), trait_path,trait_path_pp, ty_left, [&](auto impl, auto ) { + auto impl_right = impl.get_trait_ty_param(0); + assert(impl_right != ::HIR::TypeRef()); // 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()); @@ -473,7 +473,7 @@ namespace typeck { return true; } - possible_right_type = impl_right.clone(); + possible_right_type = mv$(impl_right); return false; }); @@ -726,9 +726,10 @@ namespace typeck { ops_trait_pp.m_types.push_back( ty_right.clone() ); DEBUG("Searching for impl " << ops_trait << "< " << ty_right << "> for " << ty_left); bool found_bound = this->context.find_trait_impls_bound(sp, ops_trait, ops_trait_pp, ty_left, - [&](const auto& args, const auto& assoc) { - assert(args.m_types.size() == 1); - const auto& arg_type = args.m_types[0]; + [&](auto impl, auto impl_cmp) { + auto arg_type = impl.get_trait_ty_param(0); + assert(arg_type != ::HIR::TypeRef()); + // TODO: if arg_type mentions Self? auto cmp = arg_type.compare_with_placeholders(node.span(), ty_right, this->context.callback_resolve_infer()); if( cmp == ::HIR::Compare::Unequal ) { @@ -999,9 +1000,9 @@ namespace typeck { ::HIR::TypeRef possible_index_type; unsigned int count = 0; - bool rv = this->context.find_trait_impls(node.span(), path_Index,trait_pp, ty, [&](const auto& args, const auto& assoc) { - assert( args.m_types.size() == 1 ); - const auto& impl_index = args.m_types[0]; + bool rv = this->context.find_trait_impls(node.span(), path_Index,trait_pp, ty, [&](auto impl, auto ) { + auto impl_index = impl.get_trait_ty_param(0); + assert(impl_index != ::HIR::TypeRef()); auto cmp = impl_index.compare_with_placeholders(node.span(), trait_pp.m_types[0], this->context.callback_resolve_infer()); if( cmp == ::HIR::Compare::Unequal) @@ -1078,12 +1079,12 @@ namespace typeck { // TODO: Search for Deref impl ::HIR::TypeRef res; const auto& op_deref = this->context.m_crate.get_lang_item_path(node.span(), "deref"); - bool rv = this->context.find_trait_impls(node.span(), op_deref, ::HIR::PathParams{}, ty, [&](const auto& _args, const auto& types) { + bool rv = this->context.find_trait_impls(node.span(), op_deref, ::HIR::PathParams{}, ty, [&](auto impl, auto ) { if( res != ::HIR::TypeRef() ) TODO(node.span(), "Handle multiple implementations of Deref"); - if( types.find("Target") == types.end() ) + res = impl.get_type("Target"); + if( res == ::HIR::TypeRef() ) BUG(node.span(), "Impl of Deref didn't include `Target` associated type (TODO: Is this a bug, what about bounds?)"); - res = types.at("Target").clone(); return true; }); if( rv ) { @@ -1405,13 +1406,15 @@ namespace typeck { auto real_trait = monomorphise_genericpath_with(sp, be.trait.m_path, cache.m_monomorph_cb, false); DEBUG("Bound " << be.type << ": " << be.trait); DEBUG("= (" << real_type << ": " << real_trait << ")"); - auto monomorph_bound = [&](const auto& gt)->const auto& { - return gt; - }; + //auto monomorph_bound = [&](const auto& gt)->const auto& { + // return gt; + // }; const auto& trait_params = be.trait.m_path.m_params; // TODO: Detect marker traits const auto& trait_gp = be.trait.m_path; - auto rv = this->context.find_trait_impls(sp, trait_gp.m_path, real_trait.m_params, real_type, [&](const auto& pp, const auto& at) { + auto rv = this->context.find_trait_impls(sp, trait_gp.m_path, real_trait.m_params, real_type, [&](auto impl, auto ) { + TODO(sp, impl << " cmp with " << trait_params); + #if 0 if( pp.m_types.size() != trait_params.m_types.size() ) { BUG(sp, "Parameter mismatch"); } @@ -1423,6 +1426,7 @@ namespace typeck { //this->context.apply_equality(sp, pp.m_types[i], monomorph_bound, trait_params.m_types[i], cache.m_monomorph_cb, nullptr); this->context.apply_equality(sp, pp.m_types[i], monomorph_bound, real_trait.m_params.m_types[i], IDENT_CR, nullptr); } + #endif // TODO: Use `at` // - Check if the associated type bounds are present #if 0 @@ -1504,11 +1508,11 @@ namespace typeck { const auto& lang_FnOnce = this->context.m_crate.get_lang_item_path(node.span(), "fn_once"); ::HIR::PathParams trait_pp; trait_pp.m_types.push_back( this->context.new_ivar_tr() ); // TODO: Bind to arguments? - auto was_bounded = this->context.find_trait_impls_bound(node.span(), lang_FnOnce, trait_pp, ty, [&](const auto& args, const auto& assoc) { - const auto& tup = args.m_types[0]; + auto was_bounded = this->context.find_trait_impls_bound(node.span(), lang_FnOnce, trait_pp, ty, [&](auto impl, auto ) { + auto tup = impl.get_trait_ty_param(0); if( !tup.m_data.is_Tuple() ) ERROR(node.span(), E0000, "FnOnce expects a tuple argument, got " << tup); - fcn_args_tup = tup.clone(); + fcn_args_tup = mv$(tup); return true; }); if( was_bounded ) diff --git a/src/hir_typeck/expr_simple.hpp b/src/hir_typeck/expr_simple.hpp index 18cf966a..957fbc67 100644 --- a/src/hir_typeck/expr_simple.hpp +++ b/src/hir_typeck/expr_simple.hpp @@ -122,19 +122,20 @@ public: } typedef ::std::function<bool(const ::HIR::PathParams&, const ::std::map< ::std::string,::HIR::TypeRef>&)> t_cb_trait_impl; + typedef TraitResolution::t_cb_trait_impl_r t_cb_trait_impl_r; /// Searches for a trait impl that matches the provided trait name and type - bool find_trait_impls(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const { - return m_resolve.find_trait_impls(sp, trait, params, type, [&](const auto& _, const auto& a, const auto& b){ return callback(a,b); }); + bool find_trait_impls(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl_r callback) const { + return m_resolve.find_trait_impls(sp, trait, params, type, [&](auto a, auto b){ return callback( mv$(a), b ); }); } /// Search for a trait implementation in current bounds - bool find_trait_impls_bound(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const { - return m_resolve.find_trait_impls_bound(sp, trait, params, type, [&](const auto& _, const auto& a, const auto& b){ return callback(a,b); }); + bool find_trait_impls_bound(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl_r callback) const { + return m_resolve.find_trait_impls_bound(sp, trait, params, type, callback); } /// Search for a trait implementation in the crate - bool find_trait_impls_crate(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const { - return m_resolve.find_trait_impls_crate(sp, trait, params, type, [&](const auto& _, const auto& a, const auto& b){ return callback(a,b); }); + bool find_trait_impls_crate(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, TraitResolution::t_cb_trait_impl_r callback) const { + return m_resolve.find_trait_impls_crate(sp, trait, params, type, [&](auto r, auto m){ return callback( mv$(r), m ); }); } /// Locate the named method by applying auto-dereferencing. diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 516bd40d..748559b3 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -1030,9 +1030,12 @@ bool TraitResolution::iterate_bounds( ::std::function<bool(const ::HIR::GenericB bool TraitResolution::find_trait_impls(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& ty, - t_cb_trait_impl callback + t_cb_trait_impl_r callback ) const { + static ::HIR::PathParams null_params; + static ::std::map< ::std::string, ::HIR::TypeRef> null_assoc; + const auto& type = this->m_ivars.get_type(ty); TRACE_FUNCTION_F("trait = " << trait << ", type = " << type); @@ -1055,7 +1058,7 @@ bool TraitResolution::find_trait_impls(const Span& sp, return false; ) ) - return callback( type, ::HIR::PathParams(), {} ); + return callback( ImplRef(&type, &null_params, &null_assoc), ::HIR::Compare::Equal ); } if( trait == this->m_crate.get_lang_item_path(sp, "copy") ) { @@ -1085,7 +1088,7 @@ bool TraitResolution::find_trait_impls(const Span& sp, } }; if( H::is_copy(sp, *this, type) ) { - return callback( type, ::HIR::PathParams(), {} ); + return callback( ImplRef(&type, &null_params, &null_assoc), ::HIR::Compare::Equal ); } else { return false; @@ -1120,7 +1123,7 @@ bool TraitResolution::find_trait_impls(const Span& sp, pp.m_types.push_back( ::HIR::TypeRef(mv$(args)) ); ::std::map< ::std::string, ::HIR::TypeRef> types; types.insert( ::std::make_pair( "Output", e.m_rettype->clone() ) ); - return callback( type, pp, types ); + return callback( ImplRef(type.clone(), mv$(pp), mv$(types)), ::HIR::Compare::Equal ); } else { return false; @@ -1151,7 +1154,7 @@ bool TraitResolution::find_trait_impls(const Span& sp, pp.m_types.push_back( ::HIR::TypeRef(mv$(args)) ); ::std::map< ::std::string, ::HIR::TypeRef> types; types.insert( ::std::make_pair( "Output", e.m_rettype->clone() ) ); - return callback( type, pp, types ); + return callback( ImplRef(type.clone(), mv$(pp), mv$(types)), ::HIR::Compare::Equal ); } // Continue ) @@ -1347,6 +1350,8 @@ bool TraitResolution::has_associated_type(const ::HIR::TypeRef& input) const } ) + //this->find_impl() + // 1. Bounds bool rv; bool assume_opaque = true; @@ -1489,14 +1494,14 @@ bool TraitResolution::has_associated_type(const ::HIR::TypeRef& input) const BUG(sp, "Cannot find associated type " << pe.item << " anywhere in trait " << pe.trait); //pe.trait = mv$(trait_path); - rv = this->find_trait_impls_crate(sp, trait_path.m_path, trait_path.m_params, *pe.type, [&](const auto& , const auto& args, const auto& assoc) { - DEBUG("Found impl for " << pe.trait.m_path << args << " with types {" << assoc << "}"); - auto it = assoc.find( pe.item ); - if( it == assoc.end() ) + rv = this->find_trait_impls_crate(sp, trait_path.m_path, trait_path.m_params, *pe.type, [&](auto impl, auto qual) { + DEBUG("Found " << impl); + auto ty = impl.get_type( pe.item.c_str() ); + if( ty == ::HIR::TypeRef() ) ERROR(sp, E0000, "Couldn't find assocated type " << pe.item << " in " << pe.trait); - DEBUG("Converted UfcsKnown - " << e.path << " = " << it->second); - input = it->second.clone(); + DEBUG("Converted UfcsKnown - " << e.path << " = " << ty); + input = mv$(ty); return true; }); if( rv ) { @@ -1595,7 +1600,7 @@ bool TraitResolution::find_named_trait_in_trait(const Span& sp, } return false; } -bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const +bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl_r callback) const { struct H { static ::HIR::Compare compare_pp(const Span& sp, const TraitResolution& self, const ::HIR::PathParams& left, const ::HIR::PathParams& right) { @@ -1636,7 +1641,7 @@ bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::Simple } // Hand off to the closure, and return true if it does // TODO: The type bounds are only the types that are specified. - if( callback(e.type, e.trait.m_path.m_params, e.trait.m_type_bounds) ) { + if( callback( ImplRef(&e.type, &e.trait.m_path.m_params, &e.trait.m_type_bounds), ord) ) { return true; } } @@ -1658,7 +1663,7 @@ bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::Simple assoc2.insert( ::std::make_pair(i.first, i.second.clone()) ); //} } - return callback(ty, params, assoc2); + return callback( ImplRef(ty.clone(), params.clone(), mv$(assoc2)), ::HIR::Compare::Equal ); }); if( rv ) { return true; @@ -1703,7 +1708,7 @@ bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::Simple } DEBUG("- tp_mono = " << tp_mono); // TODO: Instead of using `type` here, build the real type - if( callback(type, tp_mono.m_path.m_params, tp_mono.m_type_bounds) ) { + if( callback( ImplRef(type.clone(), mv$(tp_mono.m_path.m_params), mv$(tp_mono.m_type_bounds)), ord ) ) { return true; } } @@ -1718,7 +1723,7 @@ bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::Simple bool TraitResolution::find_trait_impls_crate(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, - t_cb_trait_impl callback + t_cb_trait_impl_r callback ) const { // TODO: Parameter defaults - apply here or in the caller? @@ -1834,14 +1839,13 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, } const auto& real_trait_path = real_trait.m_path; DEBUG("- " << real_type << " : " << real_trait_path); - auto rv = this->find_trait_impls(sp, real_trait_path.m_path, real_trait_path.m_params, real_type, [&](const auto&, const auto& a, const auto& t) { + auto rv = this->find_trait_impls(sp, real_trait_path.m_path, real_trait_path.m_params, real_type, [&](auto impl, auto impl_cmp) { for(const auto& assoc_bound : real_trait.m_type_bounds) { ::HIR::TypeRef tmp; const ::HIR::TypeRef* ty_p; - auto it = t.find(assoc_bound.first); - if( it == t.end() ) - { + tmp = impl.get_type(assoc_bound.first.c_str()); + if( tmp == ::HIR::TypeRef() ) { // This bound isn't from this particular trait, go the slow way of using expand_associated_types tmp = this->expand_associated_types(sp, ::HIR::TypeRef( ::HIR::Path(::HIR::Path::Data::Data_UfcsKnown { box$(real_type.clone()), real_trait_path.clone(), assoc_bound.first, {} })) @@ -1849,7 +1853,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, ty_p = &tmp; } else { - ty_p = &this->m_ivars.get_type(it->second); + ty_p = &tmp; } const auto& ty = *ty_p; DEBUG(" - Compare " << ty << " and " << assoc_bound.second << ", matching generics"); @@ -1892,7 +1896,8 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, //if( match == ::HIR::Compare::Fuzzy ) { // TODO(sp, "- Pass on fuzzy match status"); //} - return callback(ty_mono, args_mono, types/*, (match == ::HIR::Compare::Fuzzy)*/); + return callback(ImplRef(mv$(impl_params), impl), match); + //return callback(ty_mono, args_mono, types/*, (match == ::HIR::Compare::Fuzzy)*/); } ); } @@ -1969,9 +1974,8 @@ const ::HIR::TypeRef* TraitResolution::autoderef(const Span& sp, const ::HIR::Ty return &tmp_type; ) else { - bool succ = this->find_trait_impls(sp, this->m_crate.get_lang_item_path(sp, "deref"), ::HIR::PathParams {}, ty, [&](const auto&, const auto& args, const auto& types) { - assert(args.m_types.size() == 0); - tmp_type = types.at("Target").clone(); + bool succ = this->find_trait_impls(sp, this->m_crate.get_lang_item_path(sp, "deref"), ::HIR::PathParams {}, ty, [&](auto impls, auto match) { + tmp_type = impls.get_type("Target"); return true; }); if( succ ) { @@ -2162,7 +2166,7 @@ bool TraitResolution::find_method(const Span& sp, const HIR::t_trait_list& trait //} // TODO: Need a "don't care" marker for the PathParams - if( find_trait_impls_crate(sp, *trait_ref.first, ::HIR::PathParams{}, ty, [](const auto&,const auto&,const auto&) { return true; }) ) { + if( find_trait_impls_crate(sp, *trait_ref.first, ::HIR::PathParams{}, ty, [](auto , auto ) { return true; }) ) { DEBUG("Found trait impl " << *trait_ref.first << " (" /*<< m_ivars.fmt_type(*trait_ref.first)*/ << ") for " << ty << " ("<<m_ivars.fmt_type(ty)<<")"); fcn_path = ::HIR::Path( ::HIR::Path::Data::make_UfcsKnown({ box$( ty.clone() ), diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp index 2e55978e..d6b4e149 100644 --- a/src/hir_typeck/helpers.hpp +++ b/src/hir_typeck/helpers.hpp @@ -5,6 +5,7 @@ #include <hir/type.hpp> #include <hir/hir.hpp> #include <hir/expr.hpp> +#include "impl_ref.hpp" // TODO/NOTE - This is identical to ::HIR::t_cb_resolve_type typedef ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> t_cb_generic; @@ -179,9 +180,10 @@ public: bool iterate_bounds( ::std::function<bool(const ::HIR::GenericBound&)> cb) const; typedef ::std::function<bool(const ::HIR::TypeRef&, const ::HIR::PathParams&, const ::std::map< ::std::string,::HIR::TypeRef>&)> t_cb_trait_impl; + typedef ::std::function<bool(ImplRef, ::HIR::Compare)> t_cb_trait_impl_r; /// Searches for a trait impl that matches the provided trait name and type - bool find_trait_impls(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const; + bool find_trait_impls(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl_r callback) const; /// Locate a named trait in the provied trait (either itself or as a parent trait) bool find_named_trait_in_trait(const Span& sp, @@ -191,9 +193,9 @@ public: t_cb_trait_impl callback ) const; /// Search for a trait implementation in current bounds - bool find_trait_impls_bound(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const; + bool find_trait_impls_bound(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl_r callback) const; /// Search for a trait implementation in the crate - bool find_trait_impls_crate(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const; + bool find_trait_impls_crate(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl_r callback) const; /// Locate the named method by applying auto-dereferencing. /// \return Number of times deref was applied (or ~0 if _ was hit) diff --git a/src/hir_typeck/impl_ref.hpp b/src/hir_typeck/impl_ref.hpp new file mode 100644 index 00000000..e2ec171e --- /dev/null +++ b/src/hir_typeck/impl_ref.hpp @@ -0,0 +1,57 @@ +/* + */ +#pragma once + +#include <hir/type.hpp> + +struct ImplRef +{ + TAGGED_UNION(Data, TraitImpl, + (TraitImpl, struct { + ::std::vector<const ::HIR::TypeRef*> params; + const ::HIR::TraitImpl* impl; + }), + (BoundedPtr, struct { + const ::HIR::TypeRef* type; + const ::HIR::PathParams* trait_args; + const ::std::map< ::std::string, ::HIR::TypeRef>* assoc; + }), + (Bounded, struct { + ::HIR::TypeRef type; + ::HIR::PathParams trait_args; + ::std::map< ::std::string, ::HIR::TypeRef> assoc; + }) + ); + + Data m_data; + + ImplRef(): + m_data(Data::make_TraitImpl({ {}, nullptr })) + {} + ImplRef(::std::vector<const ::HIR::TypeRef*> params, const ::HIR::TraitImpl& impl): + m_data(Data::make_TraitImpl({ mv$(params), &impl })) + + {} + ImplRef(const ::HIR::TypeRef* type, const ::HIR::PathParams* args, const ::std::map< ::std::string, ::HIR::TypeRef>* assoc): + m_data(Data::make_BoundedPtr({ type, mv$(args), mv$(assoc) })) + {} + ImplRef(::HIR::TypeRef type, ::HIR::PathParams args, ::std::map< ::std::string, ::HIR::TypeRef> assoc): + m_data(Data::make_Bounded({ mv$(type), mv$(args), mv$(assoc) })) + {} + + bool is_valid() const { + return !(m_data.is_TraitImpl() && m_data.as_TraitImpl().impl == nullptr); + } + + bool more_specific_than(const ImplRef& other) const; + + ::HIR::TypeRef get_impl_type() const; + ::HIR::PathParams get_trait_params() const; + + ::HIR::TypeRef get_trait_ty_param(unsigned int) const; + + bool type_is_specializable(const char* name) const; + ::HIR::TypeRef get_type(const char* name) const; + + friend ::std::ostream& operator<<(::std::ostream& os, const ImplRef& x); +}; diff --git a/src/hir_typeck/outer.cpp b/src/hir_typeck/outer.cpp index 2baa6ec5..cb27ffe5 100644 --- a/src/hir_typeck/outer.cpp +++ b/src/hir_typeck/outer.cpp @@ -251,7 +251,7 @@ namespace { e.binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({}); } else { - StaticTraitResolve::ImplRef best_impl; + ImplRef best_impl; m_resolve.find_impl(sp, pe.trait.m_path, pe.trait.m_params, *pe.type, [&](auto impl) { DEBUG("[visit_type] Found " << impl); if( best_impl.more_specific_than(impl) ) diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp index 1ee20dfd..df344c79 100644 --- a/src/hir_typeck/static.cpp +++ b/src/hir_typeck/static.cpp @@ -547,7 +547,7 @@ bool StaticTraitResolve::trait_contains_type(const Span& sp, const ::HIR::Generi return false; } -bool StaticTraitResolve::ImplRef::more_specific_than(const ImplRef& other) const +bool ImplRef::more_specific_than(const ImplRef& other) const { TU_MATCH(Data, (this->m_data), (e), (TraitImpl, @@ -565,7 +565,7 @@ bool StaticTraitResolve::ImplRef::more_specific_than(const ImplRef& other) const ) throw ""; } -bool StaticTraitResolve::ImplRef::type_is_specializable(const char* name) const +bool ImplRef::type_is_specializable(const char* name) const { TU_MATCH(Data, (this->m_data), (e), (TraitImpl, @@ -585,8 +585,83 @@ bool StaticTraitResolve::ImplRef::type_is_specializable(const char* name) const ) throw ""; } -::HIR::TypeRef StaticTraitResolve::ImplRef::get_type(const char* name) const +::HIR::TypeRef ImplRef::get_impl_type() const { + Span sp; + TU_MATCH(Data, (this->m_data), (e), + (TraitImpl, + if( e.impl == nullptr ) { + BUG(Span(), "nullptr"); + } + return monomorphise_type_with(sp, e.impl->m_type, [&e](const auto& t)->const auto& { + const auto& ge = t.m_data.as_Generic(); + return *e.params.at(ge.binding); + }); + ), + (BoundedPtr, + return e.type->clone(); + ), + (Bounded, + return e.type.clone(); + ) + ) + throw ""; +} +::HIR::PathParams ImplRef::get_trait_params() const +{ + Span sp; + TU_MATCH(Data, (this->m_data), (e), + (TraitImpl, + if( e.impl == nullptr ) { + BUG(Span(), "nullptr"); + } + return monomorphise_path_params_with(sp, e.impl->m_trait_args, [&e](const auto& t)->const auto& { + const auto& ge = t.m_data.as_Generic(); + return *e.params.at(ge.binding); + }, true); + ), + (BoundedPtr, + return e.trait_args->clone(); + ), + (Bounded, + return e.trait_args.clone(); + ) + ) + throw ""; +} +::HIR::TypeRef ImplRef::get_trait_ty_param(unsigned int idx) const +{ + Span sp; + TU_MATCH(Data, (this->m_data), (e), + (TraitImpl, + if( e.impl == nullptr ) { + BUG(Span(), "nullptr"); + } + if( idx >= e.impl->m_trait_args.m_types.size() ) + return ::HIR::TypeRef(); + return monomorphise_type_with(sp, e.impl->m_trait_args.m_types[idx], [&e](const auto& t)->const auto& { + const auto& ge = t.m_data.as_Generic(); + return *e.params.at(ge.binding); + }, true); + ), + (BoundedPtr, + if( idx >= e.trait_args->m_types.size() ) + return ::HIR::TypeRef(); + return e.trait_args->m_types.at(idx).clone(); + ), + (Bounded, + if( idx >= e.trait_args.m_types.size() ) + return ::HIR::TypeRef(); + return e.trait_args.m_types.at(idx).clone(); + ) + ) + throw ""; + TODO(Span(), ""); +} +::HIR::TypeRef ImplRef::get_type(const char* name) const +{ + if( !name[0] ) + return ::HIR::TypeRef(); static Span sp; TU_MATCH(Data, (this->m_data), (e), (TraitImpl, @@ -609,11 +684,35 @@ bool StaticTraitResolve::ImplRef::type_is_specializable(const char* name) const } ), (BoundedPtr, - TODO(Span(), *this); + TODO(Span(), name << " - " << *this); ), (Bounded, - TODO(Span(), *this); + auto it = e.assoc.find(name); + if(it == e.assoc.end()) + return ::HIR::TypeRef(); + return it->second.clone(); ) ) return ::HIR::TypeRef(); } + +::std::ostream& operator<<(::std::ostream& os, const ImplRef& x) +{ + TU_MATCH(ImplRef::Data, (x.m_data), (e), + (TraitImpl, + if( e.impl == nullptr ) { + os << "none"; + } + else { + os << "impl" << e.impl->m_params.fmt_args() << " ?" << e.impl->m_trait_args << " for " << e.impl->m_type << e.impl->m_params.fmt_bounds(); + } + ), + (BoundedPtr, + os << "bound (ptr) " << *e.type << " : ?" << *e.trait_args << " + {" << *e.assoc << "}"; + ), + (Bounded, + os << "bound " << e.type << " : ?" << e.trait_args << " + {"<<e.assoc<<"}"; + ) + ) + return os; +} diff --git a/src/hir_typeck/static.hpp b/src/hir_typeck/static.hpp index 8c9989f6..bb39e164 100644 --- a/src/hir_typeck/static.hpp +++ b/src/hir_typeck/static.hpp @@ -9,6 +9,7 @@ #include <hir/hir.hpp> #include "helpers.hpp" +#include "impl_ref.hpp" class StaticTraitResolve { @@ -49,72 +50,6 @@ public: } /// \} - - struct ImplRef - { - TAGGED_UNION(Data, TraitImpl, - (TraitImpl, struct { - ::std::vector<const ::HIR::TypeRef*> params; - const ::HIR::TraitImpl* impl; - }), - (BoundedPtr, struct { - const ::HIR::TypeRef* type; - const ::HIR::PathParams* trait_args; - const ::std::map< ::std::string, ::HIR::TypeRef>* assoc; - }), - (Bounded, struct { - ::HIR::TypeRef type; - ::HIR::PathParams trait_args; - ::std::map< ::std::string, ::HIR::TypeRef> assoc; - }) - ); - - Data m_data; - - ImplRef(): - m_data(Data::make_TraitImpl({ {}, nullptr })) - {} - ImplRef(::std::vector<const ::HIR::TypeRef*> params, const ::HIR::TraitImpl& impl): - m_data(Data::make_TraitImpl({ mv$(params), &impl })) - - {} - ImplRef(const ::HIR::TypeRef* type, const ::HIR::PathParams* args, const ::std::map< ::std::string, ::HIR::TypeRef>* assoc): - m_data(Data::make_BoundedPtr({ type, mv$(args), mv$(assoc) })) - {} - ImplRef(::HIR::TypeRef type, ::HIR::PathParams args, ::std::map< ::std::string, ::HIR::TypeRef> assoc): - m_data(Data::make_Bounded({ mv$(type), mv$(args), mv$(assoc) })) - {} - - bool is_valid() const { - return !(m_data.is_TraitImpl() && m_data.as_TraitImpl().impl == nullptr); - } - - bool more_specific_than(const ImplRef& other) const; - - bool type_is_specializable(const char* name) const; - ::HIR::TypeRef get_type(const char* name) const; - - friend ::std::ostream& operator<<(::std::ostream& os, const ImplRef& x) { - TU_MATCH(Data, (x.m_data), (e), - (TraitImpl, - if( e.impl == nullptr ) { - os << "none"; - } - else { - os << "impl" << e.impl->m_params.fmt_args() << " ?" << e.impl->m_trait_args << " for " << e.impl->m_type << e.impl->m_params.fmt_bounds(); - } - ), - (BoundedPtr, - os << "bound"; - ), - (Bounded, - os << "bound"; - ) - ) - return os; - } - }; - /// \brief Lookups /// \{ typedef ::std::function<bool(ImplRef)> t_cb_find_impl; |