diff options
-rw-r--r-- | src/ast/ast.cpp | 13 | ||||
-rw-r--r-- | src/ast/ast.hpp | 14 | ||||
-rw-r--r-- | src/ast/path.hpp | 2 | ||||
-rw-r--r-- | src/common.hpp | 2 | ||||
-rw-r--r-- | src/convert/ast_iterate.cpp | 3 | ||||
-rw-r--r-- | src/convert/typecheck_expr.cpp | 4 | ||||
-rw-r--r-- | src/convert/typecheck_params.cpp | 15 | ||||
-rw-r--r-- | src/dump_as_rust.cpp | 2 | ||||
-rw-r--r-- | src/parse/root.cpp | 12 |
9 files changed, 44 insertions, 23 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index f5d87d72..b8e6d381 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -78,9 +78,10 @@ Impl Impl::make_concrete(const ::std::vector<TypeRef>& types) const */
}
-::rust::option<Impl&> Impl::matches(const TypeRef& trait, const TypeRef& type)
+::rust::option<Impl&> Impl::matches(const Path& trait, const TypeRef& type)
{
DEBUG("this = " << *this);
+
if( m_params.ty_params().size() > 0 )
{
::std::vector<TypeRef> param_types(m_params.ty_params().size());
@@ -92,7 +93,8 @@ Impl Impl::make_concrete(const ::std::vector<TypeRef>& types) const assert( (unsigned)idx < param_types.size() );
param_types[idx].merge_with( ty );
};
- m_trait.match_args(trait, c);
+ throw CompileError::Todo("Match arguments in path for m_trait");
+ //m_trait.match_args(TypeRef(trait), c);
m_type.match_args(type, c);
// Check that conditions match
@@ -180,12 +182,13 @@ const Module& Crate::get_root_module(const ::std::string& name) const { throw ParseError::Generic("crate name unknown");
}
-::rust::option<Impl&> Crate::find_impl(const TypeRef& trait, const TypeRef& type)
+::rust::option<Impl&> Crate::find_impl(const Path& trait, const TypeRef& type)
{
+ // TODO: Do a sort to allow a binary search
DEBUG("trait = " << trait << ", type = " << type);
// TODO: Support autoderef here? NO
- if( trait.is_wildcard() && !type.is_path() )
+ if( trait == Path() && !type.is_path() )
{
// You can only have 'impl <type> { }' for user-defined types (i.e. paths)
// - Return failure
@@ -801,7 +804,7 @@ bool TypeParams::check_params(Crate& crate, ::std::vector<TypeRef>& types, bool {
const auto& trait = bound.bound();
// Check if 'type' impls 'trait'
- if( !crate.find_impl(type, trait).is_some() )
+ if( !crate.find_impl(trait, trait).is_some() )
{
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 af73dca2..182652cc 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -439,7 +439,7 @@ class Impl: public Serialisable
{
TypeParams m_params;
- TypeRef m_trait;
+ Path m_trait;
TypeRef m_type;
bool m_is_negative;
@@ -449,7 +449,7 @@ class Impl: ::std::vector< ::std::pair< ::std::vector<TypeRef>, Impl > > m_concrete_impls;
public:
Impl(): m_is_negative(false) {}
- Impl(TypeParams params, TypeRef impl_type, TypeRef trait_type):
+ Impl(TypeParams params, TypeRef impl_type, Path trait_type):
m_params( move(params) ),
m_trait( move(trait_type) ),
m_type( move(impl_type) ),
@@ -457,7 +457,7 @@ public: {}
struct TagNegative {};
- Impl(TagNegative, TypeParams params, TypeRef impl_type, TypeRef trait_type):
+ Impl(TagNegative, TypeParams params, TypeRef impl_type, Path trait_type):
m_params( move(params) ),
m_trait( move(trait_type) ),
m_type( move(impl_type) ),
@@ -472,20 +472,20 @@ public: }
const TypeParams& params() const { return m_params; }
- const TypeRef& trait() const { return m_trait; }
+ const Path& trait() const { return m_trait; }
const TypeRef& type() const { return m_type; }
const ItemList<Function>& functions() const { return m_functions; }
const ItemList<TypeRef>& types() const { return m_types; }
TypeParams& params() { return m_params; }
- TypeRef& trait() { return m_trait; }
+ Path& trait() { return m_trait; }
TypeRef& type() { return m_type; }
ItemList<Function>& functions() { return m_functions; }
ItemList<TypeRef>& types() { return m_types; }
Impl make_concrete(const ::std::vector<TypeRef>& types) const;
- ::rust::option<Impl&> matches(const TypeRef& trait, const TypeRef& type);
+ ::rust::option<Impl&> matches(const Path& trait, const TypeRef& type);
friend ::std::ostream& operator<<(::std::ostream& os, const Impl& impl);
SERIALISABLE_PROTOTYPES();
@@ -693,7 +693,7 @@ public: void post_parse();
- ::rust::option<Impl&> find_impl(const TypeRef& trait, const TypeRef& type);
+ ::rust::option<Impl&> find_impl(const Path& trait, const TypeRef& type);
Function& lookup_method(const TypeRef& type, const char *name);
void load_extern_crate(::std::string name);
diff --git a/src/ast/path.hpp b/src/ast/path.hpp index 94af94da..2355c88b 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -266,6 +266,8 @@ public: 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; } + bool operator<(const Path& x) const { return ord(x) != OrdLess; } SERIALISABLE_PROTOTYPES(); void print_pretty(::std::ostream& os) const; diff --git a/src/common.hpp b/src/common.hpp index 4c8d5f23..8ab37682 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -27,7 +27,7 @@ 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() ) + if( i >= r.size() ) return OrdGreater; auto rv = it.ord(r[i]); diff --git a/src/convert/ast_iterate.cpp b/src/convert/ast_iterate.cpp index c6293393..a80b1f7f 100644 --- a/src/convert/ast_iterate.cpp +++ b/src/convert/ast_iterate.cpp @@ -287,7 +287,8 @@ void CASTIterator::handle_impl(AST::Path modpath, AST::Impl& impl) handle_params( impl.params() ); // Trait - handle_type( impl.trait() ); + if( impl.trait() != AST::Path() ) + handle_path( impl.trait(), MODE_TYPE ); // Type handle_type( impl.type() ); diff --git a/src/convert/typecheck_expr.cpp b/src/convert/typecheck_expr.cpp index 57678e94..4fb7f174 100644 --- a/src/convert/typecheck_expr.cpp +++ b/src/convert/typecheck_expr.cpp @@ -503,7 +503,7 @@ void CTC_NodeVisitor::visit(AST::ExprNode_CallMethod& node) else { // 2. Find inherent impl - auto oimpl = m_tc.m_crate.find_impl(TypeRef(), ltype); + auto oimpl = m_tc.m_crate.find_impl(AST::Path(), ltype); if( oimpl.is_some() ) { AST::Impl& impl = oimpl.unwrap(); @@ -522,7 +522,7 @@ void CTC_NodeVisitor::visit(AST::ExprNode_CallMethod& node) // 2. Iterate in-scope traits m_tc.iterate_traits( [&](const TypeRef& trait) { // TODO: Check trait first, then find an impl - auto oimpl = m_tc.m_crate.find_impl(trait, ltype); + auto oimpl = m_tc.m_crate.find_impl(trait.path(), ltype); if( oimpl.is_some() ) { AST::Impl& impl = oimpl.unwrap(); diff --git a/src/convert/typecheck_params.cpp b/src/convert/typecheck_params.cpp index 28c4e72a..2e4bc97c 100644 --- a/src/convert/typecheck_params.cpp +++ b/src/convert/typecheck_params.cpp @@ -30,7 +30,14 @@ class CGenericParamChecker: }; // name == "" indicates edge of a scope ::std::vector<LocalType> m_types_stack; + + AST::Crate& m_crate; public: + CGenericParamChecker(AST::Crate& c): + m_crate(c) + { + } + virtual void handle_path(AST::Path& path, CASTIterator::PathMode pm) override; virtual void handle_expr(AST::ExprNode& root) override; void start_scope() override; @@ -114,6 +121,12 @@ bool CGenericParamChecker::has_impl(const TypeRef& type, const AST::Path& trait) else { // Search all known impls of this trait (TODO: keep a list at the crate level) for a match to this type + auto i = m_crate.find_impl(trait, trait); + if( i.is_none() ) { + DEBUG("- Nope"); + return false; + } + throw CompileError::Todo( FMT("Search for impls on " << type << " for trait " << trait) ); } @@ -299,7 +312,7 @@ const CGenericParamChecker::LocalType* CGenericParamChecker::find_type_by_name(c void Typecheck_GenericParams(AST::Crate& crate) { DEBUG(" >>> "); - CGenericParamChecker chk; + CGenericParamChecker chk(crate); chk.handle_module(AST::Path({}), crate.root_module()); DEBUG(" <<< "); } diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp index bac9d104..45c5df5d 100644 --- a/src/dump_as_rust.cpp +++ b/src/dump_as_rust.cpp @@ -636,7 +636,7 @@ void RustPrinter::handle_module(const AST::Module& mod) m_os << "\n"; m_os << indent() << "impl"; print_params(i.params()); - if( i.trait() != TypeRef() ) + if( !(i.trait() == AST::Path()) ) { m_os << " " << i.trait() << " for"; } diff --git a/src/parse/root.cpp b/src/parse/root.cpp index eefe0d52..2beac535 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -651,13 +651,13 @@ AST::Impl Parse_Impl(TokenStream& lex, bool is_unsafe/*=false*/) }
// 2. Either a trait name (with type params), or the type to impl
- TypeRef trait_type;
+ AST::Path trait_path;
TypeRef impl_type;
// - Handle negative impls, which must be a trait
// "impl !Trait for Type {}"
if( GET_TOK(tok, lex) == TOK_EXCLAM )
{
- trait_type = Parse_Type(lex);
+ trait_path = Parse_Path(lex, PATH_GENERIC_TYPE);
GET_CHECK_TOK(tok, lex, TOK_RWORD_FOR);
impl_type = Parse_Type(lex);
@@ -671,7 +671,7 @@ AST::Impl Parse_Impl(TokenStream& lex, bool is_unsafe/*=false*/) GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE);
return AST::Impl(AST::Impl::TagNegative(), ::std::move(params),
- ::std::move(impl_type), ::std::move(trait_type)
+ ::std::move(impl_type), ::std::move(trait_path)
);
}
else
@@ -684,7 +684,9 @@ AST::Impl Parse_Impl(TokenStream& lex, bool is_unsafe/*=false*/) if( GET_TOK(tok, lex) == TOK_RWORD_FOR )
{
- trait_type = impl_type;
+ if( !impl_type.is_path() )
+ throw ParseError::Generic(lex, "Trait was not a path");
+ trait_path = impl_type.path();
// Implementing a trait for another type, get the target type
if( GET_TOK(tok, lex) == TOK_DOUBLE_DOT )
{
@@ -712,7 +714,7 @@ AST::Impl Parse_Impl(TokenStream& lex, bool is_unsafe/*=false*/) }
GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
- AST::Impl impl( ::std::move(params), ::std::move(impl_type), ::std::move(trait_type) );
+ AST::Impl impl( ::std::move(params), ::std::move(impl_type), ::std::move(trait_path) );
// A sequence of method implementations
while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
|