diff options
author | John Hodge (sonata) <tpg@mutabah.net> | 2015-01-18 13:48:31 +0800 |
---|---|---|
committer | John Hodge (sonata) <tpg@mutabah.net> | 2015-01-18 13:48:31 +0800 |
commit | 0e61ec5eafddb980eac2d6577b2e20af9aceae02 (patch) | |
tree | 95fb1a34f87be3ca9fea1f75bf1a6cf70d878577 /src | |
parent | ba61031285402285e88a16f3788c20f455acc8e3 (diff) | |
download | mrust-0e61ec5eafddb980eac2d6577b2e20af9aceae02.tar.gz |
Up to requiring checks for trait implementations
Diffstat (limited to 'src')
-rw-r--r-- | src/ast/ast.cpp | 7 | ||||
-rw-r--r-- | src/ast/ast.hpp | 4 | ||||
-rw-r--r-- | src/ast/path.cpp | 2 | ||||
-rw-r--r-- | src/ast/path.hpp | 11 | ||||
-rw-r--r-- | src/common.hpp | 2 | ||||
-rw-r--r-- | src/convert/typecheck_params.cpp | 62 | ||||
-rw-r--r-- | src/types.cpp | 16 | ||||
-rw-r--r-- | src/types.hpp | 1 |
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; }
|