From cae16a7a72a75f08e01b63ef31a56e75125556b6 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 5 Apr 2015 13:47:01 +0800 Subject: Move handling of wildcard trait destructure to TypeRef --- src/ast/ast.cpp | 80 +----------------------------------------------------- src/ast/ast.hpp | 20 ++++++++++++++ src/types.cpp | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/types.hpp | 2 ++ 4 files changed, 106 insertions(+), 79 deletions(-) (limited to 'src') diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 63e33ba6..aadade4f 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -10,26 +10,6 @@ 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) { @@ -278,65 +258,7 @@ bool Crate::check_impls_wildcard(const Path& trait, const TypeRef& type) DEBUG("No positive impl of " << trait << " for " << type); // 3. If none found, destructure the type - // Primitives always impl - if( type.is_primitive() || type.is_unit() ) { - return true; - } - else if( type.is_reference() ) { - return find_impl(trait, type.sub_types()[0], nullptr); - } - else if( type.is_pointer() ) { - return find_impl(trait, type.sub_types()[0], nullptr); - } - else if( type.is_type_param() ) { - // TODO: Include an annotation to the TypeParams structure relevant to this type - // - Allows searching the params for the impl, without having to pass the params down - throw CompileError::Todo("check_impls_wildcard - param"); - } - 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( !find_impl(trait, fld_ty, nullptr) ) - 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( !find_impl(trait, real_ty, nullptr) ) - return false; - } - } - return true; } - default: - throw CompileError::Todo("wildcard impls - auto determine path"); - } - } - else { - DEBUG("type = " << type); - throw CompileError::Todo("wildcard impls - auto determine"); - } + return type.impls_wildcard(*this, trait); } bool Crate::find_impl(const Path& trait, const TypeRef& type, Impl** out_impl) diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 2f6ab45f..671a0aa9 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -823,6 +823,26 @@ public: } +class GenericResolveClosure +{ + const AST::TypeParams& m_params; + const ::std::vector& m_args; +public: + GenericResolveClosure(const AST::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"); + } +}; + extern AST::Module g_compiler_module; extern void AST_InitProvidedModule(); diff --git a/src/types.cpp b/src/types.cpp index 5c15323b..99312d13 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -252,6 +252,89 @@ void TypeRef::match_args(const TypeRef& other, ::std::function " << fld_ty); + // TODO: Defer failure until after all fields are processed + if( !crate.find_impl(trait, fld_ty, nullptr) ) + return false; + } + return true; } + case AST::PathBinding::ENUM: { + const auto& i = m_path.binding().bound_enum(); + GenericResolveClosure resolve_fn( i.params(), m_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( !crate.find_impl(trait, real_ty, nullptr) ) + return false; + } + } + return true; } + default: + throw CompileError::Todo("wildcard impls - auto determine path"); + } + } + throw CompileError::BugCheck("TypeRef::impls_wildcard - Fell off end"); +} + /// Checks if the type is fully bounded bool TypeRef::is_concrete() const { diff --git a/src/types.hpp b/src/types.hpp index c56875f9..5a296e3d 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -178,6 +178,8 @@ public: /// Match 'GENERIC' entries with another type, passing matches to a closure void match_args(const TypeRef& other, ::std::function fcn) const; + bool impls_wildcard(AST::Crate& crate, const AST::Path& trait) const; + /// Returns true if the type is fully known (all sub-types are not wildcards) bool is_concrete() const; -- cgit v1.2.3