summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2015-03-31 22:40:04 +0800
committerJohn Hodge <tpg@mutabah.net>2015-03-31 22:40:04 +0800
commitc2684e5058415746c83e38676f91bfc32d2ee6eb (patch)
tree98ce27dcd287f52b261f9346d7bfc98ac8776483
parentc5b773f72a8ef077d8d189912014f64431825df5 (diff)
downloadmrust-c2684e5058415746c83e38676f91bfc32d2ee6eb.tar.gz
Root-level typecheck now up to requiring Sized
-rw-r--r--src/ast/ast.cpp55
-rw-r--r--src/ast/path.cpp38
-rw-r--r--src/ast/path.hpp3
-rw-r--r--src/ast/provided_module.cpp24
-rw-r--r--src/convert/resolve.cpp21
-rw-r--r--src/types.cpp23
6 files changed, 107 insertions, 57 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp
index c071e139..0ebc3e4e 100644
--- a/src/ast/ast.cpp
+++ b/src/ast/ast.cpp
@@ -92,37 +92,42 @@ Impl Impl::make_concrete(const ::std::vector<TypeRef>& types) const
if( type_match < 0 )
return ::rust::option<Impl&>();
DEBUG("Type " << type << " matches " << type_match);
+
// 2. If a parameter was seen, do the more expensive generic checks
// > Involves checking that parameters are valid
- if( trait_match > 0 )
- {
- throw CompileError::Todo("Generic-ised match of impl trait");
- }
- if( type_match > 0 )
+ if( m_params.ty_params().size() )
{
- throw CompileError::Todo("Generic-ised match of impl type");
- }
- // 3. Return success
-
- if( m_params.ty_params().size() > 0 )
+ if( trait_match == 0 && type_match == 0 )
+ throw CompileError::Generic( "Unbound generic in impl" );
+ }
+
+ if( !(trait_match == 0 && type_match == 0) )
{
::std::vector<TypeRef> param_types(m_params.ty_params().size());
try
{
- auto c = [&](const char* name,const TypeRef& ty){
+ auto c = [&](const char* name,const TypeRef& ty) {
+ if( strcmp(name, "Self") == 0 ) {
+ if( ty != type )
+ throw CompileError::Generic(FMT("Self mismatch : " << ty));
+ return ;
+ }
int idx = m_params.find_name(name);
assert( idx >= 0 );
assert( (unsigned)idx < param_types.size() );
param_types[idx].merge_with( ty );
};
- throw CompileError::Todo("Match arguments in path for m_trait");
- //m_trait.match_args(TypeRef(trait), c);
+ m_trait.match_args(trait, c);
m_type.match_args(type, c);
-
- // Check that conditions match
- // - TODO: Requires locating/checking trait implementations on types
-
- // The above two will throw if matching failed, so if we get here, it's a match
+ }
+ catch(const CompileError::Base& e)
+ {
+ DEBUG("No match - " << e.what());
+ return ::rust::option<Impl&>();
+ }
+
+ if( param_types.size() > 0 )
+ {
for( auto& i : m_concrete_impls )
{
if( i.first == param_types )
@@ -130,22 +135,12 @@ Impl Impl::make_concrete(const ::std::vector<TypeRef>& types) const
return ::rust::option<Impl&>(i.second);
}
}
+
m_concrete_impls.push_back( make_pair(param_types, this->make_concrete(param_types)) );
return ::rust::option<Impl&>( m_concrete_impls.back().second );
}
- catch( const ::std::runtime_error& e )
- {
- DEBUG("No match - " << e.what());
- }
}
- else
- {
- if( m_trait == trait && m_type == type )
- {
- return ::rust::option<Impl&>( *this );
- }
- }
- return ::rust::option<Impl&>();
+ return ::rust::option<Impl&>( *this );
}
::std::ostream& operator<<(::std::ostream& os, const Impl& impl)
diff --git a/src/ast/path.cpp b/src/ast/path.cpp
index 222ce918..80344d01 100644
--- a/src/ast/path.cpp
+++ b/src/ast/path.cpp
@@ -419,6 +419,29 @@ Path& Path::operator+=(const Path& other)
return *this;
}
+void Path::match_args(const Path& other, ::std::function<void(const char*,const TypeRef&)> fcn) const
+{
+ if( m_nodes.size() != other.m_nodes.size() )
+ throw ::std::runtime_error("Type mismatch (path size)");
+ for( unsigned int i = 0; i < m_nodes.size(); i++ )
+ {
+ auto& pn1 = m_nodes[i];
+ auto& pn2 = other.m_nodes[i];
+ if( pn1.name() != pn2.name() )
+ throw ::std::runtime_error("Type mismatch (path component)");
+
+ if( pn1.args().size() != pn2.args().size() )
+ throw ::std::runtime_error("Type mismatch (path component param count)");
+
+ for( unsigned int j = 0; j < pn1.args().size(); j ++ )
+ {
+ auto& t1 = pn1.args()[j];
+ auto& t2 = pn2.args()[j];
+ t1.match_args( t2, fcn );
+ }
+ }
+}
+
int Path::equal_no_generic(const Path& x) const
{
if( m_class != x.m_class )
@@ -426,6 +449,7 @@ int Path::equal_no_generic(const Path& x) const
if( m_crate != x.m_crate )
return -1;
+ bool conditional_match = false;
unsigned int i = 0;
for( const auto &e : m_nodes )
{
@@ -437,15 +461,21 @@ int Path::equal_no_generic(const Path& x) const
if( e.args().size() || xe.args().size() )
{
- //
- DEBUG("e = " << e << ", xe = " << xe);
- throw CompileError::Todo("Handle Path::equal_no_generic with generic");
+ DEBUG("e = " << e << ", xe = " << xe);
+ if( e.args().size() != xe.args().size() )
+ throw CompileError::BugCheck("Generics should be resolved, and hence have the correct argument count");
+ for( unsigned int j = 0; j < e.args().size(); j ++ )
+ {
+ int rv = e.args()[j].equal_no_generic( xe.args()[j] );
+ if(rv < 0) return rv;
+ if(rv > 0) conditional_match = true;
+ }
}
i ++;
}
- return 0;
+ return (conditional_match ? 1 : 0);
}
Ordering Path::ord(const Path& x) const
diff --git a/src/ast/path.hpp b/src/ast/path.hpp
index 1bf2ba7d..a2ca316b 100644
--- a/src/ast/path.hpp
+++ b/src/ast/path.hpp
@@ -255,6 +255,9 @@ public:
/// Resolve generic arguments within the path
void resolve_args(::std::function<TypeRef(const char*)> fcn);
+ /// Match args
+ void match_args(const Path& other, ::std::function<void(const char*,const TypeRef&)> fcn) const;
+
bool is_trivial() const {
return m_class == RELATIVE && m_nodes.size() == 1 && m_nodes[0].args().size() == 0;
}
diff --git a/src/ast/provided_module.cpp b/src/ast/provided_module.cpp
index bb1da26b..7bea81d4 100644
--- a/src/ast/provided_module.cpp
+++ b/src/ast/provided_module.cpp
@@ -12,7 +12,31 @@ void AST_InitProvidedModule()
});
AST::Path copy_marker_path({AST::PathNode("marker"),AST::PathNode("Copy")});
+ g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_U8), copy_marker_path));
+ g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_U16), copy_marker_path));
+ g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_U32), copy_marker_path));
+ g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_U64), copy_marker_path));
+ g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_UINT), copy_marker_path));
+
+ g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_I8), copy_marker_path));
+ g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_I16), copy_marker_path));
+ g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_I32), copy_marker_path));
+ g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_I64), copy_marker_path));
+ g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_INT), copy_marker_path));
+
g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_F32), copy_marker_path));
g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_F64), copy_marker_path));
+
+ // A hacky default impl of 'Sized', with a negative impl on [T]
+ AST::Path sized_marker_path({AST::PathNode("marker"),AST::PathNode("Sized")});
+ g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(), copy_marker_path));
+ AST::TypeParams tps;
+ tps.add_ty_param( AST::TypeParam("T") );
+ g_compiler_module.add_impl(AST::Impl(
+ AST::Impl::TagNegative(),
+ ::std::move(tps),
+ TypeRef(TypeRef::TagUnsizedArray(), TypeRef(TypeRef::TagArg(), "T")),
+ copy_marker_path
+ ));
}
diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp
index 3e690f61..bca0f576 100644
--- a/src/convert/resolve.cpp
+++ b/src/convert/resolve.cpp
@@ -23,15 +23,15 @@ class CPathResolver:
VAR,
} type;
::std::string name;
- AST::Path path;
+ TypeRef tr;
LocalItem():
type(VAR), name()
{}
- LocalItem(Type t, ::std::string name, AST::Path path=AST::Path()):
+ LocalItem(Type t, ::std::string name, TypeRef tr=TypeRef()):
type(t),
name( ::std::move(name) ),
- path( ::std::move(path) )
+ tr( ::std::move(tr) )
{}
friend ::std::ostream& operator<<(::std::ostream& os, const LocalItem& x) {
@@ -60,7 +60,7 @@ public:
virtual void start_scope() override;
virtual void local_type(::std::string name, TypeRef type) override {
- m_locals.push_back( LocalItem(LocalItem::TYPE, ::std::move(name)) );
+ m_locals.push_back( LocalItem(LocalItem::TYPE, ::std::move(name), ::std::move(type)) );
}
virtual void local_variable(bool _is_mut, ::std::string name, const TypeRef& _type) override {
m_locals.push_back( LocalItem(LocalItem::VAR, ::std::move(name)) );
@@ -500,6 +500,19 @@ void CPathResolver::handle_type(TypeRef& type)
// Not a type param, fall back to other checks
}
}
+
+ //if( type.is_type_param() && type.type_param() == "Self" )
+ //{
+ // auto l = lookup_local(LocalItem::TYPE, "Self");
+ // if( l.is_some() )
+ // {
+ // type = l.unwrap().tr;
+ // DEBUG("Replacing Self with " << type);
+ // // TODO: Can this recurse?
+ // handle_type(type);
+ // return ;
+ // }
+ //}
CASTIterator::handle_type(type);
DEBUG("res = " << type);
}
diff --git a/src/types.cpp b/src/types.cpp
index e9460886..329e93f8 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -245,25 +245,7 @@ void TypeRef::match_args(const TypeRef& other, ::std::function<void(const char*,
case TypeRef::GENERIC:
throw ::std::runtime_error("Encountered GENERIC in match_args");
case TypeRef::PATH:
- if( m_path.size() != other.m_path.size() )
- throw ::std::runtime_error("Type mismatch (path size)");
- for( unsigned int i = 0; i < m_path.size(); i++ )
- {
- auto& pn1 = m_path[i];
- auto& pn2 = other.m_path[i];
- if( pn1.name() != pn2.name() )
- throw ::std::runtime_error("Type mismatch (path component)");
-
- if( pn1.args().size() != pn2.args().size() )
- throw ::std::runtime_error("Type mismatch (path component param count)");
-
- for( unsigned int j = 0; j < pn1.args().size(); j ++ )
- {
- auto& t1 = pn1.args()[j];
- auto& t2 = pn2.args()[j];
- t1.match_args( t2, fcn );
- }
- }
+ m_path.match_args(other.m_path, fcn);
break;
case TypeRef::MULTIDST:
throw ::std::runtime_error("TODO: TypeRef::match_args on MULTIDST");
@@ -313,6 +295,9 @@ bool TypeRef::is_concrete() const
int TypeRef::equal_no_generic(const TypeRef& x) const
{
+ DEBUG(*this << ", " << x);
+ if( m_class == TypeRef::GENERIC || x.m_class == TypeRef::GENERIC )
+ return 1;
if( m_class != x.m_class ) return -1;
switch(m_class)
{