diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hir/expr_ptr.hpp | 6 | ||||
-rw-r--r-- | src/hir_expand/closures.cpp | 66 | ||||
-rw-r--r-- | src/mir/from_hir.cpp | 3 |
3 files changed, 57 insertions, 18 deletions
diff --git a/src/hir/expr_ptr.hpp b/src/hir/expr_ptr.hpp index 4ac4e86f..4060c551 100644 --- a/src/hir/expr_ptr.hpp +++ b/src/hir/expr_ptr.hpp @@ -28,7 +28,9 @@ public: ExprPtr(); ExprPtr(::std::unique_ptr< ::HIR::ExprNode> _); ExprPtr(ExprPtr&& x): - node(x.node) + node(x.node), + m_bindings( ::std::move(x.m_bindings) ), + m_mir( ::std::move(x.m_mir) ) { x.node = nullptr; } @@ -36,6 +38,8 @@ public: { this->~ExprPtr(); node = x.node; + m_bindings = ::std::move(x.m_bindings); + m_mir = ::std::move(x.m_mir); x.node = nullptr; return *this; } diff --git a/src/hir_expand/closures.cpp b/src/hir_expand/closures.cpp index 3d207f5d..5ce07886 100644 --- a/src/hir_expand/closures.cpp +++ b/src/hir_expand/closures.cpp @@ -81,7 +81,8 @@ namespace { // 1. Is it a closure-local? auto binding_it = ::std::find(m_local_vars.begin(), m_local_vars.end(), node.m_slot); if( binding_it != m_local_vars.end() ) { - node.m_slot = binding_it - m_local_vars.begin(); + // NOTE: Offset of 2 is for `self` and `args` + node.m_slot = 2 + binding_it - m_local_vars.begin(); return ; } @@ -100,15 +101,31 @@ namespace { }; struct H { + static void fix_fn_params(::HIR::ExprPtr& code, const ::HIR::TypeRef& self_ty, const ::HIR::TypeRef& args_ty) + { + if( code.m_bindings.size() == 0 ) { + // Insert 0 = Self, 1 = Args + code.m_bindings.push_back( self_ty.clone() ); + code.m_bindings.push_back( args_ty.clone() ); + } + else { + assert( code.m_bindings.size() >= 2 ); + assert( code.m_bindings[0] == ::HIR::TypeRef() ); + assert( code.m_bindings[1] == ::HIR::TypeRef() ); + code.m_bindings[0] = self_ty.clone(); + code.m_bindings[1] = args_ty.clone(); + } + } static ::HIR::TraitImpl make_fnonce( ::HIR::GenericParams params, ::HIR::PathParams trait_params, ::HIR::TypeRef closure_type, ::std::pair< ::HIR::Pattern, ::HIR::TypeRef> args_argent, ::HIR::TypeRef ret_ty, - ::HIR::ExprNodeP code + ::HIR::ExprPtr code ) { + fix_fn_params(code, closure_type, args_argent.second); return ::HIR::TraitImpl { mv$(params), mv$(trait_params), mv$(closure_type), make_map1( @@ -136,9 +153,10 @@ namespace { ::HIR::TypeRef closure_type, ::std::pair< ::HIR::Pattern, ::HIR::TypeRef> args_argent, ::HIR::TypeRef ret_ty, - ::HIR::ExprNodeP code + ::HIR::ExprPtr code ) { + fix_fn_params(code, closure_type, args_argent.second); return ::HIR::TraitImpl { mv$(params), mv$(trait_params), mv$(closure_type), make_map1( @@ -167,9 +185,10 @@ namespace { ::HIR::TypeRef closure_type, ::std::pair< ::HIR::Pattern, ::HIR::TypeRef> args_argent, ::HIR::TypeRef ret_ty, - ::HIR::ExprNodeP code + ::HIR::ExprPtr code ) { + fix_fn_params(code, closure_type, args_argent.second); return ::HIR::TraitImpl { mv$(params), mv$(trait_params), mv$(closure_type), make_map1( @@ -258,34 +277,31 @@ namespace { m_closure_stack.pop_back(); // --- Extract and mutate code into a trait impl on the closure type --- - - // 1. Iterate over the nodes and rewrite variable accesses to either renumbered locals, or field accesses - ExprVisitor_Mutate ev { node.m_res_type, ent.local_vars, ent.node.m_var_captures }; - ev.visit_node_ptr( node.m_code ); - // 2. Construct closure type (saving path/index in the node) - // Includes: - // - Generics based on the current scope (compacted) + + // 1. Construct closure type (saving path/index in the node) ::HIR::GenericParams params; ::HIR::PathParams constructor_path_params; + // - 0xFFFF "Self" -> 0 "Super" constructor_path_params.m_types.push_back( ::HIR::TypeRef("Self", 0xFFFF) ); params.m_types.push_back( ::HIR::TypeParamDef { "Super", {}, false } ); // TODO: Maybe Self is sized? + // - Top-level params come first unsigned ofs_impl = params.m_types.size(); for(const auto& ty_def : m_resolve.impl_generics().m_types) { constructor_path_params.m_types.push_back( ::HIR::TypeRef( ty_def.m_name, 0*256 + params.m_types.size() - ofs_impl ) ); params.m_types.push_back( ::HIR::TypeParamDef { ty_def.m_name, {}, ty_def.m_is_sized } ); } + // - Item-level params come second unsigned ofs_item = params.m_types.size(); for(const auto& ty_def : m_resolve.item_generics().m_types) { constructor_path_params.m_types.push_back( ::HIR::TypeRef( ty_def.m_name, 1*256 + params.m_types.size() - ofs_item ) ); params.m_types.push_back( ::HIR::TypeParamDef { ty_def.m_name, {}, ty_def.m_is_sized } ); } - + // Create placeholders for `monomorph_cb` to use ::std::vector<::HIR::TypeRef> params_placeholders; for(unsigned int i = 0; i < params.m_types.size(); i ++) { params_placeholders.push_back( ::HIR::TypeRef(params.m_types[i].m_name, i) ); } - // - Types of captured variables (to be monomorphised) auto monomorph_cb = [&](const auto& ty)->const auto& { const auto& ge = ty.m_data.as_Generic(); if( ge.binding == 0xFFFF ) { @@ -305,6 +321,21 @@ namespace { BUG(sp, "Generic type " << ty << " unknown"); } }; + + // 2. Iterate over the nodes and rewrite variable accesses to either renumbered locals, or field accesses + // - TODO: Monomorphise all referenced types within this + ExprVisitor_Mutate ev { node.m_res_type, ent.local_vars, ent.node.m_var_captures }; + ev.visit_node_ptr( node.m_code ); + + // - Types of local variables + ::std::vector< ::HIR::TypeRef> local_types; + local_types.push_back( ::HIR::TypeRef() ); // self - filled by make_fn* + local_types.push_back( ::HIR::TypeRef() ); // args - filled by make_fn* + for(const auto binding_idx : ent.local_vars) { + auto ty_mono = monomorphise_type_with(sp, m_variable_types.at(binding_idx).clone(), monomorph_cb); + local_types.push_back( mv$(ty_mono) ); + } + // - Types of captured variables (to be monomorphised) ::std::vector< ::HIR::VisEnt< ::HIR::TypeRef> > capture_types; for(const auto binding_idx : node.m_var_captures) { auto ty_mono = monomorphise_type_with(sp, m_variable_types.at(binding_idx).clone(), monomorph_cb); @@ -330,6 +361,9 @@ namespace { } ::HIR::TypeRef args_ty { mv$(args_ty_inner) }; ::HIR::Pattern args_pat { {}, ::HIR::Pattern::Data::make_Tuple({ mv$(args_pat_inner) }) }; + + ::HIR::ExprPtr body_code { mv$(node.m_code) }; + body_code.m_bindings = mv$(local_types); // 3. Create trait impls ::HIR::TypeRef closure_type = node.m_res_type.clone(); @@ -387,7 +421,7 @@ namespace { // - Fn m_out_impls.push_back(::std::make_pair( ::HIR::ExprNode_Closure::Class::Shared, - H::make_fn( mv$(params), mv$(trait_params), mv$(closure_type), ::std::make_pair(mv$(args_pat), mv$(args_ty)), node.m_return.clone(), mv$(node.m_code) ) + H::make_fn( mv$(params), mv$(trait_params), mv$(closure_type), ::std::make_pair(mv$(args_pat), mv$(args_ty)), node.m_return.clone(), mv$(body_code) ) )); } break; case ::HIR::ExprNode_Closure::Class::Mut: { @@ -417,14 +451,14 @@ namespace { // - FnMut (code) m_out_impls.push_back(::std::make_pair( ::HIR::ExprNode_Closure::Class::Mut, - H::make_fn( mv$(params), mv$(trait_params), mv$(closure_type), ::std::make_pair(mv$(args_pat), mv$(args_ty)), node.m_return.clone(), mv$(node.m_code) ) + H::make_fnmut( mv$(params), mv$(trait_params), mv$(closure_type), ::std::make_pair(mv$(args_pat), mv$(args_ty)), node.m_return.clone(), mv$(body_code) ) )); } break; case ::HIR::ExprNode_Closure::Class::Once: // - FnOnce (code) m_out_impls.push_back(::std::make_pair( ::HIR::ExprNode_Closure::Class::Once, - H::make_fnonce( mv$(params), mv$(trait_params), mv$(closure_type), ::std::make_pair(mv$(args_pat), mv$(args_ty)), node.m_return.clone(), mv$(node.m_code) ) + H::make_fnonce( mv$(params), mv$(trait_params), mv$(closure_type), ::std::make_pair(mv$(args_pat), mv$(args_ty)), node.m_return.clone(), mv$(body_code) ) )); break; } diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 6727ab4b..0edec1f9 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -975,13 +975,14 @@ namespace { ::std::vector< ::MIR::LValue> vals; for( const auto cap_idx : node.m_var_captures ) { + ASSERT_BUG(node.span(), cap_idx < m_variable_types.size(), "Capture #" << cap_idx << " not in variable set (" << m_variable_types.size() << " total)"); if( node.m_is_move ) { vals.push_back( ::MIR::LValue::make_Variable(cap_idx) ); } else { auto borrow_ty = ::HIR::BorrowType::Shared; auto lval = m_builder.lvalue_or_temp( - ::HIR::TypeRef::new_borrow(borrow_ty, m_variable_types.at(cap_idx).clone()), + ::HIR::TypeRef::new_borrow(borrow_ty, m_variable_types[cap_idx].clone()), ::MIR::RValue::make_Borrow({ 0, borrow_ty, ::MIR::LValue::make_Variable(cap_idx) }) ); vals.push_back( mv$(lval) ); |