diff options
author | John Hodge <tpg@mutabah.net> | 2016-06-05 20:37:45 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-06-05 20:37:45 +0800 |
commit | 52eb59ef0e0eedb8ea4da2210c5357245e523dfd (patch) | |
tree | 5f2a1483b0a1dd3ce3f0b1edaab8d55b90be276d | |
parent | e3f35882f8240e506e34bb37c8fef1ca34601882 (diff) | |
download | mrust-52eb59ef0e0eedb8ea4da2210c5357245e523dfd.tar.gz |
Resolve - UFCS resolution expanded to handle `Self` and params
-rw-r--r-- | src/hir/path.hpp | 4 | ||||
-rw-r--r-- | src/hir/type.cpp | 72 | ||||
-rw-r--r-- | src/hir/type.hpp | 3 | ||||
-rw-r--r-- | src/hir/visitor.cpp | 46 | ||||
-rw-r--r-- | src/hir/visitor.hpp | 56 | ||||
-rw-r--r-- | src/hir_conv/constant_evaluation.cpp | 4 | ||||
-rw-r--r-- | src/hir_conv/resolve_ufcs.cpp | 218 | ||||
-rw-r--r-- | src/hir_typeck/expr.cpp | 12 | ||||
-rw-r--r-- | src/hir_typeck/outer.cpp | 4 |
9 files changed, 313 insertions, 106 deletions
diff --git a/src/hir/path.hpp b/src/hir/path.hpp index 02aedba4..9610a076 100644 --- a/src/hir/path.hpp +++ b/src/hir/path.hpp @@ -53,6 +53,10 @@ struct PathParams PathParams(); PathParams clone() const; + PathParams(const PathParams&) = delete; + PathParams& operator=(const PathParams&) = delete; + PathParams(PathParams&&) = default; + PathParams& operator=(PathParams&&) = default; //bool operator==(const PathParams& x) const; //bool operator<(const PathParams& x) const; diff --git a/src/hir/type.cpp b/src/hir/type.cpp index 32d317a0..a5f04df5 100644 --- a/src/hir/type.cpp +++ b/src/hir/type.cpp @@ -112,6 +112,78 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const ) ) } +bool ::HIR::TypeRef::operator==(const ::HIR::TypeRef& x) const +{ + if( m_data.tag() != x.m_data.tag() ) + return false; + + TU_MATCH(::HIR::TypeRef::Data, (m_data, x.m_data), (te, xe), + (Infer, + // TODO: Should comparing inferrence vars be an error? + return true; + ), + (Diverge, + return true; + ), + (Primitive, + return te == xe; + ), + (Path, + assert(!"TODO: Compare path types"); + ), + (Generic, + return te.name == xe.name && te.binding == xe.binding; + ), + (TraitObject, + assert(!"TODO: Compare trait object types"); + ), + (Array, + if( *te.inner != *xe.inner ) + return false; + if( xe.size_val != te.size_val ) + return false; + if( te.size_val == ~0u ) + assert(!"TOD: Compre array types with non-resolved sizes"); + return true; + ), + (Slice, + return *te.inner == *xe.inner; + ), + (Tuple, + if( te.size() != xe.size() ) + return false; + for(unsigned int i = 0; i < te.size(); i ++ ) { + if( te[i] != xe[i] ) + return false; + } + return true; + ), + (Borrow, + if( te.type != xe.type ) + return false; + return *te.inner == *xe.inner; + ), + (Pointer, + if( te.is_mut != xe.is_mut ) + return false; + return *te.inner == *xe.inner; + ), + (Function, + if( te.is_unsafe != xe.is_unsafe ) + return false; + if( te.m_abi != xe.m_abi ) + return false; + if( te.m_arg_types.size() != xe.m_arg_types.size() ) + return false; + for(unsigned int i = 0; i < te.m_arg_types.size(); i ++ ) { + if( te.m_arg_types[i] != xe.m_arg_types[i] ) + return false; + } + return te.m_rettype == xe.m_rettype; + ) + ) + throw ""; +} namespace { ::HIR::TypeRef::TypePathBinding clone_binding(const ::HIR::TypeRef::TypePathBinding& x) { diff --git a/src/hir/type.hpp b/src/hir/type.hpp index 82b77067..793dce4d 100644 --- a/src/hir/type.hpp +++ b/src/hir/type.hpp @@ -149,6 +149,9 @@ public: TypeRef clone() const; void fmt(::std::ostream& os) const; + + bool operator==(const ::HIR::TypeRef& x) const; + bool operator!=(const ::HIR::TypeRef& x) const { return !(*this == x); } }; extern ::std::ostream& operator<<(::std::ostream& os, const ::HIR::TypeRef& ty); diff --git a/src/hir/visitor.cpp b/src/hir/visitor.cpp index d2ee9f74..d4eeec50 100644 --- a/src/hir/visitor.cpp +++ b/src/hir/visitor.cpp @@ -8,7 +8,7 @@ void ::HIR::Visitor::visit_crate(::HIR::Crate& crate) { - this->visit_module( crate.m_root_module ); + this->visit_module(::HIR::PathChain(""), crate.m_root_module ); for( auto& ty_impl : crate.m_type_impls ) { @@ -24,7 +24,7 @@ void ::HIR::Visitor::visit_crate(::HIR::Crate& crate) } } -void ::HIR::Visitor::visit_module(::HIR::Module& mod) +void ::HIR::Visitor::visit_module(::HIR::PathChain p, ::HIR::Module& mod) { TRACE_FUNCTION; for( auto& named : mod.m_mod_items ) @@ -35,23 +35,23 @@ void ::HIR::Visitor::visit_module(::HIR::Module& mod) (Import, ), (Module, DEBUG("mod " << name); - this->visit_module(e); + this->visit_module(p + name, e); ), (TypeAlias, DEBUG("type " << name); - this->visit_type_alias(e); + this->visit_type_alias(p + name, e); ), (Enum, DEBUG("enum " << name); - this->visit_enum(e); + this->visit_enum(p + name, e); ), (Struct, DEBUG("struct " << name); - this->visit_struct(e); + this->visit_struct(p + name, e); ), (Trait, DEBUG("trait " << name); - this->visit_trait(e); + this->visit_trait(p + name, e); ) ) } @@ -65,18 +65,18 @@ void ::HIR::Visitor::visit_module(::HIR::Module& mod) ), (Constant, DEBUG("const " << name); - this->visit_constant(e); + this->visit_constant(p + name, e); ), (Static, DEBUG("static " << name); - this->visit_static(e); + this->visit_static(p + name, e); ), (StructConstant, // Just a path ), (Function, DEBUG("fn " << name); - this->visit_function(e); + this->visit_function(p + name, e); ), (StructConstructor, // Just a path @@ -88,17 +88,19 @@ void ::HIR::Visitor::visit_module(::HIR::Module& mod) void ::HIR::Visitor::visit_type_impl(::HIR::TypeImpl& impl) { + ::HIR::PathChain p { "#impl" }; TRACE_FUNCTION_F("impl.m_type=" << impl.m_type); this->visit_params(impl.m_params); this->visit_type(impl.m_type); for(auto& method : impl.m_methods) { DEBUG("method " << method.first); - this->visit_function(method.second); + this->visit_function(p + method.first, method.second); } } void ::HIR::Visitor::visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl) { + ::HIR::PathChain p { "#impl" }; TRACE_FUNCTION_F("trait_path=" << trait_path); this->visit_params(impl.m_params); this->visit_path_params(impl.m_trait_args); @@ -106,7 +108,7 @@ void ::HIR::Visitor::visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR for(auto& ent : impl.m_methods) { DEBUG("method " << ent.first); - this->visit_function(ent.second); + this->visit_function(p + ent.first, ent.second); } for(auto& ent : impl.m_constants) { DEBUG("const " << ent.first); @@ -124,12 +126,12 @@ void ::HIR::Visitor::visit_marker_impl(const ::HIR::SimplePath& trait_path, ::HI this->visit_type(impl.m_type); } -void ::HIR::Visitor::visit_type_alias(::HIR::TypeAlias& item) +void ::HIR::Visitor::visit_type_alias(::HIR::PathChain p, ::HIR::TypeAlias& item) { this->visit_params(item.m_params); this->visit_type(item.m_type); } -void ::HIR::Visitor::visit_trait(::HIR::Trait& item) +void ::HIR::Visitor::visit_trait(::HIR::PathChain p, ::HIR::Trait& item) { TRACE_FUNCTION; this->visit_params(item.m_params); @@ -146,20 +148,20 @@ void ::HIR::Visitor::visit_trait(::HIR::Trait& item) (None, ), (Constant, DEBUG("constant " << i.first); - this->visit_constant(e); + this->visit_constant(p + i.first, e); ), (Static, DEBUG("static " << i.first); - this->visit_static(e); + this->visit_static(p + i.first, e); ), (Function, DEBUG("method " << i.first); - this->visit_function(e); + this->visit_function(p + i.first, e); ) ) } } -void ::HIR::Visitor::visit_struct(::HIR::Struct& item) +void ::HIR::Visitor::visit_struct(::HIR::PathChain p, ::HIR::Struct& item) { this->visit_params(item.m_params); TU_MATCH(::HIR::Struct::Data, (item.m_data), (e), @@ -177,7 +179,7 @@ void ::HIR::Visitor::visit_struct(::HIR::Struct& item) ) ) } -void ::HIR::Visitor::visit_enum(::HIR::Enum& item) +void ::HIR::Visitor::visit_enum(::HIR::PathChain p, ::HIR::Enum& item) { this->visit_params(item.m_params); for(auto& var : item.m_variants) @@ -201,7 +203,7 @@ void ::HIR::Visitor::visit_enum(::HIR::Enum& item) ) } } -void ::HIR::Visitor::visit_function(::HIR::Function& item) +void ::HIR::Visitor::visit_function(::HIR::PathChain p, ::HIR::Function& item) { this->visit_params(item.m_params); for(auto& arg : item.m_args) @@ -212,12 +214,12 @@ void ::HIR::Visitor::visit_function(::HIR::Function& item) this->visit_type(item.m_return); this->visit_expr(item.m_code); } -void ::HIR::Visitor::visit_static(::HIR::Static& item) +void ::HIR::Visitor::visit_static(::HIR::PathChain p, ::HIR::Static& item) { this->visit_type(item.m_type); this->visit_expr(item.m_value); } -void ::HIR::Visitor::visit_constant(::HIR::Constant& item) +void ::HIR::Visitor::visit_constant(::HIR::PathChain p, ::HIR::Constant& item) { this->visit_params(item.m_params); this->visit_type(item.m_type); diff --git a/src/hir/visitor.hpp b/src/hir/visitor.hpp index ffeb7338..fb71ba35 100644 --- a/src/hir/visitor.hpp +++ b/src/hir/visitor.hpp @@ -6,6 +6,46 @@ namespace HIR { +class PathChain +{ + const PathChain* prev; + const ::std::string& name; +public: + PathChain(const PathChain& prev, const ::std::string& name): + prev(&prev), + name(name) + {} + PathChain(const ::std::string& name): + prev(nullptr), + name(name) + {} + + PathChain operator+(const ::std::string& name) const { + return PathChain(*this, name); + } + + ::HIR::SimplePath to_path() const { + if( prev ) { + return prev->to_path() + name; + } + else { + if( name != "" ) { + return ::HIR::SimplePath("", {name}); + } + else { + return ::HIR::SimplePath("", {}); + } + } + } + + friend ::std::ostream& operator<<(::std::ostream& os, const PathChain& x) { + if( x.prev ) + os << *x.prev << "::"; + os << x.name; + return os; + } +}; + class Visitor { public: @@ -13,21 +53,21 @@ public: virtual void visit_crate(::HIR::Crate& crate); - virtual void visit_module(::HIR::Module& mod); + virtual void visit_module(PathChain p, ::HIR::Module& mod); virtual void visit_type_impl(::HIR::TypeImpl& impl); virtual void visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl); virtual void visit_marker_impl(const ::HIR::SimplePath& trait_path, ::HIR::MarkerImpl& impl); // - Type Items - virtual void visit_type_alias(::HIR::TypeAlias& item); - virtual void visit_trait(::HIR::Trait& item); - virtual void visit_struct(::HIR::Struct& item); - virtual void visit_enum(::HIR::Enum& item); + virtual void visit_type_alias(PathChain p, ::HIR::TypeAlias& item); + virtual void visit_trait(PathChain p, ::HIR::Trait& item); + virtual void visit_struct(PathChain p, ::HIR::Struct& item); + virtual void visit_enum(PathChain p, ::HIR::Enum& item); // - Value Items - virtual void visit_function(::HIR::Function& item); - virtual void visit_static(::HIR::Static& item); - virtual void visit_constant(::HIR::Constant& item); + virtual void visit_function(PathChain p, ::HIR::Function& item); + virtual void visit_static(PathChain p, ::HIR::Static& item); + virtual void visit_constant(PathChain p, ::HIR::Constant& item); // - Misc virtual void visit_params(::HIR::GenericParams& params); diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index 3ec3d4f2..da7e6713 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -540,13 +540,13 @@ namespace { ::HIR::Visitor::visit_type(ty); } } - void visit_constant(::HIR::Constant& item) override + void visit_constant(::HIR::PathChain p, ::HIR::Constant& item) override { visit_type(item.m_type); item.m_value_res = evaluate_constant(m_crate, *item.m_value); DEBUG("constant: " << item.m_type << " = " << item.m_value_res); } - void visit_static(::HIR::Static& item) override + void visit_static(::HIR::PathChain p, ::HIR::Static& item) override { visit_type(item.m_type); item.m_value_res = evaluate_constant(m_crate, *item.m_value); diff --git a/src/hir_conv/resolve_ufcs.cpp b/src/hir_conv/resolve_ufcs.cpp index 295de1b0..bd5c0a4f 100644 --- a/src/hir_conv/resolve_ufcs.cpp +++ b/src/hir_conv/resolve_ufcs.cpp @@ -19,6 +19,7 @@ namespace { const ::HIR::GenericParams* m_impl_params; const ::HIR::GenericParams* m_item_params; const ::HIR::Trait* m_current_trait; + const ::HIR::PathChain* m_current_trait_path; public: Visitor(const ::HIR::Crate& crate): @@ -28,27 +29,48 @@ namespace { m_current_trait(nullptr) {} - void visit_module(::HIR::Module& mod) override + void visit_module(::HIR::PathChain p, ::HIR::Module& mod) override { for( const auto& trait_path : mod.m_traits ) m_traits.push_back( ::std::make_pair( &trait_path, &this->find_trait(trait_path) ) ); - ::HIR::Visitor::visit_module(mod); + ::HIR::Visitor::visit_module(p, mod); for(unsigned int i = 0; i < mod.m_traits.size(); i ++ ) m_traits.pop_back(); } - void visit_function(::HIR::Function& fcn) override { + void visit_struct(::HIR::PathChain p, ::HIR::Struct& fcn) override { m_item_params = &fcn.m_params; - ::HIR::Visitor::visit_function(fcn); + ::HIR::Visitor::visit_struct(p, fcn); m_item_params = nullptr; } - void visit_trait(::HIR::Trait& trait) override { + void visit_enum(::HIR::PathChain p, ::HIR::Enum& fcn) override { + m_item_params = &fcn.m_params; + ::HIR::Visitor::visit_enum(p, fcn); + m_item_params = nullptr; + } + void visit_function(::HIR::PathChain p, ::HIR::Function& fcn) override { + m_item_params = &fcn.m_params; + ::HIR::Visitor::visit_function(p, fcn); + m_item_params = nullptr; + } + void visit_trait(::HIR::PathChain p, ::HIR::Trait& trait) override { m_current_trait = &trait; + m_current_trait_path = &p; m_impl_params = &trait.m_params; - ::HIR::Visitor::visit_trait(trait); + ::HIR::Visitor::visit_trait(p, trait); m_impl_params = nullptr; m_current_trait = nullptr; } + void visit_type_impl(::HIR::TypeImpl& impl) override { + 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) { + m_impl_params = &impl.m_params; + ::HIR::Visitor::visit_trait_impl(trait_path, impl); + m_impl_params = nullptr; + } void visit_expr(::HIR::ExprPtr& expr) override { @@ -110,8 +132,113 @@ namespace { } } - bool locate_trait_item_in_bounds(::HIR::Visitor::PathContext pc, const ::HIR::TypeRef& tr, const ::std::string& name, const ::HIR::GenericParams& params) { + 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"); + for(const auto& b : params.m_bounds) + { + TU_IFLET(::HIR::GenericBound, b, TraitBound, e, + 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) ) { + return true; + } + } + ); + // - + } + return false; + } + static ::HIR::Path::Data get_ufcs_known(::HIR::Path::Data::Data_UfcsUnknown e, ::HIR::GenericPath trait_path, const ::HIR::Trait& trait) + { + return ::HIR::Path::Data::make_UfcsKnown({ mv$(e.type), mv$(trait_path), mv$(e.item), mv$(e.params)} ); + } + static bool locate_item_in_trait(::HIR::Visitor::PathContext pc, const ::HIR::Trait& trait, ::HIR::Path::Data& pd) + { + 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(0) + 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; + } + + return true; + } + return false; + } + static ::HIR::GenericPath make_generic_path(::HIR::SimplePath sp, const ::HIR::Trait& trait) + { + auto trait_path_g = ::HIR::GenericPath( mv$(sp) ); + for(unsigned int i = 0; i < trait.m_params.m_types.size(); i ++ ) { + trait_path_g.m_params.m_types.push_back( ::HIR::TypeRef(trait.m_params.m_types[i].m_name, i) ); + } + return trait_path_g; + } + // 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) { + if( locate_item_in_trait(pc, trait, pd) ) { + pd = get_ufcs_known(mv$(pd.as_UfcsUnknown()), make_generic_path(trait_path.m_path, trait), trait); + return true; + } + // 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]; + //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) ) { + return true; + } + } + 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) { + 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 ) + { + // 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 ++ ) + { + const auto& impl = it->second; + if( impl.matches_type(type) ) + { + pd = get_ufcs_known(mv$(e), make_generic_path(trait_path.m_path, trait), trait); + return true; + } + } + } + + + // 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]; + //const auto& par_trait_ent = *trait.m_parent_trait_ptrs[i]; + const auto& par_trait_ent = this->find_trait(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; + } + } return false; } @@ -124,11 +251,11 @@ namespace { 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) ) { + // Search for matching impls in current generic blocks + if( m_item_params != nullptr && locate_trait_item_in_bounds(pc, *e.type, *m_item_params, p.m_data) ) { return ; } - if( m_impl_params != nullptr && locate_trait_item_in_bounds(pc, *e.type, e.item, *m_impl_params) ) { + if( m_impl_params != nullptr && locate_trait_item_in_bounds(pc, *e.type, *m_impl_params, p.m_data) ) { return ; } @@ -136,29 +263,13 @@ namespace { // 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; + auto trait_path = ::HIR::GenericPath( m_current_trait_path->to_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! + return ; } } ERROR(Span(), E0000, "Failed to find impl with '" << e.item << "' for " << *e.type); @@ -168,42 +279,17 @@ namespace { // 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 ) - { - 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; - } - - auto trait_impl_it = m_crate.m_trait_impls.equal_range( trait_path ); - if( trait_impl_it.first == trait_impl_it.second ) { - continue ; + 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() ); } - 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); + + // 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 ; } } diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp index c2c2abb9..1b80b9cc 100644 --- a/src/hir_typeck/expr.cpp +++ b/src/hir_typeck/expr.cpp @@ -1386,12 +1386,12 @@ namespace { TODO(Span(), "visit_expr"); } - void visit_trait(::HIR::Trait& item) override + void visit_trait(::HIR::PathChain p, ::HIR::Trait& item) override { //::HIR::TypeRef tr { "Self", 0 }; auto _ = this->set_impl_generics(item.m_params); //m_self_types.push_back(&tr); - ::HIR::Visitor::visit_trait(item); + ::HIR::Visitor::visit_trait(p, item); //m_self_types.pop_back(); } @@ -1444,7 +1444,7 @@ namespace { // ------ // Code-containing items // ------ - void visit_function(::HIR::Function& item) override { + void visit_function(::HIR::PathChain p, ::HIR::Function& item) override { auto _ = this->set_item_generics(item.m_params); if( item.m_code ) { @@ -1456,7 +1456,7 @@ namespace { Typecheck_Code( mv$(typeck_context), item.m_return, item.m_code ); } } - void visit_static(::HIR::Static& item) override { + void visit_static(::HIR::PathChain p, ::HIR::Static& item) override { //auto _ = this->set_item_generics(item.m_params); if( item.m_value ) { @@ -1465,7 +1465,7 @@ namespace { Typecheck_Code( mv$(typeck_context), item.m_type, item.m_value ); } } - void visit_constant(::HIR::Constant& item) override { + void visit_constant(::HIR::PathChain p, ::HIR::Constant& item) override { auto _ = this->set_item_generics(item.m_params); if( item.m_value ) { @@ -1474,7 +1474,7 @@ namespace { Typecheck_Code( mv$(typeck_context), item.m_type, item.m_value ); } } - void visit_enum(::HIR::Enum& item) override { + void visit_enum(::HIR::PathChain p, ::HIR::Enum& item) override { auto _ = this->set_item_generics(item.m_params); // TODO: Use a different type depding on repr() diff --git a/src/hir_typeck/outer.cpp b/src/hir_typeck/outer.cpp index ff2b0477..9fc63f11 100644 --- a/src/hir_typeck/outer.cpp +++ b/src/hir_typeck/outer.cpp @@ -261,11 +261,11 @@ namespace { } } - void visit_trait(::HIR::Trait& item) override + void visit_trait(::HIR::PathChain p, ::HIR::Trait& item) override { ::HIR::TypeRef tr { "Self", 0 }; m_self_types.push_back(&tr); - ::HIR::Visitor::visit_trait(item); + ::HIR::Visitor::visit_trait(p, item); m_self_types.pop_back(); } |