diff options
author | John Hodge <tpg@mutabah.net> | 2016-06-05 16:27:28 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-06-05 16:27:28 +0800 |
commit | e3f35882f8240e506e34bb37c8fef1ca34601882 (patch) | |
tree | bb77cf090418079e6c405eb6c71fcf1b7f52c696 /src/hir_conv/resolve_ufcs.cpp | |
parent | a0c00721f5b9d79035e522577b0f127df5849cfb (diff) | |
download | mrust-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.cpp | 188 |
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); + } } |