diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hir_conv/resolve_ufcs.cpp | 207 |
1 files changed, 114 insertions, 93 deletions
diff --git a/src/hir_conv/resolve_ufcs.cpp b/src/hir_conv/resolve_ufcs.cpp index 9f3541bd..8f4947c5 100644 --- a/src/hir_conv/resolve_ufcs.cpp +++ b/src/hir_conv/resolve_ufcs.cpp @@ -252,124 +252,145 @@ namespace { pd = get_ufcs_known(mv$(pd.as_UfcsUnknown()), trait_path.clone() /*make_generic_path(trait_path.m_path, trait)*/, trait); return true; } - // Search supertraits (recursively) - for( unsigned int i = 0; i < trait.m_parent_traits.size(); i ++ ) - { - const auto& par_trait_path_tpl = trait.m_parent_traits[i].m_path; - const auto* par_trait_path_ptr = &par_trait_path_tpl; - ::HIR::GenericPath par_trait_path_tmp; - // HACK: Compares the param sets to avoid needing to monomorphise in some cases (e.g. Fn* - if( monomorphise_genericpath_needed(par_trait_path_tpl) && par_trait_path_tpl.m_params != trait_path.m_params ) { - auto monomorph_cb = [&](const auto& ty)->const auto& { - const auto& ge = ty.m_data.as_Generic(); - if( ge.binding == 0xFFFF ) { + + auto monomorph_cb = [&](const auto& ty)->const auto& { + const auto& ge = ty.m_data.as_Generic(); + if( ge.binding == 0xFFFF ) { + // TODO: This has to be the _exact_ same type, including future ivars. + return *pd.as_UfcsUnknown().type; + } + else if( (ge.binding >> 8) == 0 ) { + auto idx = ge.binding & 0xFF; + ASSERT_BUG(sp, idx < trait.m_params.m_types.size(), ""); + if( idx < trait_path.m_params.m_types.size() ) + return trait_path.m_params.m_types[idx]; + // If the param is omitted, but has a default, use the default. + else if( trait.m_params.m_types[idx].m_default != ::HIR::TypeRef() ) { + const auto& def = trait.m_params.m_types[idx].m_default; + if( ! monomorphise_type_needed(def) ) + return def; + if( def == ::HIR::TypeRef("Self", 0xFFFF) ) // TODO: This has to be the _exact_ same type, including future ivars. return *pd.as_UfcsUnknown().type; - } - else if( (ge.binding >> 8) == 0 ) { - auto idx = ge.binding & 0xFF; - ASSERT_BUG(sp, idx < trait.m_params.m_types.size(), ""); - if( idx < trait_path.m_params.m_types.size() ) - return trait_path.m_params.m_types[idx]; - // If the param is omitted, but has a default, use the default. - else if( trait.m_params.m_types[idx].m_default != ::HIR::TypeRef() ) { - const auto& def = trait.m_params.m_types[idx].m_default; - if( ! monomorphise_type_needed(def) ) - return def; - if( def == ::HIR::TypeRef("Self", 0xFFFF) ) - // TODO: This has to be the _exact_ same type, including future ivars. - return *pd.as_UfcsUnknown().type; - TODO(sp, "Monomorphise default arg " << def << " for trait path " << trait_path); - } - else - BUG(sp, "Binding out of range in " << ty << " for trait path " << trait_path); - } - else { - ERROR(sp, E0000, "Unexpected generic binding " << ty); - } - }; - DEBUG("- Monomorph " << par_trait_path_tpl); - par_trait_path_tmp = ::HIR::GenericPath( - par_trait_path_tpl.m_path, - monomorphise_path_params_with(sp, par_trait_path_tpl.m_params, monomorph_cb, false /*no infer*/) - ); - par_trait_path_ptr = &par_trait_path_tmp; + TODO(sp, "Monomorphise default arg " << def << " for trait path " << trait_path); + } + else + BUG(sp, "Binding out of range in " << ty << " for trait path " << trait_path); + } + else { + ERROR(sp, E0000, "Unexpected generic binding " << ty); } - DEBUG("- Check " << *par_trait_path_ptr); - const auto& par_trait_path = *par_trait_path_ptr; - //const auto& par_trait_ent = *trait.m_parent_trait_ptrs[i]; - const auto& par_trait_ent = m_crate.get_trait_by_path(sp, par_trait_path.m_path); - if( locate_in_trait_and_set(pc, par_trait_path, par_trait_ent, pd) ) { + }; + ::HIR::GenericPath par_trait_path_tmp; + auto monomorph_gp_if_needed = [&](const auto& tpl)->const auto& { + // NOTE: This doesn't monomorph if the parameter set is the same + if( monomorphise_genericpath_needed(tpl) && tpl.m_params != trait_path.m_params ) { + DEBUG("- Monomorph " << tpl); + return par_trait_path_tmp = monomorphise_genericpath_with(sp, tpl, monomorph_cb, false /*no infer*/); + } + else { + return tpl; + } + }; + + // Search supertraits (recursively) + for(const auto& pt : trait.m_parent_traits) + { + const auto& par_trait_path = monomorph_gp_if_needed(pt.m_path); + DEBUG("- Check " << par_trait_path); + if( locate_in_trait_and_set(pc, par_trait_path, *pt.m_trait_ptr, pd) ) { + return true; + } + } + for(const auto& pt : trait.m_all_parent_traits) + { + const auto& par_trait_path = monomorph_gp_if_needed(pt.m_path); + DEBUG("- Check (all) " << par_trait_path); + if( locate_item_in_trait(pc, *pt.m_trait_ptr, pd) ) { + // TODO: Don't clone if this is from the temp. + pd = get_ufcs_known(mv$(pd.as_UfcsUnknown()), par_trait_path.clone(), *pt.m_trait_ptr); return true; } } return false; } - bool locate_in_trait_impl_and_set(const Span& sp, ::HIR::Visitor::PathContext pc, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait, ::HIR::Path::Data& pd) + bool set_from_trait_impl(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait, ::HIR::Path::Data& pd) { auto& e = pd.as_UfcsUnknown(); - if( this->locate_item_in_trait(pc, trait, pd) ) { - const auto& type = *e.type; - - // TODO: This is VERY arbitary and possibly nowhere near what rustc does. - this->m_resolve.find_impl(sp, trait_path.m_path, nullptr, type, [&](const auto& impl, bool fuzzy){ - auto pp = impl.get_trait_params(); - // Replace all placeholder parameters (group 2) with ivars (empty types) - pp = monomorphise_path_params_with(sp, pp, [&](const auto& gt)->const auto& { - const auto& ge = gt.m_data.as_Generic(); - if( (ge.binding >> 8) == 2 ) { - static ::HIR::TypeRef empty_type; - return empty_type; + const auto& type = *e.type; + + // TODO: This is VERY arbitary and possibly nowhere near what rustc does. + this->m_resolve.find_impl(sp, trait_path.m_path, nullptr, type, [&](const auto& impl, bool fuzzy){ + auto pp = impl.get_trait_params(); + // Replace all placeholder parameters (group 2) with ivars (empty types) + pp = monomorphise_path_params_with(sp, pp, [&](const auto& gt)->const auto& { + const auto& ge = gt.m_data.as_Generic(); + if( (ge.binding >> 8) == 2 ) { + static ::HIR::TypeRef empty_type; + return empty_type; + } + return gt; + }, true); + DEBUG("FOUND impl from " << impl); + // If this has already found an option... + TU_IFLET( ::HIR::Path::Data, pd, UfcsKnown, e, + // Compare all path params, and set different params to _ + assert( pp.m_types.size() == e.trait.m_params.m_types.size() ); + for(unsigned int i = 0; i < pp.m_types.size(); i ++ ) + { + auto& e_ty = e.trait.m_params.m_types[i]; + const auto& this_ty = pp.m_types[i]; + if( e_ty == ::HIR::TypeRef() ) { + // Already _, leave as is } - return gt; - }, true); - DEBUG("FOUND impl from " << impl); - // If this has already found an option... - TU_IFLET( ::HIR::Path::Data, pd, UfcsKnown, e, - // Compare all path params, and set different params to _ - assert( pp.m_types.size() == e.trait.m_params.m_types.size() ); - for(unsigned int i = 0; i < pp.m_types.size(); i ++ ) - { - auto& e_ty = e.trait.m_params.m_types[i]; - const auto& this_ty = pp.m_types[i]; - if( e_ty == ::HIR::TypeRef() ) { - // Already _, leave as is - } - else if( e_ty != this_ty ) { - e_ty = ::HIR::TypeRef(); - } - else { - // Equal, good - } + else if( e_ty != this_ty ) { + e_ty = ::HIR::TypeRef(); + } + else { + // Equal, good } - ) - else { - DEBUG("pp = " << pp); - // Otherwise, set to the current result. - pd = get_ufcs_known(mv$(e), ::HIR::GenericPath(trait_path.m_path, mv$(pp)), trait); } - return false; - }); - return pd.is_UfcsKnown(); + ) + else { + DEBUG("pp = " << pp); + // Otherwise, set to the current result. + pd = get_ufcs_known(mv$(e), ::HIR::GenericPath(trait_path.m_path, mv$(pp)), trait); + } + return false; + }); + return pd.is_UfcsKnown(); + } + + bool locate_in_trait_impl_and_set(const Span& sp, ::HIR::Visitor::PathContext pc, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait, ::HIR::Path::Data& pd) + { + if( this->locate_item_in_trait(pc, trait, pd) ) { + return set_from_trait_impl(sp, trait_path, trait, pd); } else { - DEBUG("- Item " << e.item << " not in trait " << trait_path.m_path); + DEBUG("- Item " << pd.as_UfcsUnknown().item << " not in trait " << trait_path.m_path); } // Search supertraits (recursively) - // NOTE: This runs before "Resolve HIR Markings", so m_all_parent_traits can't be used. - for( unsigned int i = 0; i < trait.m_parent_traits.size(); i ++ ) + // NOTE: This runs before "Resolve HIR Markings", so m_all_parent_traits can't be used exclusively + for(const auto& pt : trait.m_parent_traits) { - const auto& par_trait_path = trait.m_parent_traits[i].m_path; - //const auto& par_trait_ent = *trait.m_parent_trait_ptrs[i]; - const auto& par_trait_ent = m_crate.get_trait_by_path(sp, par_trait_path.m_path); // TODO: Modify path parameters based on the current trait's params - if( locate_in_trait_impl_and_set(sp, pc, par_trait_path, par_trait_ent, pd) ) { + if( locate_in_trait_impl_and_set(sp, pc, pt.m_path, *pt.m_trait_ptr, pd) ) { return true; } } + for(const auto& pt : trait.m_all_parent_traits) + { + if( this->locate_item_in_trait(pc, *pt.m_trait_ptr, pd) ) { + // TODO: Modify path parameters based on the current trait's params + return set_from_trait_impl(sp, pt.m_path, *pt.m_trait_ptr, pd); + } + else { + DEBUG("- Item " << pd.as_UfcsUnknown().item << " not in trait " << trait_path.m_path); + } + } return false; } |