summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2015-03-31 10:14:08 +0800
committerJohn Hodge <tpg@mutabah.net>2015-03-31 10:14:08 +0800
commitf5819ef88927734bcc36769b50d1b69de377b5db (patch)
tree8464350b07e99a9ff1058bfc94e3a29b0b3ab996
parentace202ef3d35cb5010e9164900c2c825dd6d3e8e (diff)
downloadmrust-f5819ef88927734bcc36769b50d1b69de377b5db.tar.gz
Fully convert trait name in 'impl' to be a AST:Path
-rw-r--r--src/ast/ast.cpp13
-rw-r--r--src/ast/ast.hpp14
-rw-r--r--src/ast/path.hpp2
-rw-r--r--src/common.hpp2
-rw-r--r--src/convert/ast_iterate.cpp3
-rw-r--r--src/convert/typecheck_expr.cpp4
-rw-r--r--src/convert/typecheck_params.cpp15
-rw-r--r--src/dump_as_rust.cpp2
-rw-r--r--src/parse/root.cpp12
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 )