diff options
Diffstat (limited to 'src/hir_expand/closures.cpp')
-rw-r--r-- | src/hir_expand/closures.cpp | 397 |
1 files changed, 345 insertions, 52 deletions
diff --git a/src/hir_expand/closures.cpp b/src/hir_expand/closures.cpp index 51b2c638..c53396a0 100644 --- a/src/hir_expand/closures.cpp +++ b/src/hir_expand/closures.cpp @@ -9,6 +9,7 @@ #include <hir/expr.hpp> #include <hir_typeck/static.hpp> #include <algorithm> +#include <hir/expr_state.hpp> #include "main_bindings.hpp" namespace { @@ -18,7 +19,7 @@ namespace { namespace { - typedef ::std::function< ::HIR::SimplePath(::HIR::Struct )> new_type_cb_t; + typedef ::std::function< ::std::pair<::HIR::SimplePath, const ::HIR::Struct*>(const char* suffix, ::HIR::Struct )> new_type_cb_t; typedef ::std::vector< ::std::pair< ::HIR::ExprNode_Closure::Class, ::HIR::TraitImpl> > out_impls_t; template<typename K, typename V> @@ -45,6 +46,50 @@ namespace { return rv; } + void push_new_impls(const Span& sp, ::HIR::Crate& crate, out_impls_t new_trait_impls) + { + for(auto& impl : new_trait_impls) + { + ::HIR::Crate::ImplGroup<::HIR::TraitImpl>::list_t* trait_impl_list; + switch(impl.first) + { + case ::HIR::ExprNode_Closure::Class::Once: + trait_impl_list = &crate.m_trait_impls[crate.get_lang_item_path(sp, "fn_once")].get_list_for_type_mut(impl.second.m_type); + if(0) + case ::HIR::ExprNode_Closure::Class::Mut: + trait_impl_list = &crate.m_trait_impls[crate.get_lang_item_path(sp, "fn_mut" )].get_list_for_type_mut(impl.second.m_type); + if(0) + case ::HIR::ExprNode_Closure::Class::Shared: + trait_impl_list = &crate.m_trait_impls[crate.get_lang_item_path(sp, "fn" )].get_list_for_type_mut(impl.second.m_type); + trait_impl_list->push_back( box$(impl.second) ); + break; + case ::HIR::ExprNode_Closure::Class::NoCapture: { + assert(impl.second.m_methods.size() == 1); + assert(impl.second.m_types.empty()); + assert(impl.second.m_constants.empty()); + // NOTE: This should always have a name + const auto& path = impl.second.m_type.m_data.as_Path().path.m_data.as_Generic().m_path; + DEBUG("Adding type impl " << path); + auto* list_it = &crate.m_type_impls.named[path]; + list_it->push_back(box$(::HIR::TypeImpl { + mv$(impl.second.m_params), + mv$(impl.second.m_type), + make_map1( + impl.second.m_methods.begin()->first, + ::HIR::TypeImpl::VisImplEnt< ::HIR::Function> { ::HIR::Publicity::new_global(), false, mv$(impl.second.m_methods.begin()->second.data) } + ), + {}, + mv$(impl.second.m_src_module) + })); + } break; + case ::HIR::ExprNode_Closure::Class::Unknown: + BUG(Span(), "Encountered Unkown closure type in new impls"); + break; + } + } + new_trait_impls.resize(0); + } + /// Mutate the contents of a closure to update captures, variables, and types class ExprVisitor_Mutate: public ::HIR::ExprVisitorDef @@ -106,7 +151,7 @@ namespace { assert( node_ptr ); auto& node = *node_ptr; const char* node_ty = typeid(node).name(); - TRACE_FUNCTION_FR(&node << " " << node_ty << " : " << node.m_res_type, node_ty); + TRACE_FUNCTION_FR("[_Mutate] " << &node << " " << node_ty << " : " << node.m_res_type, node_ty); node.visit(*this); if( m_replacement ) { @@ -134,7 +179,9 @@ namespace { auto binding_it = ::std::find(m_local_vars.begin(), m_local_vars.end(), node.m_slot); if( binding_it != m_local_vars.end() ) { // NOTE: Offset of 1 is for `self` (`args` is destructured) - node.m_slot = 1 + binding_it - m_local_vars.begin(); + auto new_slot = 1 + binding_it - m_local_vars.begin(); + DEBUG("_Variable: #" << node.m_slot << " -> #" << new_slot); + node.m_slot = new_slot; return ; } } @@ -146,7 +193,7 @@ namespace { { m_replacement = NEWNODE(node.m_res_type.clone(), Field, node.span(), get_self(node.span()), - FMT(binding_it - m_captures.begin()) + RcString::new_interned(FMT(binding_it - m_captures.begin())) ); if( binding_it->second != ::HIR::ValueUsage::Move ) { auto bt = (binding_it->second == ::HIR::ValueUsage::Mutate ? ::HIR::BorrowType::Unique : ::HIR::BorrowType::Shared); @@ -156,6 +203,7 @@ namespace { m_replacement = NEWNODE(node.m_res_type.clone(), Deref, node.span(), mv$(m_replacement)); } m_replacement->m_usage = node.m_usage; + DEBUG("_Variable: #" << node.m_slot << " -> capture"); return ; } } @@ -194,22 +242,38 @@ namespace { public ::HIR::ExprVisitorDef { const ::HIR::Crate& m_crate; + StaticTraitResolve m_resolve; t_cb_generic m_monomorph_cb; + bool m_run_eat; public: - ExprVisitor_Fixup(const ::HIR::Crate& crate, t_cb_generic monomorph_cb): + ExprVisitor_Fixup(const ::HIR::Crate& crate, const ::HIR::GenericParams* params, t_cb_generic monomorph_cb): m_crate(crate), - m_monomorph_cb( mv$(monomorph_cb) ) + m_resolve(crate), + m_monomorph_cb( mv$(monomorph_cb) ), + m_run_eat(false) { + if( params ) { + m_resolve.set_impl_generics_raw(*params); + m_run_eat = true; + } } - static void fix_type(const ::HIR::Crate& crate, t_cb_generic monomorph_cb, ::HIR::TypeRef& ty) { + static void fix_type(const ::HIR::Crate& crate, const Span& sp, t_cb_generic monomorph_cb, ::HIR::TypeRef& ty) { TU_IFLET( ::HIR::TypeRef::Data, ty.m_data, Closure, e, DEBUG("Closure: " << e.node->m_obj_path_base); - auto path = monomorphise_genericpath_with(Span(), e.node->m_obj_path_base, monomorph_cb, false); - const auto& str = crate.get_struct_by_path( Span(), path.m_path ); + auto path = monomorphise_genericpath_with(sp, e.node->m_obj_path_base, monomorph_cb, false); + const auto& str = *e.node->m_obj_ptr; DEBUG(ty << " -> " << path); ty = ::HIR::TypeRef::new_path( mv$(path), ::HIR::TypeRef::TypePathBinding::make_Struct(&str) ); ) + + if( auto* e = ty.m_data.opt_Path() ) + { + if( e->binding.is_Unbound() && e->path.m_data.is_UfcsKnown() ) + { + e->binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({}); + } + } } void visit_root(::HIR::ExprPtr& root) @@ -233,6 +297,42 @@ namespace { visit_type(node->m_res_type); } + void visit(::HIR::ExprNode_Cast& node) override + { + const Span& sp = node.span(); + // Handle casts from closures to function pointers + if( node.m_value->m_res_type.m_data.is_Closure() ) + { + const auto& src_te = node.m_value->m_res_type.m_data.as_Closure(); + ASSERT_BUG(sp, node.m_res_type.m_data.is_Function(), "Cannot convert closure to non-fn type"); + //const auto& dte = node.m_res_type.m_data.as_Function(); + if( src_te.node->m_class != ::HIR::ExprNode_Closure::Class::NoCapture ) + { + ERROR(sp, E0000, "Cannot cast a closure with captures to a fn() type"); + } + + ::HIR::FunctionType fcn_ty_inner { /*is_unsafe=*/false, ABI_RUST, box$(src_te.node->m_return.clone()), {} }; + ::std::vector<::HIR::TypeRef> arg_types; + fcn_ty_inner.m_arg_types.reserve(src_te.node->m_args.size()); + arg_types.reserve(src_te.node->m_args.size()); + for(const auto& arg : src_te.node->m_args) + { + fcn_ty_inner.m_arg_types.push_back( arg.second.clone() ); + arg_types.push_back(arg.second.clone()); + } + auto trait_params = ::HIR::PathParams( ::HIR::TypeRef(mv$(arg_types)) ); + auto res_ty = ::HIR::TypeRef(mv$(fcn_ty_inner)); + + const auto& str = *src_te.node->m_obj_ptr; + auto closure_type = ::HIR::TypeRef::new_path( src_te.node->m_obj_path.clone(), &str ); + auto fn_path = ::HIR::Path(mv$(closure_type), "call_free"); + fn_path.m_data.as_UfcsInherent().impl_params = src_te.node->m_obj_path.m_params.clone(); + + node.m_value = NEWNODE(mv$(res_ty), PathValue, sp, mv$(fn_path), ::HIR::ExprNode_PathValue::FUNCTION); + } + ::HIR::ExprVisitorDef::visit(node); + } + void visit(::HIR::ExprNode_CallValue& node) override { TU_IFLET( ::HIR::TypeRef::Data, node.m_value->m_res_type.m_data, Closure, e, @@ -258,8 +358,15 @@ namespace { void visit_type(::HIR::TypeRef& ty) override { - fix_type(m_crate, m_monomorph_cb, ty); + bool run_eat = m_run_eat; + m_run_eat = false; + fix_type(m_crate, Span(), m_monomorph_cb, ty); ::HIR::ExprVisitorDef::visit_type(ty); + if( run_eat ) { + // TODO: Instead of running EAT, just mark any Unbound UfcsKnown types as Opaque + //m_resolve.expand_associated_types(Span(), ty); + m_run_eat = true; + } } }; @@ -280,6 +387,37 @@ namespace { code.m_bindings[0] = self_ty.clone(); } } + static ::HIR::TraitImpl make_fnfree( + ::HIR::GenericParams params, + ::HIR::TypeRef closure_type, + ::std::vector<::std::pair< ::HIR::Pattern, ::HIR::TypeRef>> args, + ::HIR::TypeRef ret_ty, + ::HIR::ExprPtr code + ) + { + // NOTE: Fixup isn't needed, there's no self + //fix_fn_params(code, closure_type, args_argent.second); + assert(code.m_bindings.size() > 0); + code.m_bindings[0] = ::HIR::TypeRef::new_unit(); + return ::HIR::TraitImpl { + mv$(params), {}, mv$(closure_type), + make_map1( + RcString::new_interned("call_free"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::HIR::Function { + false, ::HIR::Linkage {}, + ::HIR::Function::Receiver::Free, + ABI_RUST, false, false, + {}, + mv$(args), false, + ret_ty.clone(), + mv$(code) + } } + ), + {}, + {}, + {}, + ::HIR::SimplePath() + }; + } static ::HIR::TraitImpl make_fnonce( ::HIR::GenericParams params, ::HIR::PathParams trait_params, @@ -294,7 +432,7 @@ namespace { return ::HIR::TraitImpl { mv$(params), mv$(trait_params), mv$(closure_type), make_map1( - ::std::string("call_once"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::HIR::Function { + RcString::new_interned("call_once"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::HIR::Function { false, ::HIR::Linkage {}, ::HIR::Function::Receiver::Value, ABI_RUST, false, false, @@ -313,7 +451,7 @@ namespace { {}, {}, make_map1( - ::std::string("Output"), ::HIR::TraitImpl::ImplEnt< ::HIR::TypeRef> { false, mv$(ret_ty) } + RcString::new_interned("Output"), ::HIR::TraitImpl::ImplEnt< ::HIR::TypeRef> { false, mv$(ret_ty) } ), ::HIR::SimplePath() }; @@ -332,7 +470,7 @@ namespace { return ::HIR::TraitImpl { mv$(params), mv$(trait_params), mv$(closure_type), make_map1( - ::std::string("call_mut"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::HIR::Function { + RcString::new_interned("call_mut"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::HIR::Function { false, ::HIR::Linkage {}, ::HIR::Function::Receiver::BorrowUnique, ABI_RUST, false, false, @@ -368,7 +506,7 @@ namespace { return ::HIR::TraitImpl { mv$(params), mv$(trait_params), mv$(closure_type), make_map1( - ::std::string("call"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::HIR::Function { + RcString::new_interned("call"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::HIR::Function { false, ::HIR::Linkage {}, ::HIR::Function::Receiver::BorrowShared, ABI_RUST, false, false, @@ -419,17 +557,19 @@ namespace { // Outputs out_impls_t& m_out_impls; + const char* m_new_type_suffix; const new_type_cb_t& m_new_type; /// Stack of active closures ::std::vector<ClosureScope> m_closure_stack; public: - ExprVisitor_Extract(const StaticTraitResolve& resolve, const ::HIR::TypeRef* self_type, ::std::vector< ::HIR::TypeRef>& var_types, out_impls_t& out_impls, const new_type_cb_t& new_type): + ExprVisitor_Extract(const StaticTraitResolve& resolve, const ::HIR::TypeRef* self_type, ::std::vector< ::HIR::TypeRef>& var_types, out_impls_t& out_impls, const char* nt_suffix, const new_type_cb_t& new_type): m_resolve(resolve), m_self_type(self_type), m_variable_types(var_types), m_out_impls( out_impls ), + m_new_type_suffix(nt_suffix), m_new_type( new_type ) { } @@ -445,6 +585,8 @@ namespace { TRACE_FUNCTION_F("Extract closure - " << node.m_res_type); + ASSERT_BUG(sp, node.m_obj_path == ::HIR::GenericPath(), "Closure path already set? " << node.m_obj_path); + // --- Determine borrow set --- m_closure_stack.push_back( ClosureScope(node) ); @@ -507,6 +649,7 @@ namespace { params_placeholders.push_back( ::HIR::TypeRef(params.m_types[i].m_name, i) ); impl_path_params.m_types.push_back( ::HIR::TypeRef(params.m_types[i].m_name, i) ); } + DEBUG("params_placeholders = " << params_placeholders << ", ofs_item = " << ofs_item << ", ofs_impl = " << ofs_impl); auto monomorph_cb = [&](const auto& ty)->const ::HIR::TypeRef& { const auto& ge = ty.m_data.as_Generic(); @@ -593,6 +736,7 @@ namespace { ::std::vector< ::HIR::ExprNodeP> capture_nodes; capture_types.reserve( ent.captured_vars.size() ); capture_nodes.reserve( ent.captured_vars.size() ); + node.m_is_copy = true; for(const auto binding : ent.captured_vars) { const auto binding_idx = binding.first; @@ -627,20 +771,34 @@ namespace { } // - Fix type to replace closure types with known paths - ExprVisitor_Fixup fixup { m_resolve.m_crate, monomorph_cb }; + ExprVisitor_Fixup fixup { m_resolve.m_crate, ¶ms, monomorph_cb }; fixup.visit_type(ty_mono); - capture_types.push_back( ::HIR::VisEnt< ::HIR::TypeRef> { false, mv$(ty_mono) } ); + if( !m_resolve.type_is_copy(sp, ty_mono) ) + { + node.m_is_copy = false; + } + capture_types.push_back( ::HIR::VisEnt< ::HIR::TypeRef> { ::HIR::Publicity::new_none(), mv$(ty_mono) } ); } - auto closure_struct_path = m_new_type( - ::HIR::Struct { - params.clone(), - ::HIR::Struct::Repr::Rust, - ::HIR::Struct::Data::make_Tuple(mv$(capture_types)) - } - ); - const auto& closure_struct_ref = m_resolve.m_crate.get_struct_by_path(sp, closure_struct_path); + + // --- --- + if( node.m_is_copy ) + { + DEBUG("Copy closure"); + } + + auto str = ::HIR::Struct { + params.clone(), + ::HIR::Struct::Repr::Rust, + ::HIR::Struct::Data::make_Tuple(mv$(capture_types)) + }; + str.m_markings.is_copy = node.m_is_copy; + ::HIR::SimplePath closure_struct_path; + const ::HIR::Struct* closure_struct_ptr; + ::std::tie(closure_struct_path, closure_struct_ptr) = m_new_type(m_new_type_suffix, mv$(str)); + const auto& closure_struct_ref = *closure_struct_ptr; // Mark the object pathname in the closure. + node.m_obj_ptr = &closure_struct_ref; node.m_obj_path = ::HIR::GenericPath( closure_struct_path, mv$(constructor_path_params) ); node.m_obj_path_base = node.m_obj_path.clone(); node.m_captures = mv$(capture_nodes); @@ -669,7 +827,7 @@ namespace { { DEBUG("-- Fixing types in body code"); - ExprVisitor_Fixup fixup { m_resolve.m_crate, monomorph_cb }; + ExprVisitor_Fixup fixup { m_resolve.m_crate, ¶ms, monomorph_cb }; fixup.visit_root( body_code ); DEBUG("-- Fixing types in signature"); @@ -678,6 +836,19 @@ namespace { // TODO: Replace erased types too } + if( node.m_is_copy ) + { + auto& v = const_cast<::HIR::Crate&>(m_resolve.m_crate).m_trait_impls[m_resolve.m_crate.get_lang_item_path(sp, "copy")].get_list_for_type_mut(closure_type); + v.push_back(box$(::HIR::TraitImpl { + params.clone(), {}, closure_type.clone(), + {}, + {}, + {}, + {}, + /*source module*/::HIR::SimplePath(m_resolve.m_crate.m_crate_name, {}) + })); + } + // --- // 3. Create trait impls // --- @@ -687,7 +858,83 @@ namespace { { case ::HIR::ExprNode_Closure::Class::Unknown: node.m_class = ::HIR::ExprNode_Closure::Class::NoCapture; - case ::HIR::ExprNode_Closure::Class::NoCapture: + case ::HIR::ExprNode_Closure::Class::NoCapture: { + + struct H2 { + static ::std::pair<::HIR::ExprNode_Closure::Class, HIR::TraitImpl> make_dispatch( + const Span& sp, + ::HIR::ExprNode_Closure::Class c, + ::HIR::GenericParams params, + ::HIR::PathParams trait_params, + const ::HIR::TypeRef& closure_type, + const ::HIR::TypeRef& args_ty, + const ::HIR::TypeRef& ret_type + ) + { + const auto& args_tup_inner = args_ty.m_data.as_Tuple(); + // 1. Create a list of `arg.0, arg.1, arg.2, ...` for the dispatch methods + ::std::vector<HIR::ExprNodeP> dispatch_args; + ::std::vector<HIR::TypeRef> dispatch_node_args_cache; + dispatch_args.reserve( args_tup_inner.size() ); + dispatch_node_args_cache.reserve( args_tup_inner.size()+1 ); + for(size_t i = 0; i < args_tup_inner.size(); i ++) + { + const auto& ty = args_tup_inner[i]; + dispatch_args.push_back( NEWNODE(ty.clone(), Field, sp, NEWNODE(args_ty.clone(), Variable, sp, RcString::new_interned("arg"), 1), RcString::new_interned(FMT(i))) ); + dispatch_node_args_cache.push_back( ty.clone() ); + } + dispatch_node_args_cache.push_back( ret_type.clone() ); + auto path = ::HIR::Path(closure_type.clone(), RcString::new_interned("call_free")); + path.m_data.as_UfcsInherent().impl_params = closure_type.m_data.as_Path().path.m_data.as_Generic().m_params.clone(); + HIR::ExprNodeP dispatch_node = NEWNODE(ret_type.clone(), CallPath, sp, + mv$(path), + mv$(dispatch_args) + ); + dynamic_cast<::HIR::ExprNode_CallPath&>(*dispatch_node).m_cache.m_arg_types = mv$(dispatch_node_args_cache); + + auto args_arg = ::std::make_pair( + ::HIR::Pattern { {false, ::HIR::PatternBinding::Type::Move, RcString::new_interned("args"), 1}, {} }, + args_ty.clone() + ); + HIR::TraitImpl fcn; + switch(c) + { + case ::HIR::ExprNode_Closure::Class::Once: + fcn = H::make_fnonce( mv$(params), mv$(trait_params), closure_type.clone(), mv$(args_arg), ret_type.clone(), mv$(dispatch_node) ); + break; + case ::HIR::ExprNode_Closure::Class::Mut: + fcn = H::make_fnmut( mv$(params), mv$(trait_params), closure_type.clone(), mv$(args_arg), ret_type.clone(), mv$(dispatch_node) ); + break; + case ::HIR::ExprNode_Closure::Class::Shared: + fcn = H::make_fn( mv$(params), mv$(trait_params), closure_type.clone(), mv$(args_arg), ret_type.clone(), mv$(dispatch_node) ); + break; + default: + throw ""; + } + return ::std::make_pair(c, mv$(fcn)); + } + }; + m_out_impls.push_back( H2::make_dispatch(sp, ::HIR::ExprNode_Closure::Class::Once , params.clone(), trait_params.clone(), closure_type, args_ty, ret_type) ); + m_out_impls.push_back( H2::make_dispatch(sp, ::HIR::ExprNode_Closure::Class::Mut , params.clone(), trait_params.clone(), closure_type, args_ty, ret_type) ); + m_out_impls.push_back( H2::make_dispatch(sp, ::HIR::ExprNode_Closure::Class::Shared, params.clone(), mv$(trait_params) , closure_type, args_ty, ret_type) ); + + // 2. Split args_pat/args_ty into separate arguments + ::std::vector<::std::pair< ::HIR::Pattern, ::HIR::TypeRef>> args_split; + args_split.reserve( node.m_args.size() ); + for(size_t i = 0; i < node.m_args.size(); i ++) + { + args_split.push_back(::std::make_pair( + mv$( args_pat.m_data.as_Tuple().sub_patterns[i] ), + mv$( args_ty.m_data.as_Tuple()[i] ) + )); + } + // - Create fn_free free method + m_out_impls.push_back(::std::make_pair( + ::HIR::ExprNode_Closure::Class::NoCapture, + H::make_fnfree( mv$(params), mv$(closure_type), mv$(args_split), mv$(ret_type), mv$(body_code) ) + )); + + } break; case ::HIR::ExprNode_Closure::Class::Shared: { const auto& lang_Fn = m_resolve.m_crate.get_lang_item_path(node.span(), "fn"); const auto method_self_ty = ::HIR::TypeRef::new_borrow( ::HIR::BorrowType::Shared, closure_type.clone() ); @@ -695,9 +942,9 @@ namespace { // - FnOnce { auto dispatch_node = NEWNODE(ret_type.clone(), CallPath, sp, - ::HIR::Path(closure_type.clone(), ::HIR::GenericPath(lang_Fn, trait_params.clone()), "call"), + ::HIR::Path(closure_type.clone(), ::HIR::GenericPath(lang_Fn, trait_params.clone()), RcString::new_interned("call")), make_vec2( - NEWNODE(method_self_ty.clone(), Borrow, sp, ::HIR::BorrowType::Shared, NEWNODE(closure_type.clone(), Variable, sp, "self", 0)), + NEWNODE(method_self_ty.clone(), Borrow, sp, ::HIR::BorrowType::Shared, NEWNODE(closure_type.clone(), Variable, sp, RcString::new_interned("self"), 0)), NEWNODE(args_ty.clone(), Variable, sp, "arg", 1) ) ); @@ -787,6 +1034,7 @@ namespace { } void visit(::HIR::ExprNode_Variable& node) override { + DEBUG("_Variable: #" << node.m_slot << " '" << node.m_name << "' " << node.m_usage); if( !m_closure_stack.empty() ) { mark_used_variable(node.span(), node.m_slot, node.m_usage); @@ -1012,26 +1260,19 @@ namespace { unsigned int closure_count = 0; ::HIR::SimplePath root_mod_path(crate.m_crate_name,{}); m_cur_mod_path = &root_mod_path; - m_new_type = [&](auto s)->auto { - auto name = FMT("closure_I_" << closure_count); + m_new_type = [&](const char* suffix, auto s)->auto { + auto name = RcString::new_interned(FMT("closure#I_" << closure_count)); closure_count += 1; - auto boxed = box$(( ::HIR::VisEnt< ::HIR::TypeItem> { false, ::HIR::TypeItem( mv$(s) ) } )); + auto boxed = box$(( ::HIR::VisEnt< ::HIR::TypeItem> { ::HIR::Publicity::new_none(), ::HIR::TypeItem( mv$(s) ) } )); + auto* ret_ptr = &boxed->ent.as_Struct(); crate.m_root_module.m_mod_items.insert( ::std::make_pair(name, mv$(boxed)) ); - return ::HIR::SimplePath(crate.m_crate_name, {}) + name; + return ::std::make_pair( ::HIR::SimplePath(crate.m_crate_name, {}) + name, ret_ptr ); }; ::HIR::Visitor::visit_crate(crate); - for(auto& impl : m_new_trait_impls) - { - const auto& trait = - impl.first == ::HIR::ExprNode_Closure::Class::Once ? crate.get_lang_item_path(sp, "fn_once") - : impl.first == ::HIR::ExprNode_Closure::Class::Mut ? crate.get_lang_item_path(sp, "fn_mut") - : /*impl.first == ::HIR::ExprNode_Closure::Class::Shared ?*/ crate.get_lang_item_path(sp, "fn") - ; - crate.m_trait_impls.insert( ::std::make_pair(trait.clone(), mv$(impl.second)) ); - } - m_new_trait_impls.resize(0); + push_new_impls(sp, crate, mv$(m_new_trait_impls)); + m_new_trait_impls.clear(); } void visit_module(::HIR::ItemPath p, ::HIR::Module& mod) override @@ -1040,20 +1281,29 @@ namespace { auto path = p.get_simple_path(); m_cur_mod_path = &path; + ::std::vector< ::std::pair<RcString, std::unique_ptr< ::HIR::VisEnt< ::HIR::TypeItem> > >> new_types; + unsigned int closure_count = 0; auto saved_nt = mv$(m_new_type); - m_new_type = [&](auto s)->auto { - auto name = FMT("closure_" << closure_count); + m_new_type = [&](const char* suffix, auto s)->auto { + // TODO: Use a function on `mod` that adds a closure and makes the indexes be per suffix + auto name = RcString( FMT("closure#" << suffix << (suffix[0] ? "_" : "") << closure_count) ); closure_count += 1; - auto boxed = box$( (::HIR::VisEnt< ::HIR::TypeItem> { false, ::HIR::TypeItem( mv$(s) ) }) ); - mod.m_mod_items.insert( ::std::make_pair(name, mv$(boxed)) ); - return (p + name).get_simple_path(); + auto boxed = box$( (::HIR::VisEnt< ::HIR::TypeItem> { ::HIR::Publicity::new_none(), ::HIR::TypeItem( mv$(s) ) }) ); + auto* ret_ptr = &boxed->ent.as_Struct(); + new_types.push_back( ::std::make_pair(name, mv$(boxed)) ); + return ::std::make_pair( (p + name).get_simple_path(), ret_ptr ); }; ::HIR::Visitor::visit_module(p, mod); m_cur_mod_path = saved; m_new_type = mv$(saved_nt); + + for(auto& e : new_types) + { + mod.m_mod_items.insert( mv$(e) ); + } } // NOTE: This is left here to ensure that any expressions that aren't handled by higher code cause a failure @@ -1088,12 +1338,12 @@ namespace { DEBUG("Function code " << p); { - ExprVisitor_Extract ev(m_resolve, m_self_type, item.m_code.m_bindings, m_new_trait_impls, m_new_type); + ExprVisitor_Extract ev(m_resolve, m_self_type, item.m_code.m_bindings, m_new_trait_impls, p.name, m_new_type); ev.visit_root( *item.m_code ); } { - ExprVisitor_Fixup fixup(m_resolve.m_crate, [](const auto& x)->const auto&{ return x; }); + ExprVisitor_Fixup fixup(m_resolve.m_crate, nullptr, [](const auto& x)->const auto&{ return x; }); fixup.visit_root( item.m_code ); } } @@ -1152,6 +1402,8 @@ namespace { m_self_type = &impl.m_type; auto _ = this->m_resolve.set_impl_generics(impl.m_params); + // TODO: Re-create m_new_type to store in the source module + ::HIR::Visitor::visit_type_impl(impl); m_self_type = nullptr; @@ -1169,9 +1421,50 @@ namespace { }; } -void HIR_Expand_Closures_Expr(const ::HIR::Crate& crate, ::HIR::ExprPtr& exp) +void HIR_Expand_Closures_Expr(const ::HIR::Crate& crate_ro, ::HIR::ExprPtr& exp) { - // TODO: + Span sp; + auto& crate = const_cast<::HIR::Crate&>(crate_ro); + TRACE_FUNCTION; + + StaticTraitResolve resolve { crate }; + assert(exp); + if(exp.m_state->m_impl_generics) resolve.set_impl_generics(*exp.m_state->m_impl_generics); + if(exp.m_state->m_item_generics) resolve.set_item_generics(*exp.m_state->m_item_generics); + + const ::HIR::TypeRef* self_type = nullptr; // TODO: Need to be able to get this? + + static int closure_count = 0; + out_impls_t new_trait_impls; + new_type_cb_t new_type_cb = [&](const char* suffix, auto s)->auto { + auto name = RcString::new_interned(FMT("closure#C_" << closure_count)); + closure_count += 1; + auto boxed = box$(( ::HIR::VisEnt< ::HIR::TypeItem> { ::HIR::Publicity::new_none(), ::HIR::TypeItem( mv$(s) ) } )); + auto* ret_ptr = &boxed->ent.as_Struct(); + crate.m_root_module.m_mod_items.insert( ::std::make_pair(name, mv$(boxed)) ); + return ::std::make_pair( ::HIR::SimplePath(crate.m_crate_name, {}) + name, ret_ptr ); + }; + + { + ExprVisitor_Extract ev(resolve, self_type, exp.m_bindings, new_trait_impls, "", new_type_cb); + ev.visit_root( *exp ); + } + + { + ExprVisitor_Fixup fixup(crate, nullptr, [](const auto& x)->const auto&{ return x; }); + fixup.visit_root( exp ); + } + + for(auto& impl : new_trait_impls) + { + for( auto& m : impl.second.m_methods ) + { + m.second.data.m_code.m_state = ::HIR::ExprStatePtr(*exp.m_state); + m.second.data.m_code.m_state->stage = ::HIR::ExprState::Stage::Typecheck; + } + impl.second.m_src_module = exp.m_state->m_mod_path; + } + push_new_impls(sp, crate, mv$(new_trait_impls)); } void HIR_Expand_Closures(::HIR::Crate& crate) |