summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-05-29 08:50:39 +0800
committerJohn Hodge <tpg@mutabah.net>2016-05-29 08:50:39 +0800
commita8d2de3db9d9f92013d0ac6e52319b55590efea4 (patch)
tree1f85c37a21df5379518f2567a34eb3f174cb790f
parent727e254fe58274741036ca31f4c3eae2f3e1695a (diff)
downloadmrust-a8d2de3db9d9f92013d0ac6e52319b55590efea4.tar.gz
AST - Remove dead code, add lifetime params, fix param clobber
-rw-r--r--src/ast/ast.cpp28
-rw-r--r--src/ast/path.cpp192
-rw-r--r--src/ast/path.hpp38
-rw-r--r--src/ast/types.cpp381
-rw-r--r--src/ast/types.hpp17
-rw-r--r--src/common.hpp50
-rw-r--r--src/expand/derive.cpp6
-rw-r--r--src/expand/lang_item.cpp2
-rw-r--r--src/hir/from_ast.cpp7
-rw-r--r--src/hir/from_ast_expr.cpp2
-rw-r--r--src/include/span.hpp2
-rw-r--r--src/main.cpp4
-rw-r--r--src/parse/common.hpp2
-rw-r--r--src/parse/paths.cpp36
-rw-r--r--src/resolve/absolute.cpp43
15 files changed, 157 insertions, 653 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp
index 802bde37..77981a4d 100644
--- a/src/ast/ast.cpp
+++ b/src/ast/ast.cpp
@@ -495,34 +495,6 @@ SERIALISE_TYPE(Enum::, "AST_Enum", {
s.item(m_variants);
})
-TypeRef Struct::get_field_type(const char *name, const ::std::vector<TypeRef>& args)
-{
- if( args.size() != m_params.ty_params().size() )
- {
- throw ::std::runtime_error("Incorrect parameter count for struct");
- }
- // TODO: Should the bounds be checked here? Or is the count sufficient?
- for(const auto& f : m_data.as_Struct().ents)
- {
- if( f.m_name == name )
- {
- // Found it!
- if( args.size() )
- {
- TypeRef res = f.m_type;
- res.resolve_args( GenericResolveClosure(m_params, args) );
- return res;
- }
- else
- {
- return f.m_type;
- }
- }
- }
-
- throw ::std::runtime_error(FMT("No such field " << name));
-}
-
SERIALISE_TYPE(Struct::, "AST_Struct", {
s << m_params;
s << m_data;
diff --git a/src/ast/path.cpp b/src/ast/path.cpp
index be8b5887..bd5ffe1a 100644
--- a/src/ast/path.cpp
+++ b/src/ast/path.cpp
@@ -52,8 +52,42 @@ PathBinding PathBinding::clone() const
throw "BUG: Fell off the end of PathBinding::clone";
}
+::std::ostream& operator<<(::std::ostream& os, const PathParams& x)
+{
+ bool needs_comma = false;
+ os << "<";
+ for(const auto& v : x.m_lifetimes) {
+ if(needs_comma) os << ", ";
+ needs_comma = true;
+ os << "'" << v;
+ }
+ for(const auto& v : x.m_types) {
+ if(needs_comma) os << ", ";
+ needs_comma = true;
+ os << v;
+ }
+ for(const auto& v : x.m_assoc) {
+ if(needs_comma) os << ", ";
+ needs_comma = true;
+ os << v.first << "=" << v.second;
+ }
+ os << ">";
+ return os;
+}
+Ordering PathParams::ord(const PathParams& x) const
+{
+ Ordering rv;
+ rv = ::ord(m_lifetimes, x.m_lifetimes);
+ if(rv != OrdEqual) return rv;
+ rv = ::ord(m_types, x.m_types);
+ if(rv != OrdEqual) return rv;
+ rv = ::ord(m_assoc, x.m_assoc);
+ if(rv != OrdEqual) return rv;
+ return rv;
+}
+
// --- AST::PathNode
-PathNode::PathNode(::std::string name, ::std::vector<TypeRef> args):
+PathNode::PathNode(::std::string name, PathParams args):
m_name( mv$(name) ),
m_params( mv$(args) )
{
@@ -63,20 +97,18 @@ Ordering PathNode::ord(const PathNode& x) const
Ordering rv;
rv = ::ord(m_name, x.m_name);
if(rv != OrdEqual) return rv;
- rv = ::ord(m_params, x.m_params);
+ rv = m_params.ord(x.m_params);
if(rv != OrdEqual) return rv;
return OrdEqual;
}
void PathNode::print_pretty(::std::ostream& os, bool is_type_context) const
{
os << m_name;
- if( m_params.size() )
+ if( ! m_params.is_empty() )
{
if( ! is_type_context )
os << "::";
- os << "<";
os << m_params;
- os << ">";
}
}
::std::ostream& operator<<(::std::ostream& os, const PathNode& pn) {
@@ -85,10 +117,10 @@ void PathNode::print_pretty(::std::ostream& os, bool is_type_context) const
}
SERIALISE_TYPE(PathNode::, "PathNode", {
s << m_name;
- s << m_params;
+ //s << m_params;
},{
s.item(m_name);
- s.item(m_params);
+ //s.item(m_params);
})
/// Return an iterator to the named item
@@ -260,34 +292,6 @@ void Path::bind_trait(const Trait& ent, const ::std::vector<TypeRef>& /*args*/)
m_binding = PathBinding::make_Trait({&ent});
}
-void Path::resolve_args(::std::function<TypeRef(const char*)> fcn)
-{
- TRACE_FUNCTION_F(*this);
-
- TU_MATCH(Path::Class, (m_class), (ent),
- (Invalid),
- (Local, ),
-
- (Relative, Path::resolve_args_nl(ent.nodes, fcn); ),
- (Absolute, Path::resolve_args_nl(ent.nodes, fcn); ),
- (Self , Path::resolve_args_nl(ent.nodes, fcn); ),
- (Super , Path::resolve_args_nl(ent.nodes, fcn); ),
- (UFCS,
- ent.type->resolve_args(fcn);
- ent.trait->resolve_args(fcn);
- Path::resolve_args_nl(ent.nodes, fcn);
- )
- )
-}
-void Path::resolve_args_nl(::std::vector<PathNode>& nodes, ::std::function<TypeRef(const char*)> fcn)
-{
- for(auto& n : nodes)
- {
- for(auto& p : n.args())
- p.resolve_args(fcn);
- }
-}
-
Path& Path::operator+=(const Path& other)
{
for(auto& node : other.nodes())
@@ -297,124 +301,6 @@ Path& Path::operator+=(const Path& other)
return *this;
}
-/// Match two same-format (i.e. same components) paths together, calling TypeRef::match_args on arguments
-void Path::match_args(const Path& other, ::std::function<void(const char*,const TypeRef&)> fcn) const
-{
- // TODO: Ensure that the two paths are of a compatible class (same class?)
- // - This will crash atm if they aren't the same
- TU_MATCH(Path::Class, (m_class, other.m_class), (ent, x_ent),
- (Invalid),
- (Local, ),
-
- (Relative, Path::match_args_nl(ent.nodes, x_ent.nodes, fcn); ),
- (Absolute, Path::match_args_nl(ent.nodes, x_ent.nodes, fcn); ),
- (Self , Path::match_args_nl(ent.nodes, x_ent.nodes, fcn); ),
- (Super , Path::match_args_nl(ent.nodes, x_ent.nodes, fcn); ),
- (UFCS,
- Path::match_args_nl(ent.nodes, x_ent.nodes, fcn);
- throw ::std::runtime_error("TODO: UFCS Path::match_args");
- )
- )
-}
-
-void Path::match_args_nl(const ::std::vector<PathNode>& nodes_a, const ::std::vector<PathNode>& nodes_b, ::std::function<void(const char*,const TypeRef&)> fcn)
-{
- if( nodes_a.size() != nodes_b.size() )
- throw ::std::runtime_error("Type mismatch (path size)");
- for( unsigned int i = 0; i < nodes_a.size(); i++ )
- {
- auto& pn1 = nodes_a[i];
- auto& pn2 = nodes_b[i];
- if( pn1.name() != pn2.name() )
- throw ::std::runtime_error("Type mismatch (path component)");
- if( pn1.args().size() != pn2.args().size() )
- throw ::std::runtime_error("Type mismatch (path component param count)");
-
- for( unsigned int j = 0; j < pn1.args().size(); j ++ )
- {
- auto& t1 = pn1.args()[j];
- auto& t2 = pn2.args()[j];
- t1.match_args( t2, fcn );
- }
- }
-}
-
-bool Path::is_concrete() const
-{
- for(const auto& n : this->nodes())
- {
- for(const auto& p : n.args())
- if( not p.is_concrete() )
- return false;
- }
- return true;
-}
-
-/// Compare if two paths refer to the same non-generic item
-///
-/// - This doesn't handle the (impossible?) case where a generic might
-/// cause two different paths to look the same.
-int Path::equal_no_generic(const Path& x) const
-{
- if( m_class.is_Invalid() && x.m_class.is_Invalid() )
- return 0;
- DEBUG("equal_no_generic(this = " << *this << ", x = " << x << ")");
- if( m_class.tag() != x.m_class.tag() )
- return -1;
-
- TU_MATCH(Path::Class, (m_class, x.m_class), (ent, x_ent),
- (Invalid, return 0; ),
- (Local, return (ent.name == x_ent.name ? 0 : 1); ),
-
- (Relative, return Path::node_lists_equal_no_generic(ent.nodes, x_ent.nodes); ),
- (Absolute,
- if( ent.crate != x_ent.crate )
- return -1;
- return Path::node_lists_equal_no_generic(ent.nodes, x_ent.nodes);
- ),
- (Self , return Path::node_lists_equal_no_generic(ent.nodes, x_ent.nodes); ),
- (Super , return Path::node_lists_equal_no_generic(ent.nodes, x_ent.nodes); ),
- (UFCS,
- throw ::std::runtime_error("TODO: UFCS Path::equal_no_generic");
- return Path::node_lists_equal_no_generic(ent.nodes, x_ent.nodes);
- )
- )
- throw ::std::runtime_error("Path::equal_no_generic - fell off");
-}
-
-int Path::node_lists_equal_no_generic(const ::std::vector<PathNode>& nodes_a, const ::std::vector<PathNode>& nodes_b)
-{
- if( nodes_a.size() != nodes_b.size() ) {
- return -1;
- }
-
- bool conditional_match = false;
- unsigned int i = 0;
- for( const auto &e : nodes_a )
- {
- const auto& xe = nodes_b[i];
- if( e.name() != xe.name() )
- return -1;
-
- if( e.args().size() || xe.args().size() )
- {
- DEBUG("e = " << e << ", xe = " << xe);
- if( e.args().size() != xe.args().size() )
- throw CompileError::BugCheck("Generics should be resolved, and hence have the correct argument count");
- for( unsigned int j = 0; j < e.args().size(); j ++ )
- {
- int rv = e.args()[j].equal_no_generic( xe.args()[j] );
- if(rv < 0) return rv;
- if(rv > 0) conditional_match = true;
- }
- }
-
- i ++;
- }
-
- return (conditional_match ? 1 : 0);
-}
-
Ordering Path::ord(const Path& x) const
{
Ordering rv;
diff --git a/src/ast/path.hpp b/src/ast/path.hpp
index 4029f655..4b9cffa4 100644
--- a/src/ast/path.hpp
+++ b/src/ast/path.hpp
@@ -82,18 +82,33 @@ TAGGED_UNION_EX(PathBinding, (), Unbound, (
extern ::std::ostream& operator<<(::std::ostream& os, const PathBinding& x);
+struct PathParams
+{
+ ::std::vector< ::std::string > m_lifetimes;
+ ::std::vector< TypeRef > m_types;
+ ::std::vector< ::std::pair< ::std::string, TypeRef> > m_assoc;
+
+ bool is_empty() const {
+ return m_lifetimes.empty() && m_types.empty() && m_assoc.empty();
+ }
+
+ Ordering ord(const PathParams& x) const;
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const PathParams& x);
+};
class PathNode:
public ::Serialisable
{
::std::string m_name;
- ::std::vector<TypeRef> m_params;
+ PathParams m_params;
public:
PathNode() {}
- PathNode(::std::string name, ::std::vector<TypeRef> args = {});
+ PathNode(::std::string name, PathParams args = {});
const ::std::string& name() const { return m_name; }
- ::std::vector<TypeRef>& args() { return m_params; }
- const ::std::vector<TypeRef>& args() const { return m_params; }
+
+ const ::AST::PathParams& args() const { return m_params; }
+ ::AST::PathParams& args() { return m_params; }
Ordering ord(const PathNode& x) const;
void print_pretty(::std::ostream& os, bool is_type_context) const;
@@ -218,7 +233,7 @@ public:
;
else if( nodes().size() > 0 )
nodes().back().args() = b[0].args();
- else if( b[0].args().size() > 0 )
+ else if( ! b[0].args().is_empty() )
throw ::std::runtime_error("add_tail to empty path, but generics in source");
else {
}
@@ -247,12 +262,6 @@ public:
nodes().push_back(node);
m_binding = PathBinding();
}
-
- /// Resolve generic arguments within the path
- void resolve_args(::std::function<TypeRef(const char*)> fcn);
-
- /// Match args
- void match_args(const Path& other, ::std::function<void(const char*,const TypeRef&)> fcn) const;
bool is_trivial() const {
TU_MATCH_DEF(Class, (m_class), (e),
@@ -263,7 +272,7 @@ public:
return true;
),
(Relative,
- return e.nodes.size() == 1 && e.nodes[0].args().size() == 0;
+ return e.nodes.size() == 1 && e.nodes[0].args().is_empty();
)
)
}
@@ -311,9 +320,6 @@ public:
PathNode& operator[](int idx) { if(idx>=0) return nodes()[idx]; else return nodes()[size()+idx]; }
const PathNode& operator[](int idx) const { return (*(Path*)this)[idx]; }
- /// Returns 0 if paths are identical, 1 if TypeRef::TagArg is present in one, and -1 if a node differs
- int equal_no_generic(const Path& x) const;
-
Ordering ord(const Path& x) const;
bool operator==(const Path& x) const { return ord(x) == OrdEqual; }
bool operator!=(const Path& x) const { return ord(x) != OrdEqual; }
@@ -327,8 +333,6 @@ public:
friend void operator>>(Deserialiser& s, Path::Class& pc);
private:
static void resolve_args_nl(::std::vector<PathNode>& nodes, ::std::function<TypeRef(const char*)> fcn);
- static void match_args_nl(const ::std::vector<PathNode>& nodes_a, const ::std::vector<PathNode>& nodes_b, ::std::function<void(const char*,const TypeRef&)> fcn);
- static int node_lists_equal_no_generic(const ::std::vector<PathNode>& nodes_a, const ::std::vector<PathNode>& nodes_b);
void check_param_counts(const GenericParams& params, bool expect_params, PathNode& node);
public:
diff --git a/src/ast/types.cpp b/src/ast/types.cpp
index 8cc9b4ea..7b1c4cdb 100644
--- a/src/ast/types.cpp
+++ b/src/ast/types.cpp
@@ -127,387 +127,6 @@ TypeRef::TypeRef(const TypeRef& other)
}
}
-/// Replace this type reference with a dereferenced version
-bool TypeRef::deref(bool is_implicit)
-{
- #define _(VAR, ...) case TypeData::TAG_##VAR: { auto &ent = m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break;
- switch(m_data.tag())
- {
- case TypeData::TAGDEAD: throw "";
- case TypeData::TAG_None: throw ::std::runtime_error("Dereferencing ! - bugcheck");
- case TypeData::TAG_Macro: throw ::std::runtime_error("Dereferencing unexpanded macro - bugcheck");
- case TypeData::TAG_Any: throw ::std::runtime_error("Dereferencing _");
- case TypeData::TAG_Unit: throw ::std::runtime_error("Dereferencing ()");
- case TypeData::TAG_Primitive: throw ::std::runtime_error("Dereferencing a primtive type");
- case TypeData::TAG_Function: throw ::std::runtime_error("Dereferencing a function");
-
- case TypeData::TAG_Generic:
- // TODO: Check for Deref<Output=?> bound
- throw ::std::runtime_error("TODO: Check for a Deref bound on generic");
- _(Borrow,
- *this = *ent.inner;
- return true;
- )
- _(Pointer,
- // raw pointers can't be implicitly dereferenced
- if( is_implicit )
- return false;
- *this = *ent.inner;
- return true;
- )
- case TypeData::TAG_Tuple:
- case TypeData::TAG_Array:
- case TypeData::TAG_Path:
- throw ::std::runtime_error("TODO: Search for an impl of Deref");
- case TypeData::TAG_TraitObject:
- throw ::std::runtime_error("TODO: TypeRef::deref on MULTIDST");
- }
- #undef _
- throw ::std::runtime_error("BUGCHECK: Fell off end of TypeRef::deref");
-}
-
-/// Merge the contents of the passed type with this type
-///
-/// \note Both types must be of the same form (i.e. both be tuples)
-void TypeRef::merge_with(const TypeRef& other)
-{
- // Ignore if other is wildcard
- //if( other.m_class == TypeRef::ANY ) {
- // assert(other.m_inner_types.size() == 0 && "TODO: merge_with on bounded _");
- // return;
- //}
-
- // If this is a wildcard, then replace with the other type
- if( m_data.is_Any() ) {
- //if( m_inner_types.size() && m_inner_types.size() != other.m_inner_types.size() )
- // throw ::std::runtime_error("TypeRef::merge_with - Handle bounded wildcards");
- *this = other;
- return;
- }
-
- // If classes don't match, then merge is impossible
- if( m_data.tag() != other.m_data.tag() )
- throw ::std::runtime_error("TypeRef::merge_with - Types not compatible");
-
- // If both types are concrete, then they must be the same
- if( is_concrete() && other.is_concrete() )
- {
- if( *this != other )
- throw ::std::runtime_error("TypeRef::merge_with - Types not compatible");
- return;
- }
-
-
- TU_MATCH(TypeData, (m_data, other.m_data), (ent, other_ent),
- (None,
- throw ::std::runtime_error("TypeRef::merge_with - Reached concrete/wildcard");
- ),
- (Macro,
- throw ::std::runtime_error("TypeRef::merge_with - Reached unexpanded macro");
- ),
- (Any,
- throw ::std::runtime_error("TypeRef::merge_with - Reached concrete/wildcard");
- ),
- (Unit,
- throw ::std::runtime_error("TypeRef::merge_with - Reached concrete/wildcard");
- ),
- (Primitive,
- throw ::std::runtime_error("TypeRef::merge_with - Reached concrete/wildcard");
- ),
- (Function,
- ent.info.m_rettype->merge_with( *other_ent.info.m_rettype );
-
- if( ent.info.m_arg_types.size() != other_ent.info.m_arg_types.size() )
- throw ::std::runtime_error("TypeRef::merge_with - Types not compatible [function sz]");
- for(unsigned int i = 0; i < ent.info.m_arg_types.size(); i ++)
- {
- ent.info.m_arg_types[i].merge_with( other_ent.info.m_arg_types[i] );
- }
- ),
- (Tuple,
- // Other is known not to be wildcard, and is also a tuple, so it must be the same size
- if( ent.inner_types.size() != other_ent.inner_types.size() )
- throw ::std::runtime_error("TypeRef::merge_with - Types not compatible [tuple sz]");
- for(unsigned int i = 0; i < ent.inner_types.size(); i ++)
- {
- ent.inner_types[i].merge_with( other_ent.inner_types[i] );
- }
- ),
- (Borrow,
- if( ent.is_mut != other_ent.is_mut )
- throw ::std::runtime_error("TypeRef::merge_with - Types not compatible [inner mut]");
- ent.inner->merge_with( *other_ent.inner );
- ),
- (Pointer,
- if( ent.is_mut != other_ent.is_mut )
- throw ::std::runtime_error("TypeRef::merge_with - Types not compatible [inner mut]");
- ent.inner->merge_with( *other_ent.inner );
- ),
- (Array,
- throw ::std::runtime_error("TODO: TypeRef::merge_with on ARRAY");
- ),
- (Generic,
- throw ::std::runtime_error("TODO: TypeRef::merge_with on GENERIC");
- ),
- (Path,
- throw ::std::runtime_error("TODO: TypeRef::merge_with on PATH");
- ),
- (TraitObject,
- throw ::std::runtime_error("TODO: TypeRef::merge_with on MULTIDST");
- )
- )
-}
-
-/// Resolve all Generic/Argument types to the value returned by the passed closure
-///
-/// Replaces every instance of a TypeRef::GENERIC with the value returned from the passed
-/// closure.
-void TypeRef::resolve_args(::std::function<TypeRef(const char*)> fcn)
-{
- DEBUG("" << *this);
- #define _(VAR, ...) case TypeData::TAG_##VAR: { auto &ent = m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break;
- switch(m_data.tag())
- {
- case TypeData::TAGDEAD: throw "";
- _(None,
- throw ::std::runtime_error("TypeRef::resolve_args on !");
- )
- _(Macro,
- throw ::std::runtime_error("TypeRef::resolve_args on unexpanded macro");
- )
- // TODO: Is resolving args on an ANY an erorr?
- _(Any)
- _(Unit)
- _(Primitive)
- _(Function,
- ent.info.m_rettype->resolve_args(fcn);
- for( auto& t : ent.info.m_arg_types )
- t.resolve_args(fcn);
- )
- _(Tuple,
- for( auto& t : ent.inner_types )
- t.resolve_args(fcn);
- )
- _(Borrow,
- ent.inner->resolve_args(fcn);
- )
- _(Pointer,
- ent.inner->resolve_args(fcn);
- )
- _(Array,
- ent.inner->resolve_args(fcn);
- )
- _(Generic,
- *this = fcn(ent.name.c_str());
- )
- _(Path,
- ent.path.resolve_args(fcn);
- )
- _(TraitObject,
- for( auto& p : ent.traits )
- p.resolve_args(fcn);
- )
- }
- #undef _
-}
-
-/// Match this type against another type, calling the provided function for all generics found in this
-///
-/// \param other Type containing (possibly) concrete types
-/// \param fcn Function to call for all generics (called with matching type from \a other)
-/// This is used to handle extracting types passsed to methods/enum variants
-void TypeRef::match_args(const TypeRef& other, ::std::function<void(const char*,const TypeRef&)> fcn) const
-{
- // If this type is a generic, then call the closure with the other type
- if( m_data.tag() == TypeData::TAG_Generic ) {
- fcn( m_data.as_Generic().name.c_str(), other );
- return ;
- }
-
- // If the other type is a wildcard, early return
- // - TODO - Might want to restrict the other type to be of the same form as this type
- if( other.m_data.tag() == TypeData::TAG_Any )
- return;
-
- DEBUG("this = " << *this << ", other = " << other);
-
- // Any other case, it's a "pattern" match
- if( m_data.tag() != other.m_data.tag() )
- throw ::std::runtime_error("Type mismatch (class)");
- TU_MATCH(TypeData, (m_data, other.m_data), (ent, other_ent),
- (None,
- throw ::std::runtime_error("TypeRef::match_args on !");
- ),
- (Macro,
- throw CompileError::BugCheck("TypeRef::match_args - unexpanded macro");
- ),
- (Any,
- // Wait, isn't this an error?
- throw ::std::runtime_error("Encountered '_' in match_args");
- ),
- (Unit),
- (Primitive,
- // TODO: Should check if the type matches
- if( ent.core_type != other_ent.core_type )
- throw ::std::runtime_error("Type mismatch (core)");
- ),
- (Function,
- if( ent.info.m_abi != other_ent.info.m_abi )
- throw ::std::runtime_error("Type mismatch (function abi)");
- ent.info.m_rettype->match_args( *other_ent.info.m_rettype, fcn );
-
- if( ent.info.m_arg_types.size() != other_ent.info.m_arg_types.size() )
- throw ::std::runtime_error("Type mismatch (function size)");
- for(unsigned int i = 0; i < ent.info.m_arg_types.size(); i ++ )
- ent.info.m_arg_types[i].match_args( other_ent.info.m_arg_types[i], fcn );
- ),
- (Tuple,
- if( ent.inner_types.size() != other_ent.inner_types.size() )
- throw ::std::runtime_error("Type mismatch (tuple size)");
- for(unsigned int i = 0; i < ent.inner_types.size(); i ++ )
- ent.inner_types[i].match_args( other_ent.inner_types[i], fcn );
- ),
- (Borrow,
- if( ent.is_mut != other_ent.is_mut )
- throw ::std::runtime_error("Type mismatch (inner mutable)");
- ent.inner->match_args( *other_ent.inner, fcn );
- ),
- (Pointer,
- if( ent.is_mut != other_ent.is_mut )
- throw ::std::runtime_error("Type mismatch (inner mutable)");
- ent.inner->match_args( *other_ent.inner, fcn );
- ),
- (Array,
- ent.inner->match_args( *other_ent.inner, fcn );
- if(ent.size.get() || other_ent.size.get())
- {
- throw ::std::runtime_error("TODO: Sized array match_args");
- }
- ),
- (Generic,
- throw ::std::runtime_error("Encountered GENERIC in match_args");
- ),
- (Path,
- ent.path.match_args(other_ent.path, fcn);
- ),
- (TraitObject,
- throw ::std::runtime_error("TODO: TypeRef::match_args on MULTIDST");
- )
- )
-}
-
-/// Checks if the type is fully bounded
-bool TypeRef::is_concrete() const
-{
- #define _(VAR, ...) case TypeData::VAR: { const auto &ent = m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break;
- TU_MATCH(TypeData, (m_data), (ent),
- (None,
- throw ::std::runtime_error("TypeRef::is_concrete on !");
- ),
- (Macro, throw CompileError::BugCheck("TypeRef::is_concrete - unexpanded macro");),
- (Any, return false;),
- (Unit, return true; ),
- (Primitive, return true; ),
- (Function,
- if( not ent.info.m_rettype->is_concrete() )
- return false;
- for(const auto& t : ent.info.m_arg_types )
- if( not t.is_concrete() )
- return false;
- return true;
- ),
- (Tuple,
- for(const auto& t : ent.inner_types)
- if( not t.is_concrete() )
- return false;
- return true;
- ),
- (Borrow,
- return ent.inner->is_concrete();
- ),
- (Pointer,
- return ent.inner->is_concrete();
- ),
- (Array,
- return ent.inner->is_concrete();
- ),
- (Generic,
- // Well, I guess a generic param is "concrete"
- return true;
- ),
- (Path,
- return ent.path.is_concrete();
- ),
- (TraitObject,
- for(const auto& p : ent.traits )
- if( not p.is_concrete() )
- return false;
- return true;
- )
- )
- #undef _
- throw ::std::runtime_error( FMT("BUGCHECK - Invalid type class on " << *this) );
-}
-
-int TypeRef::equal_no_generic(const TypeRef& x) const
-{
- //DEBUG(*this << ", " << x);
- if( m_data.tag() == TypeData::TAG_Generic ) //|| x.m_class == TypeRef::GENERIC )
- return 1;
- if( m_data.tag() != x.m_data.tag() ) return -1;
-
- TU_MATCH(TypeData, (m_data, x.m_data), (ent, x_ent),
- (None, return 0;),
- (Macro, throw CompileError::BugCheck("TypeRef::equal_no_generic - unexpanded macro");),
- (Unit, return 0;),
- (Any, return 0;),
- (Primitive,
- if( ent.core_type != x_ent.core_type ) return -1;
- return 0;
- ),
- (Function,
- if( ent.info.m_abi != x_ent.info.m_abi ) return -1;
- throw CompileError::Todo("TypeRef::equal_no_generic - FUNCTION");
- ),
- (Generic,
- throw CompileError::BugCheck("equal_no_generic - Generic should have been handled above");
- ),
- (Path,
- return ent.path.equal_no_generic( x_ent.path );
- ),
- (Borrow,
- if( ent.is_mut != x_ent.is_mut )
- return -1;
- return ent.inner->equal_no_generic( *x_ent.inner );
- ),
- (Pointer,
- if( ent.is_mut != x_ent.is_mut )
- return -1;
- return ent.inner->equal_no_generic( *x_ent.inner );
- ),
- (Array,
- if( ent.size.get() || x_ent.size.get() )
- throw CompileError::Todo("TypeRef::equal_no_generic - sized array");
- return ent.inner->equal_no_generic( *x_ent.inner );
- ),
- (Tuple,
- bool fuzzy = false;
- if( ent.inner_types.size() != x_ent.inner_types.size() )
- return -1;
- for( unsigned int i = 0; i < ent.inner_types.size(); i ++ )
- {
- int rv = ent.inner_types[i].equal_no_generic( x_ent.inner_types[i] );
- if(rv < 0) return -1;
- if(rv > 0) fuzzy = true;
- }
- return (fuzzy ? 1 : 0);
- ),
- (TraitObject,
- throw CompileError::Todo("TypeRef::equal_no_generic - MULTIDST");
- )
- )
- throw CompileError::BugCheck("equal_no_generic - Ran off end");
-}
Ordering TypeRef::ord(const TypeRef& x) const
{
Ordering rv;
diff --git a/src/ast/types.hpp b/src/ast/types.hpp
index a79a811d..b3208f8c 100644
--- a/src/ast/types.hpp
+++ b/src/ast/types.hpp
@@ -220,20 +220,6 @@ public:
const Span& span() const { return m_span; }
- /// Dereference the type (return the result of *type_instance)
- bool deref(bool is_implicit);
- /// Merge with another type (combines known aspects, conflitcs cause an exception)
- void merge_with(const TypeRef& other);
- /// Replace 'GENERIC' entries with the return value of the closure
- void resolve_args(::std::function<TypeRef(const char*)> fcn);
- /// Match 'GENERIC' entries with another type, passing matches to a closure
- void match_args(const TypeRef& other, ::std::function<void(const char*,const TypeRef&)> fcn) const;
-
- bool impls_wildcard(const AST::Crate& crate, const AST::Path& trait) const;
-
- /// Returns true if the type is fully known (all sub-types are not wildcards)
- bool is_concrete() const;
-
bool is_valid() const { return ! m_data.is_None(); }
bool is_unbounded() const { return m_data.is_Any(); }
@@ -285,9 +271,6 @@ public:
//void add_trait(TypeRef trait) { assert(is_wildcard()); m_inner_types.push_back( ::std::move(trait) ); }
//const ::std::vector<TypeRef>& traits() const { assert(is_wildcard()); return m_inner_types; }
- /// Returns 0 if types are identical, 1 if TypeRef::TagArg is present in one, and -1 if form differs
- int equal_no_generic(const TypeRef& x) const;
-
Ordering ord(const TypeRef& x) const;
bool operator==(const TypeRef& x) const { return ord(x) == OrdEqual; }
bool operator!=(const TypeRef& x) const { return ord(x) != OrdEqual; }
diff --git a/src/common.hpp b/src/common.hpp
index 96cfcd96..da2c3898 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -41,24 +41,6 @@ enum Ordering
OrdEqual,
OrdGreater,
};
-template<typename T>
-Ordering ord(const ::std::vector<T>& l, const ::std::vector<T>& r)
-{
- unsigned int i = 0;
- for(const auto& it : l)
- {
- if( i >= r.size() )
- return OrdGreater;
-
- auto rv = it.ord(r[i]);
- if( rv != OrdEqual )
- return rv;
-
- i ++;
- }
-
- return OrdEqual;
-}
static inline Ordering ord(bool l, bool r)
{
if(l == r)
@@ -86,6 +68,38 @@ static inline Ordering ord(const ::std::string& l, const ::std::string& r)
else
return OrdLess;
}
+template<typename T>
+Ordering ord(const T& l, const T& r)
+{
+ return l.ord(r);
+}
+template<typename T, typename U>
+Ordering ord(const ::std::pair<T,U>& l, const ::std::pair<T,U>& r)
+{
+ Ordering rv;
+ rv = ::ord(l.first, r.first);
+ if(rv != OrdEqual) return rv;
+ rv = ::ord(l.second, r.second);
+ return rv;
+}
+template<typename T>
+Ordering ord(const ::std::vector<T>& l, const ::std::vector<T>& r)
+{
+ unsigned int i = 0;
+ for(const auto& it : l)
+ {
+ if( i >= r.size() )
+ return OrdGreater;
+
+ auto rv = ::ord( it, r[i] );
+ if( rv != OrdEqual )
+ return rv;
+
+ i ++;
+ }
+
+ return OrdEqual;
+}
template <typename T>
diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp
index 06369787..fdb8088b 100644
--- a/src/expand/derive.cpp
+++ b/src/expand/derive.cpp
@@ -149,8 +149,10 @@ static void derive_item(const Span& sp, AST::Module& mod, const AST::MetaItem& a
const auto& params = item.params();
TypeRef type(sp, path);
- for( const auto& param : params.ty_params() )
- type.path().nodes().back().args().push_back( TypeRef(TypeRef::TagArg(), param.name()) );
+ auto& types_args = type.path().nodes().back().args();
+ for( const auto& param : params.ty_params() ) {
+ types_args.m_types.push_back( TypeRef(TypeRef::TagArg(), param.name()) );
+ }
for( const auto& trait : attr.items() )
{
diff --git a/src/expand/lang_item.cpp b/src/expand/lang_item.cpp
index d381d17c..c34642db 100644
--- a/src/expand/lang_item.cpp
+++ b/src/expand/lang_item.cpp
@@ -15,7 +15,7 @@ void handle_lang_item(AST::Crate& crate, const AST::Path& path, const ::std::str
{
if(name == "phantom_fn") {
crate.m_lang_item_PhantomFn = AST::Path(path);
- crate.m_lang_item_PhantomFn.nodes().back().args() = { TypeRef("A"), TypeRef("B") };
+ crate.m_lang_item_PhantomFn.nodes().back().args().m_types = { TypeRef("A"), TypeRef("B") };
}
else if( name == "send" ) {
// Don't care, Send is fully library in mrustc
diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp
index 26d7029f..bffafc48 100644
--- a/src/hir/from_ast.cpp
+++ b/src/hir/from_ast.cpp
@@ -319,7 +319,7 @@
::HIR::SimplePath rv( e.crate );
for( const auto& node : e.nodes )
{
- if( node.args().size() > 0 )
+ if( ! node.args().is_empty() )
{
if( allow_final_generic && &node == &e.nodes.back() ) {
// Let it pass
@@ -342,7 +342,10 @@
TU_IFLET(::AST::Path::Class, path.m_class, Absolute, e,
auto sp = LowerHIR_SimplePath(path, true);
::HIR::PathParams params;
- for(const auto& param : e.nodes.back().args()) {
+ const auto& src_params = e.nodes.back().args();
+ //for(const auto& param : src_params.m_lifetimes) {
+ //}
+ for(const auto& param : src_params.m_types) {
params.m_types.push_back( LowerHIR_Type(param) );
}
// TODO: Lifetime params (not encoded in AST::PathNode as yet)
diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp
index d9982da9..f5e9b31a 100644
--- a/src/hir/from_ast_expr.cpp
+++ b/src/hir/from_ast_expr.cpp
@@ -237,7 +237,7 @@ struct LowerHIR_ExprNode_Visitor:
// TODO: Should this be abstracted?
::HIR::PathParams params;
- for(const auto& param : v.m_method.args())
+ for(const auto& param : v.m_method.args().m_types)
params.m_types.push_back( LowerHIR_Type(param) );
m_rv.reset( new ::HIR::ExprNode_CallMethod(
diff --git a/src/include/span.hpp b/src/include/span.hpp
index e7bd2694..86d21514 100644
--- a/src/include/span.hpp
+++ b/src/include/span.hpp
@@ -67,5 +67,5 @@ Spanned<T> make_spanned(Span sp, T val) {
#define ERROR(span, code, msg) do { ::Span(span).error(code, [&](::std::ostream& os) { os << msg; }); throw ::std::runtime_error("Error fell through" #code); } while(0)
#define WARNING(span, code, msg) do { ::Span(span).warning(code, [&](::std::ostream& os) { os << msg; }); } while(0)
#define BUG(span, msg) do { ::Span(span).bug([&](::std::ostream& os) { os << msg; }); throw ::std::runtime_error("Bug fell through"); } while(0)
-#define TODO(span, msg) do { ::Span(span).bug([&](::std::ostream& os) { os << "TODO: " << msg; }); throw ::std::runtime_error("Bug (todo) fell through"); } while(0)
+#define TODO(span, msg) do { const char* __TODO_func = __func__; ::Span(span).bug([&](::std::ostream& os) { os << "TODO: " << __TODO_func << " - " << msg; }); throw ::std::runtime_error("Bug (todo) fell through"); } while(0)
diff --git a/src/main.cpp b/src/main.cpp
index d8384184..ffe61468 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -25,9 +25,9 @@ int g_debug_indent_level = 0;
bool debug_enabled()
{
- //return true;
+ return true;
//return g_cur_phase != "Parse";
- return g_cur_phase != "Parse" && g_cur_phase != "Expand";
+ //return g_cur_phase != "Parse" && g_cur_phase != "Expand";
//return g_cur_phase != "Parse" && g_cur_phase != "Expand" && g_cur_phase != "Resolve";
}
::std::ostream& debug_output(int indent, const char* function)
diff --git a/src/parse/common.hpp b/src/parse/common.hpp
index c42889c3..bf1c7448 100644
--- a/src/parse/common.hpp
+++ b/src/parse/common.hpp
@@ -36,7 +36,7 @@ enum eParsePathGenericMode
extern AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode); // Auto-determines
extern AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode);
extern ::std::vector<AST::PathNode> Parse_PathNodes(TokenStream& lex, eParsePathGenericMode generic_mode);
-extern ::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex);
+extern AST::PathParams Parse_Path_GenericList(TokenStream& lex);
extern AST::MetaItem Parse_MetaItem(TokenStream& lex);
diff --git a/src/parse/paths.cpp b/src/parse/paths.cpp
index 153f51a0..2c97075e 100644
--- a/src/parse/paths.cpp
+++ b/src/parse/paths.cpp
@@ -12,7 +12,7 @@
AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode);
AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode);
::std::vector<AST::PathNode> Parse_PathNodes(TokenStream& lex, eParsePathGenericMode generic_mode);
-::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex);
+AST::PathParams Parse_Path_GenericList(TokenStream& lex);
AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode)
{
@@ -106,7 +106,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi
tok = lex.getToken();
while(true)
{
- ::std::vector<TypeRef> params;
+ ::AST::PathParams params;
CHECK_TOK(tok, TOK_IDENT);
::std::string component = tok.str();
@@ -122,7 +122,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi
// Type-mode generics "::path::to::Type<A,B>"
params = Parse_Path_GenericList(lex);
- tok = lex.getToken();
+ GET_TOK(tok, lex);
}
// HACK - 'Fn*(...) -> ...' notation
else if( tok.type() == TOK_PAREN_OPEN )
@@ -153,7 +153,11 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi
DEBUG("- Fn("<<args<<")->"<<ret_type<<"");
// Encode into path, by converting Fn(A,B)->C into Fn<(A,B),Ret=C>
- params = ::std::vector<TypeRef> { TypeRef(TypeRef::TagTuple(), lex.end_span(ps), ::std::move(args)) };
+ params = ::AST::PathParams {
+ {},
+ ::std::vector<TypeRef> { TypeRef(TypeRef::TagTuple(), lex.end_span(ps), ::std::move(args)) },
+ { ::std::make_pair( (::std::string)"Output", mv$(ret_type) ) }
+ };
// TODO: Use 'ret_type' as an associated type bound
GET_TOK(tok, lex);
@@ -175,32 +179,30 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi
// Expr-mode generics "::path::to::function::<Type1,Type2>(arg1, arg2)"
params = Parse_Path_GenericList(lex);
- tok = lex.getToken();
- if( tok.type() != TOK_DOUBLE_COLON ) {
+ if( GET_TOK(tok, lex) != TOK_DOUBLE_COLON ) {
ret.push_back( AST::PathNode(component, mv$(params)) );
+ // Break out of loop down to return
break;
}
+ // Match with CHECK_TOK at start of loop
GET_TOK(tok, lex);
}
ret.push_back( AST::PathNode(component, mv$(params)) );
}
PUTBACK(tok, lex);
- //if( path.is_trivial() ) {
- // path = AST::Path(path[0].name());
- //}
DEBUG("ret = " << ret);
return ret;
}
/// Parse a list of parameters within a path
-::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex)
+::AST::PathParams Parse_Path_GenericList(TokenStream& lex)
{
TRACE_FUNCTION;
Token tok;
::std::vector<TypeRef> types;
::std::vector< ::std::string> lifetimes;
- ::std::map< ::std::string, TypeRef> assoc_bounds;
- //::std::vector<unsigned int> int_args;
+ ::std::vector< ::std::pair< ::std::string, TypeRef > > assoc_bounds;
+
do {
if( LOOK_AHEAD(lex) == TOK_GT || LOOK_AHEAD(lex) == TOK_DOUBLE_GT || LOOK_AHEAD(lex) == TOK_GTE || LOOK_AHEAD(lex) == TOK_DOUBLE_GT_EQUAL ) {
GET_TOK(tok, lex);
@@ -216,7 +218,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi
{
::std::string name = tok.str();
GET_CHECK_TOK(tok, lex, TOK_EQUAL);
- assoc_bounds.insert( ::std::make_pair( ::std::move(name), Parse_Type(lex) ) );
+ assoc_bounds.push_back( ::std::make_pair( mv$(name), Parse_Type(lex) ) );
break;
}
default:
@@ -240,8 +242,10 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi
CHECK_TOK(tok, TOK_GT);
}
- // TODO: Actually use the lifetimes/assoc_bounds
-
- return types;
+ return ::AST::PathParams {
+ mv$( lifetimes ),
+ mv$( types ),
+ mv$( assoc_bounds )
+ };
}
diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp
index 41eacd46..ca7b0dfc 100644
--- a/src/resolve/absolute.cpp
+++ b/src/resolve/absolute.cpp
@@ -414,14 +414,23 @@ void Resolve_Absolute_Mod(const ::AST::Crate& crate, ::AST::Module& mod);
void Resolve_Absolute_Mod( Context item_context, ::AST::Module& mod );
+void Resolve_Absolute_PathParams(/*const*/ Context& context, const Span& sp, ::AST::PathParams& args)
+{
+ for(auto& arg : args.m_types)
+ {
+ Resolve_Absolute_Type(context, arg);
+ }
+ for(auto& arg : args.m_assoc)
+ {
+ Resolve_Absolute_Type(context, arg.second);
+ }
+}
+
void Resolve_Absolute_PathNodes(/*const*/ Context& context, const Span& sp, ::std::vector< ::AST::PathNode >& nodes)
{
for(auto& node : nodes)
{
- for(auto& arg : node.args())
- {
- Resolve_Absolute_Type(context, arg);
- }
+ Resolve_Absolute_PathParams(context, sp, node.args());
}
}
@@ -522,7 +531,7 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex
if( n.name()[0] == '#' ) {
- if( n.args().size() > 0 ) {
+ if( ! n.args().is_empty() ) {
ERROR(sp, E0000, "Type parameters were not expected here");
}
@@ -553,8 +562,9 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex
),
(Trait,
auto trait_path = ::AST::Path(name_ref.path);
- if( n.args().size() )
+ if( !n.args().is_empty() ) {
trait_path.nodes().back().args() = mv$(n.args());
+ }
auto new_path = ::AST::Path(::AST::Path::TagUfcs(), ::TypeRef(), mv$(trait_path));
for( unsigned int j = i+1; j < path_abs.nodes.size(); j ++ )
new_path.nodes().push_back( mv$(path_abs.nodes[j]) );
@@ -575,7 +585,7 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex
ERROR(sp, E0000, "Unexpected enum in path " << path);
}
// NOTE: Type parameters for enums go after the _variant_
- if( n.args().size() ) {
+ if( ! n.args().is_empty() ) {
ERROR(sp, E0000, "Type parameters were not expected here (enum params go on the variant)");
}
@@ -585,8 +595,9 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex
}
auto type_path = ::AST::Path(name_ref.path);
- if( n.args().size() )
+ if( !n.args().is_empty() ) {
type_path.nodes().back().args() = mv$(n.args());
+ }
auto new_path = ::AST::Path(::AST::Path::TagUfcs(), ::TypeRef(sp, mv$(type_path)), ::AST::Path());
for( unsigned int j = i+1; j < path_abs.nodes.size(); j ++ )
new_path.nodes().push_back( mv$(path_abs.nodes[j]) );
@@ -597,8 +608,9 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex
),
(Struct,
auto type_path = ::AST::Path(name_ref.path);
- if( n.args().size() )
+ if( ! n.args().is_empty() ) {
type_path.nodes().back().args() = mv$(n.args());
+ }
auto new_path = ::AST::Path(::AST::Path::TagUfcs(), ::TypeRef(sp, mv$(type_path)), ::AST::Path());
for( unsigned int j = i+1; j < path_abs.nodes.size(); j ++ )
new_path.nodes().push_back( mv$(path_abs.nodes[j]) );
@@ -627,6 +639,7 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex
// Replaces the path with the one returned by `lookup_in_mod`, ensuring that `use` aliases are eliminated
DEBUG("Replace " << path << " with " << tmp);
+ tmp.nodes().back().args() = mv$(path.nodes().back().args());
path = mv$(tmp);
}
@@ -664,10 +677,10 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::
if( p.m_class.is_Local() ) {
p = ::AST::Path( ::AST::Path::TagUfcs(), TypeRef(sp, mv$(p)) );
}
- if( e.nodes[0].args().size() > 0 )
+ if( ! e.nodes[0].args().is_empty() )
{
assert( p.nodes().size() > 0 );
- assert( p.nodes().back().args().size() == 0 );
+ assert( p.nodes().back().args().is_empty() );
p.nodes().back().args() = mv$( e.nodes[0].args() );
}
for( unsigned int i = 1; i < e.nodes.size(); i ++ )
@@ -681,6 +694,10 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::
// Look up value
auto p = context.lookup(sp, e.nodes[0].name(), mode);
DEBUG("Found path " << p << " for " << path);
+ if( p.is_absolute() ) {
+ assert( !p.nodes().empty() );
+ p.nodes().back().args() = mv$(e.nodes.back().args());
+ }
path = mv$(p);
}
@@ -730,6 +747,7 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::
)
)
+ DEBUG("path = " << path);
// TODO: Should this be deferred until the HIR?
// - Doing it here so the HIR lowering has a bit more information
// - Also handles splitting "absolute" paths into UFCS
@@ -934,8 +952,7 @@ void Resolve_Absolute_Expr(Context& context, ::AST::ExprNode& node)
}
void visit(AST::ExprNode_CallMethod& node) override {
DEBUG("ExprNode_CallMethod");
- for(auto& param : node.m_method.args())
- Resolve_Absolute_Type(this->context, param);
+ Resolve_Absolute_PathParams(this->context, Span(node.get_pos()), node.m_method.args());
AST::NodeVisitorDef::visit(node);
}
void visit(AST::ExprNode_NamedValue& node) override {