diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hir_conv/constant_evaluation.cpp | 9 | ||||
-rw-r--r-- | src/hir_conv/resolve_ufcs.cpp | 119 | ||||
-rw-r--r-- | src/hir_typeck/outer.cpp | 2 | ||||
-rw-r--r-- | src/resolve/absolute.cpp | 8 |
4 files changed, 85 insertions, 53 deletions
diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index fe1c46ca..286981f7 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -379,9 +379,12 @@ namespace { } } - const_cast<HIR::ExprNode&>(*fcn.m_code).visit( *this ); - assert( ! m_rv.is_Invalid() ); - //TODO(node.span(), "exec const fn - " << node.m_path); + // Call by running the code directly + { + TRACE_FUNCTION_F("Call const fn " << node.m_path); + const_cast<HIR::ExprNode&>(*fcn.m_code).visit( *this ); + assert( ! m_rv.is_Invalid() ); + } for(unsigned int i = 0; i < fcn.m_args.size(); i ++ ) { diff --git a/src/hir_conv/resolve_ufcs.cpp b/src/hir_conv/resolve_ufcs.cpp index 509faddf..0d8029c9 100644 --- a/src/hir_conv/resolve_ufcs.cpp +++ b/src/hir_conv/resolve_ufcs.cpp @@ -14,7 +14,8 @@ namespace { { const ::HIR::Crate& m_crate; - ::std::vector< ::std::pair< const ::HIR::SimplePath*, const ::HIR::Trait* > > m_traits; + typedef ::std::vector< ::std::pair< const ::HIR::SimplePath*, const ::HIR::Trait* > > t_trait_imports; + t_trait_imports m_traits; const ::HIR::GenericParams* m_impl_params; const ::HIR::GenericParams* m_item_params; @@ -29,13 +30,24 @@ namespace { m_current_trait(nullptr) {} - void visit_module(::HIR::PathChain p, ::HIR::Module& mod) override - { + struct ModTraitsGuard { + Visitor* v; + t_trait_imports old_imports; + + ~ModTraitsGuard() { + this->v->m_traits = mv$(this->old_imports); + } + }; + ModTraitsGuard push_mod_traits(const ::HIR::Module& mod) { + auto rv = ModTraitsGuard { this, mv$(this->m_traits) }; for( const auto& trait_path : mod.m_traits ) m_traits.push_back( ::std::make_pair( &trait_path, &this->find_trait(trait_path) ) ); + return rv; + } + void visit_module(::HIR::PathChain p, ::HIR::Module& mod) override + { + auto _ = this->push_mod_traits( mod ); ::HIR::Visitor::visit_module(p, mod); - for(unsigned int i = 0; i < mod.m_traits.size(); i ++ ) - m_traits.pop_back(); } void visit_struct(::HIR::PathChain p, ::HIR::Struct& fcn) override { @@ -62,11 +74,13 @@ namespace { m_current_trait = nullptr; } void visit_type_impl(::HIR::TypeImpl& impl) override { + auto _ = this->push_mod_traits( this->m_crate.get_mod_by_path(Span(), impl.m_src_module) ); m_impl_params = &impl.m_params; ::HIR::Visitor::visit_type_impl(impl); m_impl_params = nullptr; } void visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl) { + auto _ = this->push_mod_traits( this->m_crate.get_mod_by_path(Span(), impl.m_src_module) ); m_impl_params = &impl.m_params; ::HIR::Visitor::visit_trait_impl(trait_path, impl); m_impl_params = nullptr; @@ -164,23 +178,20 @@ namespace { { const auto& e = pd.as_UfcsUnknown(); - // TODO: Search super traits switch(pc) { case ::HIR::Visitor::PathContext::VALUE: - if( trait.m_values.find( e.item ) == trait.m_values.end() ) { - break; + if( trait.m_values.find( e.item ) != trait.m_values.end() ) { + return true; } - if(0) + break; case ::HIR::Visitor::PathContext::TRAIT: break; - if(0) case ::HIR::Visitor::PathContext::TYPE: - if( trait.m_types.find( e.item ) == trait.m_types.end() ) { - break; + if( trait.m_types.find( e.item ) != trait.m_types.end() ) { + return true; } - - return true; + break; } return false; } @@ -211,20 +222,21 @@ namespace { } return false; } + bool locate_in_trait_impl_and_set(::HIR::Visitor::PathContext pc, 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) ) { - auto& e = pd.as_UfcsUnknown(); const auto& type = *e.type; auto trait_impl_it = this->m_crate.m_trait_impls.equal_range( trait_path.m_path ); - if( trait_impl_it.first != trait_impl_it.second ) - { + if( trait_impl_it.first == trait_impl_it.second ) { // Since this trait isn't implemented, none of the supertraits matter return false; } - for( auto it = trait_impl_it.first; it != trait_impl_it.second; it ++ ) + for( auto it = trait_impl_it.first; it != trait_impl_it.second; ++ it ) { const auto& impl = it->second; + DEBUG("impl" << impl.m_params.fmt_args() << " " << trait_path.m_path << impl.m_trait_args << " for " << impl.m_type); if( impl.matches_type(type) ) { pd = get_ufcs_known(mv$(e), make_generic_path(trait_path.m_path, trait), trait); @@ -232,6 +244,9 @@ namespace { } } } + else { + DEBUG("- Item " << e.item << " not in trait " << trait_path.m_path); + } // Search supertraits (recursively) @@ -250,6 +265,8 @@ namespace { void visit_path(::HIR::Path& p, ::HIR::Visitor::PathContext pc) override { + auto sp = Span(); + DEBUG("p = " << p); TU_IFLET(::HIR::Path::Data, p.m_data, UfcsUnknown, e, DEBUG("UfcsUnknown - p=" << p); @@ -278,45 +295,26 @@ namespace { return ; } } - ERROR(Span(), E0000, "Failed to find impl with '" << e.item << "' for " << *e.type); + ERROR(sp, 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 ) - { - const auto& trait = *trait_info.second; - - auto trait_path = ::HIR::GenericPath( *trait_info.first ); - for(unsigned int i = 0; i < trait.m_params.m_types.size(); i ++ ) { - trait_path.m_params.m_types.push_back( ::HIR::TypeRef() ); - } - - // TODO: Search supertraits - // TODO: Should impls be searched first, or item names? - // - Item names add complexity, but impls are slower - if( this->locate_in_trait_impl_and_set(pc, mv$(trait_path), trait, p.m_data) ) { - return ; - } - } - - // 2. No trait matched, search for inherent impl + // 1. Search for applicable inherent methods (COMES FIRST!) 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 + DEBUG("- matched inherent impl " << *e.type); + // Search for item in this block switch( pc ) { - case ::HIR::Visitor::PathContext::VALUE: { - auto it1 = impl.m_methods.find( e.item ); - if( it1 == impl.m_methods.end() ) { + case ::HIR::Visitor::PathContext::VALUE: + if( impl.m_methods.find(e.item) == impl.m_methods.end() ) { continue ; } // Found it, just keep going (don't care about details here) - } break; + break; case ::HIR::Visitor::PathContext::TRAIT: case ::HIR::Visitor::PathContext::TYPE: continue ; @@ -327,10 +325,41 @@ namespace { DEBUG("- Resolved, replace with " << p); return ; } + // 2. Search all impls of in-scope traits for this method on this type + for( const auto& trait_info : m_traits ) + { + const auto& trait = *trait_info.second; + + switch(pc) + { + case ::HIR::Visitor::PathContext::VALUE: + if( trait.m_values.find(e.item) == trait.m_values.end() ) + continue ; + break; + case ::HIR::Visitor::PathContext::TRAIT: + case ::HIR::Visitor::PathContext::TYPE: + if( trait.m_types.find(e.item) == trait.m_types.end() ) + continue ; + break; + } + DEBUG("- Looking for impl of " << *trait_info.first << " for " << *e.type); + + auto trait_path = ::HIR::GenericPath( *trait_info.first ); + for(unsigned int i = 0; i < trait.m_params.m_types.size(); i ++ ) { + trait_path.m_params.m_types.push_back( ::HIR::TypeRef() ); + } + + // TODO: Search supertraits + // TODO: Should impls be searched first, or item names? + // - Item names add complexity, but impls are slower + if( this->locate_in_trait_impl_and_set(pc, mv$(trait_path), trait, p.m_data) ) { + return ; + } + } } // Couldn't find it - DEBUG("Failed to find impl with '" << e.item << "' for " << *e.type); + ERROR(sp, E0000, "Failed to find impl with '" << e.item << "' for " << *e.type << " (in " << p << ")"); ) else { ::HIR::Visitor::visit_path(p, pc); diff --git a/src/hir_typeck/outer.cpp b/src/hir_typeck/outer.cpp index 8f33f120..e91278a8 100644 --- a/src/hir_typeck/outer.cpp +++ b/src/hir_typeck/outer.cpp @@ -228,7 +228,7 @@ namespace { // TODO: Locate impl block and check parameters ), (UfcsUnknown, - BUG(Span(), "Encountered unknown-trait UFCS path during outer typeck"); + BUG(Span(), "Encountered unknown-trait UFCS path during outer typeck - " << p); ) ) } diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp index 62b528a4..3e1e2ff4 100644 --- a/src/resolve/absolute.cpp +++ b/src/resolve/absolute.cpp @@ -363,7 +363,7 @@ struct Context ), (ConcreteSelf, if( ( mode == LookupMode::Type || mode == LookupMode::Namespace ) && name == "Self" ) { - return ::AST::Path( ::AST::Path::TagUfcs(), *e, ::std::vector< ::AST::PathNode>() ); + return ::AST::Path( ::AST::Path::TagUfcs(), *e, ::AST::Path(), ::std::vector< ::AST::PathNode>() ); } ), (VarBlock, @@ -411,7 +411,7 @@ struct Context auto ct = coretype_fromstring(name); if( ct != CORETYPE_INVAL ) { - return ::AST::Path( ::AST::Path::TagUfcs(), TypeRef(Span("-",0,0,0,0), ct), ::std::vector< ::AST::PathNode>() ); + return ::AST::Path( ::AST::Path::TagUfcs(), TypeRef(Span("-",0,0,0,0), ct), ::AST::Path(), ::std::vector< ::AST::PathNode>() ); } return AST::Path(); @@ -521,7 +521,7 @@ void Resolve_Absolute_Path_BindUFCS(Context& context, const Span& sp, Context::L } if( ufcs.nodes.size() == 0 ) { - if( mode == Context::LookupMode::Type && ! ufcs.trait ) { + if( mode == Context::LookupMode::Type && ufcs.trait && *ufcs.trait == ::AST::Path() ) { return ; } @@ -909,7 +909,7 @@ void Resolve_Absolute_Type(Context& context, TypeRef& type) (Path, Resolve_Absolute_Path(context, type.span(), Context::LookupMode::Type, e.path); TU_IFLET(::AST::Path::Class, e.path.m_class, UFCS, ufcs, - if( ufcs.nodes.size() == 0 && ! ufcs.trait ) { + if( ufcs.nodes.size() == 0 /*&& ufcs.trait && *ufcs.trait == ::AST::Path()*/ ) { auto ty = mv$(*ufcs.type); type = mv$(ty); return ; |