summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge (sonata) <tpg@mutabah.net>2015-01-18 13:48:31 +0800
committerJohn Hodge (sonata) <tpg@mutabah.net>2015-01-18 13:48:31 +0800
commit0e61ec5eafddb980eac2d6577b2e20af9aceae02 (patch)
tree95fb1a34f87be3ca9fea1f75bf1a6cf70d878577 /src
parentba61031285402285e88a16f3788c20f455acc8e3 (diff)
downloadmrust-0e61ec5eafddb980eac2d6577b2e20af9aceae02.tar.gz
Up to requiring checks for trait implementations
Diffstat (limited to 'src')
-rw-r--r--src/ast/ast.cpp7
-rw-r--r--src/ast/ast.hpp4
-rw-r--r--src/ast/path.cpp2
-rw-r--r--src/ast/path.hpp11
-rw-r--r--src/common.hpp2
-rw-r--r--src/convert/typecheck_params.cpp62
-rw-r--r--src/types.cpp16
-rw-r--r--src/types.hpp1
8 files changed, 78 insertions, 27 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp
index 696978fb..21a8b58a 100644
--- a/src/ast/ast.cpp
+++ b/src/ast/ast.cpp
@@ -291,7 +291,7 @@ SERIALISE_TYPE(Struct::, "AST_Struct", {
::std::ostream& operator<<(::std::ostream& os, const TypeParam& tp)
{
- os << "TypeParam(";
+ //os << "TypeParam(";
switch(tp.m_class)
{
case TypeParam::LIFETIME: os << "'"; break;
@@ -300,7 +300,7 @@ SERIALISE_TYPE(Struct::, "AST_Struct", {
os << tp.m_name;
os << " = ";
os << tp.m_default;
- os << ")";
+ //os << ")";
return os;
}
SERIALISE_TYPE(TypeParam::, "AST_TypeParam", {
@@ -338,7 +338,8 @@ SERIALISE_TYPE_S(GenericBound, {
::std::ostream& operator<<(::std::ostream& os, const TypeParams& tps)
{
- return os << "TypeParams({" << tps.m_params << "}, {" << tps.m_bounds << "})";
+ //return os << "TypeParams({" << tps.m_params << "}, {" << tps.m_bounds << "})";
+ return os << "<" << tps.m_params << "> where {" << tps.m_bounds << "}";
}
SERIALISE_TYPE_S(TypeParams, {
s.item(m_params);
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp
index 20d28467..579cb058 100644
--- a/src/ast/ast.hpp
+++ b/src/ast/ast.hpp
@@ -68,9 +68,11 @@ public:
{ }
bool is_trait() const { return m_lifetime == ""; }
- TypeRef& type() { return m_trait; }
+ const ::std::string& name() const { return m_argname; }
const TypeRef& type() const { return m_trait; }
+ TypeRef& type() { return m_trait; }
+
friend ::std::ostream& operator<<(::std::ostream& os, const GenericBound& x);
SERIALISABLE_PROTOTYPES();
};
diff --git a/src/ast/path.cpp b/src/ast/path.cpp
index 16c9c5cc..aff3586d 100644
--- a/src/ast/path.cpp
+++ b/src/ast/path.cpp
@@ -156,7 +156,7 @@ void Path::resolve(const Crate& root_crate)
DEBUG("Found trait");
if( is_last ) {
m_binding_type = TRAIT;
- m_binding.trait = &it->data;
+ m_binding.trait_ = &it->data;
return;
}
else if( is_sec_last ) {
diff --git a/src/ast/path.hpp b/src/ast/path.hpp
index 7d6f9462..e390d9aa 100644
--- a/src/ast/path.hpp
+++ b/src/ast/path.hpp
@@ -81,7 +81,7 @@ private:
const Module* module_;
const Enum* enum_;
const Struct* struct_;
- const Trait* trait;
+ const Trait* trait_;
const Static* static_;
const Function* func_;
struct {
@@ -155,8 +155,13 @@ public:
bool is_bound() const { return m_binding_type != UNBOUND; }
BindingType binding_type() const { return m_binding_type; }
- const Module& bound_module() const { assert(m_binding_type == MODULE); return *m_binding.module_; }
- const Trait& bound_trait() const { assert(m_binding_type == TRAIT); return *m_binding.trait; }
+ #define _(t, n, v) const t& bound_##n() const { assert(m_binding_type == v); return *m_binding.n##_; }
+ _(Module, module, MODULE)
+ _(Trait, trait, TRAIT)
+ _(Struct, struct, STRUCT)
+ _(Enum, enum, ENUM)
+ _(Function, func, FUNCTION)
+ #undef _
::std::vector<PathNode>& nodes() { return m_nodes; }
const ::std::vector<PathNode>& nodes() const { return m_nodes; }
diff --git a/src/common.hpp b/src/common.hpp
index 1e77d84a..3247ee7a 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -84,7 +84,7 @@ option<T> None() {
};
-namespace AST {
+namespace std {
template <typename T>
inline ::std::ostream& operator<<(::std::ostream& os, const ::std::vector<T>& v) {
diff --git a/src/convert/typecheck_params.cpp b/src/convert/typecheck_params.cpp
index 07d15bf6..376627c7 100644
--- a/src/convert/typecheck_params.cpp
+++ b/src/convert/typecheck_params.cpp
@@ -30,9 +30,17 @@ public:
/// \param info Generic item information (param names and bounds)
/// \param types Type parameters being passed to the generic item
/// \param allow_infer Allow inferrence (mutates \a types with conditions from \a info)
-bool check_generic_params(const AST::TypeParams& info, ::std::vector<TypeRef>& types, bool allow_infer = false)
+void check_generic_params(const AST::TypeParams& info, ::std::vector<TypeRef>& types, bool allow_infer = false)
{
+ DEBUG("(info = " << info << ", types = {" << types << "}");
+ // TODO: Need to correctly handle lifetime params here, they should be in a different list
const auto& params = info.params();
+
+ {
+ for(const auto& p : params)
+ assert(p.is_type());
+ }
+
if( types.size() > params.size() )
{
throw ::std::runtime_error(FMT("Too many generic params ("<<types.size()<<" passed, expecting "<< params.size()<<")"));
@@ -51,17 +59,58 @@ bool check_generic_params(const AST::TypeParams& info, ::std::vector<TypeRef>& t
throw ::std::runtime_error(FMT("Too few generic params, ("<<types.size()<<" passed, expecting "<<params.size()<<")"));
}
}
+ else
+ {
+ // Counts are good, time to validate types
+ }
+
+ for( unsigned int i = 0; i < types.size(); i ++ )
+ {
+ auto& type = types[i];
+ auto& param = params[i].name();
+ if( type.is_wildcard() )
+ {
+ // Type is a wildcard - this can match any condition
+ if( allow_infer )
+ {
+ // Apply conditions for this param to the type
+ // TODO: Requires supporting type "ranges" on the TypeRef
+ // Should also check for conflicting requirements (negative bounds?)
+ }
+ else
+ {
+ // This is an error, as inferrence is not currently allowed
+ throw ::std::runtime_error(FMT("Type of '_' present for param " << param << " when inferrence isn't allowed"));
+ }
+ }
+ else
+ {
+ // Not a wildcard!
+ // Check that the type fits the bounds applied to it
+ for( const auto& bound : info.bounds() )
+ {
+ if( bound.is_trait() && bound.name() == param )
+ {
+ const auto& trait = bound.type();
+ // Check if 'type' impls 'trait'
+ throw ::std::runtime_error( FMT("TODO: Check if " << type << " impls " << trait) );
+ }
+ }
+ }
+ }
}
// === CODE ===
void CGenericParamChecker::handle_path(AST::Path& path, CASTIterator::PathMode pm)
{
+ DEBUG("path = " << path);
AST::PathNode& last_node = path[path.size()-1];
switch(path.binding_type())
{
case AST::Path::TRAIT:
// Outside of expressions, param types must match perfectly
- if( m_within_expr == 0 ) {
+ if( m_within_expr == 0 )
+ {
try {
check_generic_params(path.bound_trait().params(), last_node.args());
}
@@ -71,6 +120,15 @@ void CGenericParamChecker::handle_path(AST::Path& path, CASTIterator::PathMode p
}
}
break;
+ case AST::Path::STRUCT:
+ try {
+ check_generic_params(path.bound_struct().params(), last_node.args(), (m_within_expr > 0));
+ }
+ catch( const ::std::exception& e )
+ {
+ throw ::std::runtime_error( FMT("Checking '" << path << "', threw : " << e.what()) );
+ }
+ break;
}
}
diff --git a/src/types.cpp b/src/types.cpp
index 907bffc0..230fae77 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -3,22 +3,6 @@
#include "types.hpp"
#include "ast/ast.hpp"
-template <typename T>
-inline ::std::ostream& operator<<(::std::ostream& os, const ::std::vector<T>& v) {
- if( v.size() > 0 )
- {
- bool is_first = true;
- for( const auto& i : v )
- {
- if(!is_first)
- os << ", ";
- is_first = false;
- os << i;
- }
- }
- return os;
-}
-
::std::ostream& operator<<(::std::ostream& os, const TypeRef& tr) {
os << "TypeRef(";
diff --git a/src/types.hpp b/src/types.hpp
index 2d052a06..01a50d0c 100644
--- a/src/types.hpp
+++ b/src/types.hpp
@@ -108,6 +108,7 @@ public:
m_inner_types( {::std::move(base), ::std::move(trait)} )
{}
+ bool is_wildcard() const { return m_class == ANY; }
bool is_path() const { return m_class == PATH; }
AST::Path& path() { assert(is_path()); return m_path; }
::std::vector<TypeRef>& sub_types() { return m_inner_types; }