diff options
author | John Hodge <tpg@mutabah.net> | 2015-04-04 08:14:06 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2015-04-04 08:14:06 +0800 |
commit | b532739cc38f6754770b7a3f8a285df6aa5cd532 (patch) | |
tree | 12a2af495998ef3b0b2beb1a83a35c7fe3a84409 | |
parent | c15006c15505ae785eb5447c055b8f9379e7fcde (diff) | |
download | mrust-b532739cc38f6754770b7a3f8a285df6aa5cd532.tar.gz |
Partial auto-determining of wildcard trait impls
-rw-r--r-- | src/ast/ast.cpp | 75 | ||||
-rw-r--r-- | src/synexts/derive.cpp | 2 |
2 files changed, 65 insertions, 12 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 1bd4e819..b5025e9c 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -10,6 +10,27 @@ namespace AST {
+class GenericResolveClosure
+{
+ const TypeParams& m_params;
+ const ::std::vector<TypeRef>& m_args;
+public:
+ GenericResolveClosure(const TypeParams& params, const ::std::vector<TypeRef>& args):
+ m_params(params),
+ m_args(args)
+ {}
+ TypeRef operator()(const char *argname) {
+ for(unsigned int i = 0; i < m_params.ty_params().size(); i ++)
+ {
+ if( m_params.ty_params()[i].name() == argname ) {
+ return m_args.at(i);
+ }
+ }
+ throw ::std::runtime_error("BUGCHECK - Unknown arg in field type");
+ }
+};
+
+
void MetaItems::push_back(MetaItem i)
{
m_items.push_back( ::std::move(i) );
@@ -272,10 +293,48 @@ bool Crate::check_impls_wildcard(const Path& trait, const TypeRef& type) else if( type.is_reference() ) {
return check_impls_wildcard(trait, type.sub_types()[0]);
}
- // - structs need all fields to impl this trait (cache result)
- // - same for enums, tuples, arrays, pointers...
- // - traits check the Self bounds
+ else if( type.is_path() ) {
+ // - structs need all fields to impl this trait (cache result)
+ // - same for enums, tuples, arrays, pointers...
+ // - traits check the Self bounds
+ // CATCH: Need to handle recursion, keep a list of currently processing paths and assume true if found
+ switch(type.path().binding().type())
+ {
+ case AST::PathBinding::STRUCT: {
+ const auto &s = type.path().binding().bound_struct();
+ GenericResolveClosure resolve_fn( s.params(), type.path().nodes().back().args() );
+ for(const auto& fld : s.fields())
+ {
+ TypeRef fld_ty = fld.data;
+ fld_ty.resolve_args( resolve_fn );
+ DEBUG("- Fld '" << fld.name << "' := " << fld.data << " => " << fld_ty);
+ // TODO: Defer failure until after all fields are processed
+ if( !check_impls_wildcard(trait, fld_ty) )
+ return false;
+ }
+ return true; }
+ case AST::PathBinding::ENUM: {
+ const auto& i = type.path().binding().bound_enum();
+ GenericResolveClosure resolve_fn( i.params(), type.path().nodes().back().args() );
+ for( const auto& var : i.variants() )
+ {
+ for( const auto& ty : var.m_sub_types )
+ {
+ TypeRef real_ty = ty;
+ real_ty.resolve_args( resolve_fn );
+ DEBUG("- Var '" << var.m_name << "' := " << ty << " => " << real_ty);
+ // TODO: Defer failure until after all fields are processed
+ if( !check_impls_wildcard(trait, real_ty) )
+ return false;
+ }
+ }
+ return true; }
+ default:
+ throw CompileError::Todo("wildcard impls - auto determine path");
+ }
+ }
else {
+ DEBUG("type = " << type);
throw CompileError::Todo("wildcard impls - auto determine");
}
}
@@ -779,15 +838,7 @@ TypeRef Struct::get_field_type(const char *name, const ::std::vector<TypeRef>& a if( args.size() )
{
TypeRef res = f.data;
- res.resolve_args( [&](const char *argname){
- for(unsigned int i = 0; i < m_params.ty_params().size(); i ++)
- {
- if( m_params.ty_params()[i].name() == argname ) {
- return args.at(i);
- }
- }
- throw ::std::runtime_error("BUGCHECK - Unknown arg in field type");
- });
+ res.resolve_args( GenericResolveClosure(m_params, args) );
return res;
}
else
diff --git a/src/synexts/derive.cpp b/src/synexts/derive.cpp index ccb4fb00..e6f191d0 100644 --- a/src/synexts/derive.cpp +++ b/src/synexts/derive.cpp @@ -47,6 +47,8 @@ class Deriver_Debug: public: AST::Impl handle_item(const AST::TypeParams& p, const TypeRef& type, const AST::Struct& str) const override { + // TODO: be correct herhe and use "core" as the crate name + // - Requires handling the crate_name crate attribute correctly const AST::Path debug_trait("", { AST::PathNode("fmt", {}), AST::PathNode("Debug", {}) }); const TypeRef ret_type(AST::Path("", {AST::PathNode("fmt",{}), AST::PathNode("Result",{})}) ); const TypeRef f_type(TypeRef::TagReference(), true, |