summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hir_conv/resolve_ufcs.cpp78
1 files changed, 42 insertions, 36 deletions
diff --git a/src/hir_conv/resolve_ufcs.cpp b/src/hir_conv/resolve_ufcs.cpp
index 8d5dce86..13e1da18 100644
--- a/src/hir_conv/resolve_ufcs.cpp
+++ b/src/hir_conv/resolve_ufcs.cpp
@@ -22,8 +22,10 @@ namespace {
t_trait_imports m_traits;
StaticTraitResolve m_resolve;
+ const ::HIR::TypeRef* m_current_type = nullptr;
const ::HIR::Trait* m_current_trait;
const ::HIR::ItemPath* m_current_trait_path;
+ bool m_in_expr = false;
public:
Visitor(const ::HIR::Crate& crate):
@@ -41,11 +43,12 @@ namespace {
}
};
ModTraitsGuard push_mod_traits(const ::HIR::Module& mod) {
+ static Span sp;
DEBUG("");
auto rv = ModTraitsGuard { this, mv$(this->m_traits) };
for( const auto& trait_path : mod.m_traits ) {
DEBUG("- " << trait_path);
- m_traits.push_back( ::std::make_pair( &trait_path, &this->find_trait(trait_path) ) );
+ m_traits.push_back( ::std::make_pair( &trait_path, &m_crate.get_trait_by_path(sp, trait_path) ) );
}
return rv;
}
@@ -88,6 +91,7 @@ namespace {
auto _g = m_resolve.set_impl_generics(impl.m_params);
// TODO: Push a bound that `Self: ThisTrait`
+ m_current_type = &impl.m_type;
m_current_trait = &m_crate.get_trait_by_path(Span(), trait_path);
m_current_trait_path = &p;
@@ -97,6 +101,7 @@ namespace {
m_traits.pop_back( );
m_current_trait = nullptr;
+ m_current_type = nullptr;
}
void visit_expr(::HIR::ExprPtr& expr) override
@@ -177,12 +182,15 @@ namespace {
if( expr.get() != nullptr )
{
+ m_in_expr = true;
ExprVisitor v { *this };
(*expr).visit(v);
+ m_in_expr = false;
}
}
bool locate_trait_item_in_bounds(::HIR::Visitor::PathContext pc, const ::HIR::TypeRef& tr, const ::HIR::GenericParams& params, ::HIR::Path::Data& pd) {
+ static Span sp;
//const auto& name = pd.as_UfcsUnknown().item;
for(const auto& b : params.m_bounds)
{
@@ -190,7 +198,7 @@ namespace {
DEBUG("- " << e.type << " : " << e.trait.m_path);
if( e.type == tr ) {
DEBUG(" - Match");
- if( locate_in_trait_and_set(pc, e.trait.m_path, this->find_trait(e.trait.m_path.m_path), pd) ) {
+ if( locate_in_trait_and_set(pc, e.trait.m_path, m_crate.get_trait_by_path(sp, e.trait.m_path.m_path), pd) ) {
return true;
}
}
@@ -290,7 +298,7 @@ namespace {
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 = this->find_trait(par_trait_path.m_path);
+ 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) ) {
return true;
}
@@ -355,7 +363,7 @@ namespace {
{
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 = this->find_trait(par_trait_path.m_path);
+ 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(pc, par_trait_path, par_trait_ent, pd) ) {
return true;
@@ -452,33 +460,6 @@ namespace {
DEBUG("Found in impl params, p = " << p);
return ;
}
-
- TU_IFLET(::HIR::TypeRef::Data, e.type->m_data, Generic, te,
- // If processing a trait, and the type is 'Self', search for the type/method on the trait
- // - TODO: This could be encoded by a `Self: Trait` bound in the generics, but that may have knock-on issues?
- if( te.name == "Self" && m_current_trait ) {
-
- ::HIR::GenericPath trait_path;
- if( m_current_trait_path->trait_path() )
- {
- trait_path = ::HIR::GenericPath( *m_current_trait_path->trait_path() );
- trait_path.m_params = m_current_trait_path->trait_args()->clone();
- }
- else {
- trait_path = ::HIR::GenericPath( m_current_trait_path->get_simple_path() );
- for(unsigned int i = 0; i < m_current_trait->m_params.m_types.size(); i ++ ) {
- trait_path.m_params.m_types.push_back( ::HIR::TypeRef(m_current_trait->m_params.m_types[i].m_name, i) );
- }
- }
- if( locate_in_trait_and_set(pc, trait_path, *m_current_trait, p.m_data) ) {
- // Success!
- DEBUG("Found in Self, p = " << p);
- return ;
- }
- }
- //ERROR(sp, E0000, "Failed to find bound with '" << e.item << "' for " << *e.type);
- //return ;
- )
// TODO: Control ordering with a flag in UfcsUnknown
// 1. Search for applicable inherent methods (COMES FIRST!)
@@ -486,6 +467,36 @@ namespace {
return ;
}
assert(p.m_data.is_UfcsUnknown());
+
+ // If processing a trait, and the type is 'Self', search for the type/method on the trait
+ // - TODO: This could be encoded by a `Self: Trait` bound in the generics, but that may have knock-on issues?
+ if( *e.type == ::HIR::TypeRef("Self", 0xFFFF) || (m_current_type && *e.type == *m_current_type) )
+ {
+ ::HIR::GenericPath trait_path;
+ if( m_current_trait_path->trait_path() )
+ {
+ trait_path = ::HIR::GenericPath( *m_current_trait_path->trait_path() );
+ trait_path.m_params = m_current_trait_path->trait_args()->clone();
+ }
+ else
+ {
+ trait_path = ::HIR::GenericPath( m_current_trait_path->get_simple_path() );
+ for(unsigned int i = 0; i < m_current_trait->m_params.m_types.size(); i ++ ) {
+ trait_path.m_params.m_types.push_back( ::HIR::TypeRef(m_current_trait->m_params.m_types[i].m_name, i) );
+ }
+ }
+ if( locate_in_trait_and_set(pc, trait_path, *m_current_trait, p.m_data) ) {
+ // Success!
+ if( m_in_expr ) {
+ for(auto& t : p.m_data.as_UfcsKnown().trait.m_params.m_types)
+ t = ::HIR::TypeRef();
+ }
+ DEBUG("Found in Self, p = " << p);
+ return ;
+ }
+ DEBUG("- Item " << e.item << " not found in Self - ty=" << *e.type);
+ }
+
// 2. Search all impls of in-scope traits for this method on this type
if( this->resolve_UfcsUnknown_trait(p, pc, p.m_data) ) {
return ;
@@ -560,11 +571,6 @@ namespace {
)
)
}
-
- const ::HIR::Trait& find_trait(const ::HIR::SimplePath& path) const
- {
- return m_crate.get_trait_by_path(Span(), path);
- }
};
}