summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-06-05 20:37:45 +0800
committerJohn Hodge <tpg@mutabah.net>2016-06-05 20:37:45 +0800
commit52eb59ef0e0eedb8ea4da2210c5357245e523dfd (patch)
tree5f2a1483b0a1dd3ce3f0b1edaab8d55b90be276d
parente3f35882f8240e506e34bb37c8fef1ca34601882 (diff)
downloadmrust-52eb59ef0e0eedb8ea4da2210c5357245e523dfd.tar.gz
Resolve - UFCS resolution expanded to handle `Self` and params
-rw-r--r--src/hir/path.hpp4
-rw-r--r--src/hir/type.cpp72
-rw-r--r--src/hir/type.hpp3
-rw-r--r--src/hir/visitor.cpp46
-rw-r--r--src/hir/visitor.hpp56
-rw-r--r--src/hir_conv/constant_evaluation.cpp4
-rw-r--r--src/hir_conv/resolve_ufcs.cpp218
-rw-r--r--src/hir_typeck/expr.cpp12
-rw-r--r--src/hir_typeck/outer.cpp4
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();
}