summaryrefslogtreecommitdiff
path: root/src/hir_conv/resolve_ufcs.cpp
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-06-05 16:27:28 +0800
committerJohn Hodge <tpg@mutabah.net>2016-06-05 16:27:28 +0800
commite3f35882f8240e506e34bb37c8fef1ca34601882 (patch)
treebb77cf090418079e6c405eb6c71fcf1b7f52c696 /src/hir_conv/resolve_ufcs.cpp
parenta0c00721f5b9d79035e522577b0f127df5849cfb (diff)
downloadmrust-e3f35882f8240e506e34bb37c8fef1ca34601882.tar.gz
HIR - Spanned expressions, fixed sections of resolve
Diffstat (limited to 'src/hir_conv/resolve_ufcs.cpp')
-rw-r--r--src/hir_conv/resolve_ufcs.cpp188
1 files changed, 130 insertions, 58 deletions
diff --git a/src/hir_conv/resolve_ufcs.cpp b/src/hir_conv/resolve_ufcs.cpp
index 14b0233a..295de1b0 100644
--- a/src/hir_conv/resolve_ufcs.cpp
+++ b/src/hir_conv/resolve_ufcs.cpp
@@ -16,9 +16,16 @@ namespace {
::std::vector< ::std::pair< const ::HIR::SimplePath*, const ::HIR::Trait* > > m_traits;
+ const ::HIR::GenericParams* m_impl_params;
+ const ::HIR::GenericParams* m_item_params;
+ const ::HIR::Trait* m_current_trait;
+
public:
Visitor(const ::HIR::Crate& crate):
- m_crate(crate)
+ m_crate(crate),
+ m_impl_params(nullptr),
+ m_item_params(nullptr),
+ m_current_trait(nullptr)
{}
void visit_module(::HIR::Module& mod) override
@@ -30,6 +37,18 @@ namespace {
m_traits.pop_back();
}
+ void visit_function(::HIR::Function& fcn) override {
+ m_item_params = &fcn.m_params;
+ ::HIR::Visitor::visit_function(fcn);
+ m_item_params = nullptr;
+ }
+ void visit_trait(::HIR::Trait& trait) override {
+ m_current_trait = &trait;
+ m_impl_params = &trait.m_params;
+ ::HIR::Visitor::visit_trait(trait);
+ m_impl_params = nullptr;
+ m_current_trait = nullptr;
+ }
void visit_expr(::HIR::ExprPtr& expr) override
{
@@ -91,86 +110,139 @@ namespace {
}
}
+ bool locate_trait_item_in_bounds(::HIR::Visitor::PathContext pc, const ::HIR::TypeRef& tr, const ::std::string& name, const ::HIR::GenericParams& params) {
+ DEBUG("TODO: Search for trait impl for " << tr << " with " << name << " in params");
+ return false;
+ }
+
void visit_path(::HIR::Path& p, ::HIR::Visitor::PathContext pc) override
{
+ DEBUG("p = " << p);
TU_IFLET(::HIR::Path::Data, p.m_data, UfcsUnknown, e,
DEBUG("UfcsUnknown - p=" << p);
- // 1. Search all impls of in-scope traits for this method on this type
- for( const auto& trait_info : m_traits )
- {
- const auto& trait_path = *trait_info.first;
- const auto& trait = *trait_info.second;
-
- switch( pc )
+
+ this->visit_type( *e.type );
+ this->visit_path_params( e.params );
+
+ // TODO: Search for matching impls in current generic blocks
+ if( m_item_params != nullptr && locate_trait_item_in_bounds(pc, *e.type, e.item, *m_item_params) ) {
+ return ;
+ }
+ if( m_impl_params != nullptr && locate_trait_item_in_bounds(pc, *e.type, e.item, *m_impl_params) ) {
+ 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 ) {
+ switch(pc)
+ {
+ case ::HIR::Visitor::PathContext::VALUE: {
+ auto it1 = m_current_trait->m_values.find( e.item );
+ if( it1 != m_current_trait->m_values.end() ) {
+ TODO(Span(), "Found in Self trait - need path to trait");
+ // TODO: What's the easiest way to get the path to this trait?
+ //auto new_data = ::HIR::Path::Data::make_UfcsKnown({ mv$(e.type), ::HIR::GenericPath(trait_path), mv$(e.item), mv$(e.params)} );
+ //p.m_data = mv$(new_data);
+ //DEBUG("- Resolved, replace with " << p);
+
+ return ;
+ }
+ } break;
+ case ::HIR::Visitor::PathContext::TRAIT:
+ break;
+ case ::HIR::Visitor::PathContext::TYPE: {
+ auto it1 = m_current_trait->m_types.find( e.item );
+ if( it1 != m_current_trait->m_types.end() ) {
+ TODO(Span(), "Found in Self trait - need path to trait");
+ return ;
+ }
+ } break;
+ }
+ }
+ ERROR(Span(), E0000, "Failed to find impl with '" << e.item << "' for " << *e.type);
+ return ;
+ )
+ else {
+ // 1. Search all impls of in-scope traits for this method on this type
+ for( const auto& trait_info : m_traits )
{
- case ::HIR::Visitor::PathContext::VALUE: {
- auto it1 = trait.m_values.find( e.item );
- if( it1 == trait.m_values.end() ) {
- continue ;
+ const auto& trait_path = *trait_info.first;
+ const auto& trait = *trait_info.second;
+
+ switch( pc )
+ {
+ case ::HIR::Visitor::PathContext::VALUE: {
+ auto it1 = trait.m_values.find( e.item );
+ if( it1 == trait.m_values.end() ) {
+ continue ;
+ }
+ // Found it, just keep going (don't care about details here)
+ } break;
+ case ::HIR::Visitor::PathContext::TRAIT:
+ case ::HIR::Visitor::PathContext::TYPE: {
+ auto it1 = trait.m_types.find( e.item );
+ if( it1 == trait.m_types.end() ) {
+ continue ;
+ }
+ // Found it, just keep going (don't care about details here)
+ } break;
}
- // Found it, just keep going (don't care about details here)
- } break;
- case ::HIR::Visitor::PathContext::TRAIT:
- case ::HIR::Visitor::PathContext::TYPE: {
- auto it1 = trait.m_types.find( e.item );
- if( it1 == trait.m_types.end() ) {
+
+ auto trait_impl_it = m_crate.m_trait_impls.equal_range( trait_path );
+ if( trait_impl_it.first == trait_impl_it.second ) {
continue ;
}
- // Found it, just keep going (don't care about details here)
- } break;
- }
-
- auto trait_impl_it = m_crate.m_trait_impls.equal_range( trait_path );
- if( trait_impl_it.first == trait_impl_it.second ) {
- continue ;
+ for( auto it = trait_impl_it.first; it != trait_impl_it.second; it ++ )
+ {
+ const auto& impl = it->second;
+ if( !impl.matches_type(*e.type) ) {
+ continue ;
+ }
+
+ auto new_data = ::HIR::Path::Data::make_UfcsKnown({ mv$(e.type), ::HIR::GenericPath(trait_path), mv$(e.item), mv$(e.params)} );
+ p.m_data = mv$(new_data);
+ DEBUG("- Resolved, replace with " << p);
+ return ;
+ }
}
- for( auto it = trait_impl_it.first; it != trait_impl_it.second; it ++ )
+
+ // 2. No trait matched, search for inherent impl
+ for( const auto& impl : m_crate.m_type_impls )
{
- const auto& impl = it->second;
if( !impl.matches_type(*e.type) ) {
continue ;
}
+ DEBUG("- matched impl " << *e.type);
+ // TODO: Search for item
+ switch( pc )
+ {
+ case ::HIR::Visitor::PathContext::VALUE: {
+ auto it1 = impl.m_methods.find( e.item );
+ if( it1 == impl.m_methods.end() ) {
+ continue ;
+ }
+ // Found it, just keep going (don't care about details here)
+ } break;
+ case ::HIR::Visitor::PathContext::TRAIT:
+ case ::HIR::Visitor::PathContext::TYPE:
+ continue ;
+ }
- auto new_data = ::HIR::Path::Data::make_UfcsKnown({ mv$(e.type), ::HIR::GenericPath(trait_path), mv$(e.item), mv$(e.params)} );
+ auto new_data = ::HIR::Path::Data::make_UfcsInherent({ mv$(e.type), mv$(e.item), mv$(e.params)} );
p.m_data = mv$(new_data);
DEBUG("- Resolved, replace with " << p);
return ;
}
}
- // 2. No trait matched, search for inherent impl
- for( const auto& impl : m_crate.m_type_impls )
- {
- if( !impl.matches_type(*e.type) ) {
- continue ;
- }
- DEBUG("- matched impl " << *e.type);
- // TODO: Search for item
- switch( pc )
- {
- case ::HIR::Visitor::PathContext::VALUE: {
- auto it1 = impl.m_methods.find( e.item );
- if( it1 == impl.m_methods.end() ) {
- continue ;
- }
- // Found it, just keep going (don't care about details here)
- } break;
- case ::HIR::Visitor::PathContext::TRAIT:
- case ::HIR::Visitor::PathContext::TYPE: {
- continue ;
- // Found it, just keep going (don't care about details here)
- } break;
- }
-
- auto new_data = ::HIR::Path::Data::make_UfcsInherent({ mv$(e.type), mv$(e.item), mv$(e.params)} );
- p.m_data = mv$(new_data);
- DEBUG("- Resolved, replace with " << p);
- return ;
- }
-
// Couldn't find it
DEBUG("Failed to find impl with '" << e.item << "' for " << *e.type);
)
+ else {
+ ::HIR::Visitor::visit_path(p, pc);
+ }
}