From b532739cc38f6754770b7a3f8a285df6aa5cd532 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 4 Apr 2015 08:14:06 +0800 Subject: Partial auto-determining of wildcard trait impls --- src/ast/ast.cpp | 75 ++++++++++++++++++++++++++++++++++++++++++-------- src/synexts/derive.cpp | 2 ++ 2 files changed, 65 insertions(+), 12 deletions(-) (limited to 'src') 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& m_args; +public: + GenericResolveClosure(const TypeParams& params, const ::std::vector& 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& 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, -- cgit v1.2.3