diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hir_typeck/helpers.cpp | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 540a2a90..d31b5b7d 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -940,13 +940,13 @@ bool TraitResolution::find_trait_impls(const Span& sp, ) return callback( type, ::HIR::PathParams(), {} ); } + + const auto& trait_fn = this->m_crate.get_lang_item_path(sp, "fn"); + const auto& trait_fn_mut = this->m_crate.get_lang_item_path(sp, "fn_mut"); + const auto& trait_fn_once = this->m_crate.get_lang_item_path(sp, "fn_once"); // Closures are magical. They're unnamable and all trait impls come from within the compiler TU_IFLET(::HIR::TypeRef::Data, type.m_data, Closure, e, - const auto trait_fn = this->m_crate.get_lang_item_path(sp, "fn"); - const auto trait_fn_mut = this->m_crate.get_lang_item_path(sp, "fn_mut"); - const auto trait_fn_once = this->m_crate.get_lang_item_path(sp, "fn_once"); - if( trait == trait_fn || trait == trait_fn_mut || trait == trait_fn_once ) { if( params.m_types.size() != 1 ) BUG(sp, "Fn* traits require a single tuple argument"); @@ -974,6 +974,35 @@ bool TraitResolution::find_trait_impls(const Span& sp, } ) + // Magic Fn* trait impls for function pointers + TU_IFLET(::HIR::TypeRef::Data, type.m_data, Function, e, + if( trait == trait_fn || trait == trait_fn_mut || trait == trait_fn_once ) { + if( params.m_types.size() != 1 ) + BUG(sp, "Fn* traits require a single tuple argument"); + + // NOTE: unsafe or non-rust ABI functions aren't valid + if( e.m_abi != "rust" || e.is_unsafe ) { + DEBUG("- No magic impl, wrong ABI or unsafe in " << type); + return false; + } + DEBUG("- Magic impl of Fn* for " << type); + + ::std::vector< ::HIR::TypeRef> args; + for(const auto& at : e.m_arg_types) { + args.push_back( at.clone() ); + } + + // NOTE: This is a conditional "true", we know nothing about the move/mut-ness of this closure yet + // - Could we? + ::HIR::PathParams pp; + pp.m_types.push_back( ::HIR::TypeRef(mv$(args)) ); + ::std::map< ::std::string, ::HIR::TypeRef> types; + types.insert( ::std::make_pair( "Output", e.m_rettype->clone() ) ); + return callback( type, pp, types ); + } + // Continue + ) + // 1. Search generic params if( find_trait_impls_bound(sp, trait, params, type, callback) ) return true; |