summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--src/ast/ast.cpp57
-rw-r--r--src/ast/ast.hpp47
-rw-r--r--src/ast/path.cpp6
-rw-r--r--src/ast/path.hpp1
-rw-r--r--src/convert/resolve.cpp151
-rw-r--r--src/include/rustic.hpp28
-rw-r--r--src/include/tagged_union.hpp8
-rw-r--r--src/parse/lex.hpp10
-rw-r--r--src/parse/root.cpp16
10 files changed, 265 insertions, 60 deletions
diff --git a/Makefile b/Makefile
index f720ae48..44611658 100644
--- a/Makefile
+++ b/Makefile
@@ -6,6 +6,7 @@ V ?= @
LINKFLAGS := -g
LIBS :=
CXXFLAGS := -g -Wall -std=c++11 -Werror
+#CXXFLAGS += -O3
CPPFLAGS := -I src/include/
SHELL = bash
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp
index fb289a20..d2006e52 100644
--- a/src/ast/ast.cpp
+++ b/src/ast/ast.cpp
@@ -106,6 +106,17 @@ SERIALISE_TYPE(ImplDef::, "AST_ImplDef", {
s.item(m_type);
})
+bool Impl::has_named_item(const ::std::string& name) const
+{
+ for( const auto& it : this->functions() )
+ {
+ if( it.name == name ) {
+ return true;
+ }
+ }
+ return false;
+}
+
Impl& Impl::get_concrete(const ::std::vector<TypeRef>& param_types)
{
if( param_types.size() > 0 )
@@ -177,6 +188,17 @@ Crate::Crate():
{
}
+::rust::option<char> ImplRef::find_named_item(const ::std::string& name) const
+{
+ if( this->impl.has_named_item(name) ) {
+ return ::rust::Some(' ');
+ }
+ else {
+ return ::rust::None<char>();
+ }
+}
+
+
static void iterate_module(Module& mod, ::std::function<void(Module& mod)> fcn)
{
fcn(mod);
@@ -263,6 +285,39 @@ bool Crate::check_impls_wildcard(const Path& trait, const TypeRef& type) const
return type.impls_wildcard(*this, trait);
}
+
+::std::vector<ImplRef> Crate::find_inherent_impls(const TypeRef& type) const
+{
+ assert( !type.is_type_param() );
+
+ ::std::vector<ImplRef> ret;
+
+ for( auto implptr : m_impl_index )
+ {
+ Impl& impl = *implptr;
+ ::std::vector<TypeRef> out_params;
+ if( impl.def().matches(out_params, AST::Path(), type) )
+ {
+ ret.push_back( ImplRef(impl, out_params) );
+ }
+ }
+
+ return ret;
+}
+
+::rust::option<ImplRef> Crate::find_impl(const Path& trait, const TypeRef& type) const
+{
+ ::std::vector<TypeRef> params;
+ Impl *out_impl;
+ if( find_impl(trait, type, &out_impl, &params) )
+ {
+ return ::rust::Some( ImplRef(*out_impl, params) );
+ }
+ else {
+ return ::rust::None<ImplRef>();
+ }
+}
+
bool Crate::find_impl(const Path& trait, const TypeRef& type, Impl** out_impl, ::std::vector<TypeRef>* out_params) const
{
TRACE_FUNCTION_F("trait = " << trait << ", type = " << type);
@@ -1003,7 +1058,7 @@ bool TypeParams::check_params(Crate& crate, ::std::vector<TypeRef>& types, bool
{
const auto& trait = bound.as_IsTrait().trait;
// Check if 'type' impls 'trait'
- if( !crate.find_impl(trait, trait) )
+ if( !crate.find_impl(trait, trait, nullptr, nullptr) )
{
throw ::std::runtime_error( FMT("No matching impl of "<<trait<<" for "<<type));
}
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp
index 301c94bb..bec17bda 100644
--- a/src/ast/ast.hpp
+++ b/src/ast/ast.hpp
@@ -408,22 +408,26 @@ class Trait:
{
MetaItems m_attrs;
TypeParams m_params;
+ ::std::vector<AST::Path> m_supertraits;
ItemList<TypeAlias> m_types;
ItemList<Function> m_functions;
public:
Trait() {}
- Trait(MetaItems attrs, TypeParams params):
- m_attrs( move(attrs) ),
- m_params(params)
+ Trait(MetaItems attrs, TypeParams params, ::std::vector<Path> supertraits):
+ m_attrs( mv$(attrs) ),
+ m_params( mv$(params) ),
+ m_supertraits( mv$(supertraits) )
{
}
const MetaItems& attrs() const { return m_attrs; }
const TypeParams& params() const { return m_params; }
+ const ::std::vector<Path>& supertraits() const { return m_supertraits; }
const ItemList<Function>& functions() const { return m_functions; }
const ItemList<TypeAlias>& types() const { return m_types; }
TypeParams& params() { return m_params; }
+ ::std::vector<Path>& supertraits() { return m_supertraits; }
ItemList<Function>& functions() { return m_functions; }
ItemList<TypeAlias>& types() { return m_types; }
@@ -434,6 +438,22 @@ public:
m_functions.push_back( Item<Function>(::std::move(name), ::std::move(fcn), true) );
}
+ bool has_named_item(const ::std::string& name, bool& out_is_fcn) const {
+ for( const auto& f : m_functions )
+ if( f.name == name ) {
+ out_is_fcn = true;
+ return true;
+ }
+ for( const auto& f : m_types )
+ if( f.name == name ) {
+ out_is_fcn = false;
+ return true;
+ }
+
+ //for( const auto& st :
+ return false;
+ }
+
SERIALISABLE_PROTOTYPES();
};
@@ -587,6 +607,8 @@ public:
ImplDef& def() { return m_def; }
ItemList<Function>& functions() { return m_functions; }
ItemList<TypeRef>& types() { return m_types; }
+
+ bool has_named_item(const ::std::string& name) const;
/// Obtain a concrete implementation based on the provided types (caches)
Impl& get_concrete(const ::std::vector<TypeRef>& param_types);
@@ -790,6 +812,20 @@ private:
extern void handle_lang_item(AST::Crate& , const AST::Path& h, const ::std::string& , AST::eItemType );
namespace AST {
+
+struct ImplRef
+{
+ const Impl& impl;
+ ::std::vector<TypeRef> params;
+
+ ImplRef(const Impl& impl, ::std::vector<TypeRef> params):
+ impl(impl),
+ params(params)
+ {}
+
+ ::rust::option<char> find_named_item(const ::std::string& name) const;
+};
+
class Crate:
public Serialisable
{
@@ -821,7 +857,10 @@ public:
bool is_trait_implicit(const Path& trait) const;
- bool find_impl(const Path& trait, const TypeRef& type, Impl** out_impl=nullptr, ::std::vector<TypeRef>* out_prams=nullptr) const;
+
+ ::std::vector<ImplRef> find_inherent_impls(const TypeRef& type) const;
+ ::rust::option<ImplRef> find_impl(const Path& trait, const TypeRef& type) const;
+ bool find_impl(const Path& trait, const TypeRef& type, Impl** out_impl, ::std::vector<TypeRef>* out_prams=nullptr) const;
const ::rust::option<Impl&> get_impl(const Path& trait, const TypeRef& type) {
Impl* impl_ptr;
::std::vector<TypeRef> params;
diff --git a/src/ast/path.cpp b/src/ast/path.cpp
index 863902e6..971cc657 100644
--- a/src/ast/path.cpp
+++ b/src/ast/path.cpp
@@ -88,7 +88,9 @@ AST::Path::Path(TagUfcs, TypeRef type, TypeRef trait):
{
}
AST::Path::Path(const Path& x):
+ m_crate(x.m_crate),
m_class()
+ //m_binding(x.m_binding)
{
TU_MATCH(Class, (x.m_class), (ent),
(Invalid, m_class = Class::make_Invalid({});),
@@ -111,6 +113,8 @@ AST::Path::Path(const Path& x):
m_class = Class::make_UFCS({ box$(TypeRef(*ent.type)), box$(TypeRef(*ent.trait)), ent.nodes });
)
)
+
+ DEBUG("clone, x = " << x << ", this = " << *this );
}
/// Resolve a path into a canonical form, and bind it to the target value
@@ -434,7 +438,7 @@ void Path::resolve_ufcs(const Crate& root_crate, bool expect_params)
goto _impl_item_bound;
}
}
- throw ParseError::Generic("Path::resolve_ufcs - No item in inherent");
+ throw ParseError::Generic( FMT("Path::resolve_ufcs - No item named '"<<node.name()<<"' in inherent"));
_impl_item_bound:
DEBUG("UFCS inherent bound to " << m_binding);
}
diff --git a/src/ast/path.hpp b/src/ast/path.hpp
index 04de1aeb..0fa4ff04 100644
--- a/src/ast/path.hpp
+++ b/src/ast/path.hpp
@@ -276,6 +276,7 @@ public:
bool is_concrete() const;
+ bool is_bound() const { return !m_binding.is_Unbound(); }
const PathBinding& binding() const { return m_binding; }
void bind_variable(unsigned int slot);
diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp
index 360ba852..9725549c 100644
--- a/src/convert/resolve.cpp
+++ b/src/convert/resolve.cpp
@@ -52,6 +52,8 @@ class CPathResolver:
AST::Module *module; // can be NULL
AST::Path module_path;
::std::vector< ::std::string > locals;
+
+ ::std::vector< ::std::pair<AST::Path, const AST::Trait&> > traits;
};
::std::vector<Scope> m_scope_stack;
::std::vector< TypeRef > m_self_type;
@@ -65,11 +67,13 @@ public:
virtual void handle_path(AST::Path& path, CASTIterator::PathMode mode) override;
void handle_path_ufcs(AST::Path& path, CASTIterator::PathMode mode);
+ bool find_trait_item(const AST::Path& path, AST::Trait& trait, const ::std::string& item_name, bool& out_is_method, AST::Path& out_trait_path);
virtual void handle_type(TypeRef& type) override;
virtual void handle_expr(AST::ExprNode& node) override;
virtual void handle_pattern(AST::Pattern& pat, const TypeRef& type_hint) override;
virtual void handle_module(AST::Path path, AST::Module& mod) override;
+ virtual void handle_trait(AST::Path path, AST::Trait& trait) override;
virtual void handle_function(AST::Path path, AST::Function& fcn) override;
virtual void start_scope() override;
@@ -85,6 +89,12 @@ public:
assert(m_scope_stack.size() > 0);
m_scope_stack.back().locals.push_back( ::std::move(name) );
}
+ virtual void local_use(::std::string name, AST::Path path) override {
+ assert( !path.binding().is_Unbound() );
+ if( path.binding().is_Trait() ) {
+ m_scope_stack.back().traits.push_back( ::std::pair<AST::Path, const AST::Trait&>(path, *path.binding().as_Trait().trait_) );
+ }
+ }
virtual void end_scope() override;
::rust::option<const LocalItem&> lookup_local(LocalItem::Type type, const ::std::string& name) const;
@@ -99,6 +109,22 @@ public:
// TODO: Handle a block and obtain the local module (if any)
private:
void handle_path_int(AST::Path& path, CASTIterator::PathMode mode);
+
+ ::std::vector< ::std::pair<AST::Path, const AST::Trait&> > inscope_traits() const
+ {
+ ::std::vector< ::std::pair<AST::Path, const AST::Trait&> > ret;
+ for( auto it = m_scope_stack.rbegin(); it != m_scope_stack.rend(); ++it )
+ {
+ for( const auto& t : it->traits ) {
+ DEBUG("t = " << t.first);
+ //assert(t.first.binding().is_Trait());
+ ret.push_back(t);
+ }
+ }
+ return ret;
+ }
+
+
};
// Path resolution checking
@@ -619,12 +645,13 @@ void CPathResolver::handle_path_ufcs(AST::Path& path, CASTIterator::PathMode mod
// Search applicable type parameters for known implementations
// 1. Inherent
- AST::Impl* impl_ptr;
+ //AST::Impl* impl_ptr;
::std::vector<TypeRef> params;
if( info.type->is_type_param() && info.type->type_param() == "Self" )
{
- // TODO: What is "Self" here? May want to use GenericBound's to replace Self with the actual type when possible.
- // In which case, Self will refer to "implementor of this trait"
+ // TODO: What is "Self" here? May want to use `GenericBound`s to replace Self with the actual type when possible.
+ // In which case, Self will refer to "implementor of this trait".
+ // - Look up applicable traits for this type, using bounds (basically same as next)
throw ParseError::Todo("CPathResolver::handle_path_ufcs - Handle '<Self as _>::...'");
}
else if( info.type->is_type_param() )
@@ -642,50 +669,68 @@ void CPathResolver::handle_path_ufcs(AST::Path& path, CASTIterator::PathMode mod
(),
(IsTrait,
if( ent.type == *info.type ) {
- const auto& t = *ent.trait.binding().as_Trait().trait_;
+ auto& t = *const_cast<AST::Trait*>(ent.trait.binding().as_Trait().trait_);
+ DEBUG("Type match, t.params() = " << t.params());
+ bool is_method;
+ AST::Path found_trait_path;
+ DEBUG("find_trait_item(" << ent.trait << /*", t=" << t <<*/ ", item_name = " << item_name);
+ if( this->find_trait_item(ent.trait, t, item_name, is_method, found_trait_path) )
{
- const auto& fcns = t.functions();
- auto it = ::std::find_if( fcns.begin(), fcns.end(), [&](const AST::Item<AST::Function>& a) { return a.name == item_name; } );
- if( it != fcns.end() ) {
- // Found it.
+ if( is_method ) {
if( info.nodes.size() != 1 )
- throw ParseError::Generic("CPathResolver::handle_path_ufcs - Multiple arguments");
- *info.trait = ent.trait;
- success = true;
- break;
+ throw ParseError::Generic("CPathResolver::handle_path_ufcs - Sub-nodes to method");
}
- }
- {
- const auto& types = t.types();
- auto it = ::std::find_if( types.begin(), types.end(), [&](const AST::Item<AST::TypeAlias>& a) { return a.name == item_name; } );
- if( it != types.end() ) {
- // Found it.
- *info.trait = ent.trait;
- success = true;
- break;
+ else {
+ if( info.nodes.size() != 1 )
+ throw ParseError::Todo("CPathResolver::handle_path_ufcs - Sub nodes on associated type");
}
+ *info.trait = TypeRef( mv$(found_trait_path) );
+ success = true;
+ break ;
}
}
+ else {
+ DEBUG("Type mismatch " << ent.type << " != " << *info.type);
+ }
)
)
}
if( !success )
- throw ParseError::Todo("CPathResolver::handle_path_ufcs - UFCS, find trait for generic");
+ throw ParseError::Todo( FMT("CPathResolver::handle_path_ufcs - UFCS, find trait for generic matching '" << item_name << "'") );
// - re-handle, to ensure that the bound is resolved
handle_type(*info.trait);
}
- else if( m_crate.find_impl(AST::Path(), *info.type, &impl_ptr, &params) )
- {
- DEBUG("Found matching inherent impl");
- // - Mark as being from the inherent, and move along
- // > TODO: What about if this item is actually from a trait (due to genric restrictions)
- *info.trait = TypeRef(TypeRef::TagInvalid());
- }
else
{
+ // Iterate all inherent impls
+ for( auto impl : m_crate.find_inherent_impls(*info.type) ) {
+ IF_OPTION_SOME(item, impl.find_named_item(item_name), {
+ DEBUG("Found matching inherent impl");
+ *info.trait = TypeRef(TypeRef::TagInvalid());
+ //path.set_binding(item);
+ path.resolve(m_crate);
+ return ;
+ })
+ }
// Iterate all traits in scope, and find one that is implemented for this type
// - TODO: Iterate traits to find match for <Type as _>
+ for( const auto& trait_ref : this->inscope_traits() )
+ {
+ const auto& trait_p = trait_ref.first;
+ const auto& trait = trait_ref.second;
+ bool is_fcn;
+ if( trait.has_named_item(item_name, is_fcn) ) {
+ IF_OPTION_SOME(impl, m_crate.find_impl( trait_p, *info.type ), {
+ *info.trait = TypeRef( trait_p );
+ //auto item = impl.find_named_item(item_name).unwrap();
+ //path.set_binding(item);
+ path.resolve(m_crate);
+ return ;
+ })
+ }
+ }
+
throw ParseError::Todo("CPathResolver::handle_path_ufcs - UFCS, find trait");
}
}
@@ -693,6 +738,40 @@ void CPathResolver::handle_path_ufcs(AST::Path& path, CASTIterator::PathMode mod
path.resolve(m_crate);
}
+bool CPathResolver::find_trait_item(const AST::Path& path, AST::Trait& trait, const ::std::string& item_name, bool& out_is_method, AST::Path& out_trait_path)
+{
+ {
+ const auto& fcns = trait.functions();
+ //DEBUG("fcns = " << fcns);
+ auto it = ::std::find_if( fcns.begin(), fcns.end(), [&](const AST::Item<AST::Function>& a) { DEBUG("fcn " << a.name); return a.name == item_name; } );
+ if( it != fcns.end() ) {
+ // Found it.
+ out_is_method = true;
+ DEBUG("&out_trait_path = " << &out_trait_path);
+ out_trait_path = AST::Path(path);
+ return true;
+ }
+ }
+ {
+ const auto& types = trait.types();
+ auto it = ::std::find_if( types.begin(), types.end(), [&](const AST::Item<AST::TypeAlias>& a) { DEBUG("type " << a.name); return a.name == item_name; } );
+ if( it != types.end() ) {
+ // Found it.
+ out_is_method = false;
+ out_trait_path = AST::Path(path);
+ return true;
+ }
+ }
+
+ for( auto& st : trait.supertraits() ) {
+ assert(st.is_bound());
+ if( this->find_trait_item(st, *const_cast<AST::Trait*>(st.binding().as_Trait().trait_), item_name, out_is_method, out_trait_path) )
+ return true;
+ }
+
+ return false;
+}
+
bool CPathResolver::find_local_item(AST::Path& path, const ::std::string& name, bool allow_variables)
{
TRACE_FUNCTION_F("path="<<path<<", allow_variables="<<allow_variables);
@@ -798,14 +877,14 @@ void CPathResolver::handle_type(TypeRef& type)
{
const auto& name = type.type_param();
auto opt_local = lookup_local(LocalItem::TYPE, name);
- if( name == "Self" )
+ /*if( name == "Self" )
{
// Good as it is
// - TODO: Allow replacing this with the real Self (e.g. in an impl block)
// - NEED to annotate with the relevant impl block, and with other bounds
// > So that you can handle 'where Self: Sized' etc
}
- else if( opt_local.is_some() )
+ else*/ if( opt_local.is_some() )
{
type = opt_local.unwrap().tr;
}
@@ -875,10 +954,20 @@ void CPathResolver::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint)
}
void CPathResolver::handle_module(AST::Path path, AST::Module& mod)
{
+ ::std::vector<Scope> saved = mv$(m_scope_stack);
// NOTE: Assigning here is safe, as the CASTIterator handle_module iterates submodules as the last action
m_module = &mod;
m_module_path = AST::Path(path);
CASTIterator::handle_module(mv$(path), mod);
+ m_scope_stack = mv$(saved);
+}
+void CPathResolver::handle_trait(AST::Path path, AST::Trait& trait)
+{
+ // Handle local
+ for( auto& st : trait.supertraits() ) {
+ handle_path(st, MODE_TYPE);
+ }
+ m_scope_stack.back().traits.push_back( ::std::pair<AST::Path, const AST::Trait&>(path, trait) );
}
void CPathResolver::handle_function(AST::Path path, AST::Function& fcn)
{
diff --git a/src/include/rustic.hpp b/src/include/rustic.hpp
index 84e98b31..15588565 100644
--- a/src/include/rustic.hpp
+++ b/src/include/rustic.hpp
@@ -50,23 +50,29 @@ namespace rust {
template<typename T>
class option
{
+ char m_data[ sizeof(T) ];
bool m_set;
- T m_data;
public:
option(T ent):
- m_set(true),
- m_data( ::std::move(ent) )
- {}
+ m_set(true)
+ {
+ new (m_data) T(::std::move(ent));
+ }
option():
m_set(false)
{}
+ ~option() {
+ if( m_set ) {
+ reinterpret_cast<T*>(m_data)->~T();
+ }
+ }
bool is_none() const { return !m_set; }
bool is_some() const { return m_set; }
const T& unwrap() const {
assert(is_some());
- return m_data;
+ return *reinterpret_cast<const T*>(m_data);
}
void if_set(::std::function<void (const T&)> f) const {
@@ -107,16 +113,6 @@ public:
return f(*m_ptr);
}
}
-
- //template<typename U/*, class FcnSome, class FcnNone*/>
- //U match(::std::function<U(const T&)> if_some, ::Std::function<U()> if_none) const {
- // if( m_set ) {
- // return if_some(*m_ptr);
- // }
- // else {
- // return if_none();
- // }
- //}
};
template<typename T>
option<T> Some(T data) {
@@ -127,4 +123,6 @@ option<T> None() {
return option<T>( );
}
+#define IF_OPTION_SOME(bind, var, ...) { auto __v = (var); if( var.is_some() ) { auto bind = __v.unwrap(); (void)&bind; __VA_ARGS__ } }
+
};
diff --git a/src/include/tagged_union.hpp b/src/include/tagged_union.hpp
index 15eb3148..34657ff5 100644
--- a/src/include/tagged_union.hpp
+++ b/src/include/tagged_union.hpp
@@ -107,9 +107,9 @@
return __name( ::std::move(v) );\
}\
bool is_##__tag() const { return m_tag == __tag; } \
- const __type& as_##__tag() const { return reinterpret_cast<const __type&>(m_data); } \
- __type& as_##__tag() { return reinterpret_cast<__type&>(m_data); } \
- __type unwrap_##__tag() { return ::std::move(reinterpret_cast<__type&>(m_data)); } \
+ const __type& as_##__tag() const { assert(m_tag == __tag); return reinterpret_cast<const __type&>(m_data); } \
+ __type& as_##__tag() { assert(m_tag == __tag); return reinterpret_cast<__type&>(m_data); } \
+ __type unwrap_##__tag() { assert(m_tag == __tag); return ::std::move(reinterpret_cast<__type&>(m_data)); } \
// Define a tagged union constructor
#define TU_CONS(__name, name, _) TU_CONS_I(__name, name, TU_DATANAME(name))
@@ -173,7 +173,7 @@ class _name TU_EXP _inherit { \
_name(): m_tag(_def) { new((void*)m_data) TU_DATANAME(_def); }\
_name(const _name&) = delete; \
_name(_name&& x) noexcept: m_tag(x.m_tag) { switch(m_tag) { TU_MOVE_CASES _variants } } \
- _name& operator =(_name&& x) { this->~_name(); m_tag = x.m_tag; x.m_tag = _def; switch(m_tag) { TU_MOVE_CASES _variants }; return *this; } \
+ _name& operator =(_name&& x) { this->~_name(); m_tag = x.m_tag; switch(m_tag) { TU_MOVE_CASES _variants }; return *this; } \
~_name() { switch(m_tag) { TU_DEST_CASES _variants } } \
\
Tag tag() const { return m_tag; }\
diff --git a/src/parse/lex.hpp b/src/parse/lex.hpp
index 522d2d31..f2e268ac 100644
--- a/src/parse/lex.hpp
+++ b/src/parse/lex.hpp
@@ -36,6 +36,16 @@ struct Position
};
extern ::std::ostream& operator<<(::std::ostream& os, const Position& p);
+struct Span
+{
+ ::std::string filename;
+
+ unsigned int start_line;
+ unsigned int start_ofs;
+ unsigned int end_line;
+ unsigned int end_ofs;
+};
+
class Token:
public Serialisable
{
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index d64005a9..832aa209 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -490,11 +490,19 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
}
// Trait bounds "trait Trait : 'lifetime + OtherTrait + OtherTrait2"
+ ::std::vector<AST::Path> supertraits;
if(tok.type() == TOK_COLON)
{
- // 'Self' is a special generic type only valid within traits
- Parse_TypeBound(lex, params, TypeRef(TypeRef::TagArg(), "Self"));
- GET_TOK(tok, lex);
+ do {
+ if( GET_TOK(tok, lex) == TOK_LIFETIME ) {
+ // TODO: Need a better way of indiciating 'static than just an invalid path
+ supertraits.push_back( AST::Path() );
+ }
+ else {
+ lex.putback(tok);
+ supertraits.push_back( Parse_Path(lex, PATH_GENERIC_TYPE) );
+ }
+ } while( GET_TOK(tok, lex) == TOK_PLUS );
}
// TODO: Support "for Sized?"
@@ -507,7 +515,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
}
- AST::Trait trait(mv$(meta_items), mv$(params));
+ AST::Trait trait( mv$(meta_items), mv$(params), mv$(supertraits) );
CHECK_TOK(tok, TOK_BRACE_OPEN);
while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )