diff options
author | John Hodge <tpg@mutabah.net> | 2016-08-06 15:08:09 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-08-06 15:08:09 +0800 |
commit | 517802c8dbccc7b20d921936dd3028e3c77d258a (patch) | |
tree | 60178220b88cb9a0ae169caf061a0d1d2a9f043f /src | |
parent | a11fee6abe86b049cb73dbd29784792999503d97 (diff) | |
download | mrust-517802c8dbccc7b20d921936dd3028e3c77d258a.tar.gz |
HIR Conv - Fix bad trait args in UFCS trait selection
Diffstat (limited to 'src')
-rw-r--r-- | src/hir/path.hpp | 1 | ||||
-rw-r--r-- | src/hir_conv/resolve_ufcs.cpp | 35 | ||||
-rw-r--r-- | src/hir_typeck/helpers.hpp | 3 |
3 files changed, 36 insertions, 3 deletions
diff --git a/src/hir/path.hpp b/src/hir/path.hpp index cace3ff9..8dd27096 100644 --- a/src/hir/path.hpp +++ b/src/hir/path.hpp @@ -90,6 +90,7 @@ struct PathParams PathParams& operator=(PathParams&&) = default; bool operator==(const PathParams& x) const; + bool operator!=(const PathParams& x) const { return !(*this == x); } bool operator<(const PathParams& x) const { return ord(x) == OrdLess; } Ordering ord(const PathParams& x) const { return ::ord(m_types, x.m_types); diff --git a/src/hir_conv/resolve_ufcs.cpp b/src/hir_conv/resolve_ufcs.cpp index d6e4d64b..d7add7b2 100644 --- a/src/hir_conv/resolve_ufcs.cpp +++ b/src/hir_conv/resolve_ufcs.cpp @@ -156,8 +156,7 @@ namespace { } bool locate_trait_item_in_bounds(::HIR::Visitor::PathContext pc, const ::HIR::TypeRef& tr, const ::HIR::GenericParams& params, ::HIR::Path::Data& pd) { - const auto& name = pd.as_UfcsUnknown().item; - DEBUG("TODO: Search for trait impl for " << tr << " with " << name << " in params"); + //const auto& name = pd.as_UfcsUnknown().item; for(const auto& b : params.m_bounds) { TU_IFLET(::HIR::GenericBound, b, TraitBound, e, @@ -211,6 +210,9 @@ namespace { // Locate the item in `pd` and set `pd` to UfcsResolved if found // TODO: This code may end up generating paths without the type information they should contain bool locate_in_trait_and_set(::HIR::Visitor::PathContext pc, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait, ::HIR::Path::Data& pd) { + // TODO: Get the span from caller + static Span _sp; + const auto& sp = _sp; if( locate_item_in_trait(pc, trait, pd) ) { pd = get_ufcs_known(mv$(pd.as_UfcsUnknown()), trait_path.clone() /*make_generic_path(trait_path.m_path, trait)*/, trait); return true; @@ -218,7 +220,31 @@ namespace { // Search supertraits (recursively) for( unsigned int i = 0; i < trait.m_parent_traits.size(); i ++ ) { - const auto& par_trait_path = trait.m_parent_traits[i].m_path; + 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 ) { + TODO(sp, "Self when monomorphising trait args"); + } + else if( ge.binding < 256 ) { + assert(ge.binding < trait_path.m_params.m_types.size()); + return trait_path.m_params.m_types[ge.binding]; + } + else { + ERROR(sp, E0000, "Unexpected generic binding " << ty); + } + }; + 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; + } + 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 = this->find_trait(par_trait_path.m_path); if( locate_in_trait_and_set(pc, par_trait_path, par_trait_ent, pd) ) { @@ -273,9 +299,11 @@ namespace { // Search for matching impls in current generic blocks if( m_resolve.m_item_generics != nullptr && locate_trait_item_in_bounds(pc, *e.type, *m_resolve.m_item_generics, p.m_data) ) { + DEBUG("Found in item params, p = " << p); return ; } if( m_resolve.m_impl_generics != nullptr && locate_trait_item_in_bounds(pc, *e.type, *m_resolve.m_impl_generics, p.m_data) ) { + DEBUG("Found in impl params, p = " << p); return ; } @@ -289,6 +317,7 @@ namespace { } if( locate_in_trait_and_set(pc, trait_path, *m_current_trait, p.m_data) ) { // Success! + DEBUG("Found in Self, p = " << p); return ; } } diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp index 478d89c5..d2fccfde 100644 --- a/src/hir_typeck/helpers.hpp +++ b/src/hir_typeck/helpers.hpp @@ -12,6 +12,9 @@ typedef ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> t_cb_gen extern bool monomorphise_type_needed(const ::HIR::TypeRef& tpl); extern bool monomorphise_pathparams_needed(const ::HIR::PathParams& tpl); +static inline bool monomorphise_genericpath_needed(const ::HIR::GenericPath& tpl) { + return monomorphise_pathparams_needed(tpl.m_params); +} extern bool monomorphise_path_needed(const ::HIR::Path& tpl); extern bool monomorphise_traitpath_needed(const ::HIR::TraitPath& tpl); extern bool monomorphise_type_needed(const ::HIR::TypeRef& tpl); |