diff options
author | John Hodge <tpg@mutabah.net> | 2016-12-24 11:44:08 +1100 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-12-24 11:44:08 +1100 |
commit | 07e150e9d7d638977ba3a1561d2687950a2a4668 (patch) | |
tree | 153faf4ceff6b1397fb0c76e40ef51dd311578c2 | |
parent | 4d8c5a1a0ea1fea86e0e8b4be30ce0c77411f9c2 (diff) | |
download | mrust-07e150e9d7d638977ba3a1561d2687950a2a4668.tar.gz |
HIR Expand Closures - Handle closures called from other closures
-rw-r--r-- | src/hir/expr.cpp | 5 | ||||
-rw-r--r-- | src/hir_expand/closures.cpp | 34 | ||||
-rw-r--r-- | src/mir/from_hir_match.cpp | 2 |
3 files changed, 33 insertions, 8 deletions
diff --git a/src/hir/expr.cpp b/src/hir/expr.cpp index 51f0661f..7921cf98 100644 --- a/src/hir/expr.cpp +++ b/src/hir/expr.cpp @@ -173,6 +173,11 @@ DEF_VISIT(ExprNode_Closure, node, { visit_node_ptr(node.m_code); } + else + { + for(auto& cap : node.m_captures) + visit_node_ptr(cap); + } ) #undef DEF_VISIT diff --git a/src/hir_expand/closures.cpp b/src/hir_expand/closures.cpp index 0923e494..71e6a8c2 100644 --- a/src/hir_expand/closures.cpp +++ b/src/hir_expand/closures.cpp @@ -795,31 +795,49 @@ namespace { void visit(::HIR::ExprNode_CallValue& node) override { + const auto& fcn_ty = node.m_value->m_res_type; + DEBUG("_CallValue - " << fcn_ty); if( !m_closure_stack.empty() ) { TRACE_FUNCTION_F("_CallValue"); if( node.m_trait_used == ::HIR::ExprNode_CallValue::TraitUsed::Unknown ) { - if( node.m_res_type.m_data.is_Closure() ) + if( fcn_ty.m_data.is_Closure() ) { - TODO(node.span(), "Determine how value in CallValue is used on a closure"); + const auto& cn = *fcn_ty.m_data.as_Closure().node; + // Use the closure's class to determine if & or &mut should be taken (and which function to use) + ::HIR::ValueUsage vu = ::HIR::ValueUsage::Unknown; + switch(cn.m_class) + { + case ::HIR::ExprNode_Closure::Class::Unknown: + case ::HIR::ExprNode_Closure::Class::NoCapture: + case ::HIR::ExprNode_Closure::Class::Shared: + vu = ::HIR::ValueUsage::Borrow; + break; + case ::HIR::ExprNode_Closure::Class::Mut: + vu = ::HIR::ValueUsage::Mutate; + break; + case ::HIR::ExprNode_Closure::Class::Once: + vu = ::HIR::ValueUsage::Move; + break; + } + node.m_value->m_usage = vu; } else { + // Must be a function pointer, leave it } } else { // If the trait is known, then the &/&mut has been added } - - node.m_value->visit(*this); - for(auto& arg : node.m_args) - arg->visit(*this); + ::HIR::ExprVisitorDef::visit(node); } - else if( node.m_res_type.m_data.is_Closure() ) + else if( fcn_ty.m_data.is_Closure() ) { - TODO(node.span(), "Determine how value in CallValue is used on a closure"); + //TODO(node.span(), "Determine how value in CallValue is used on a closure"); + ::HIR::ExprVisitorDef::visit(node); } else { diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp index 31704dc4..f191f3fa 100644 --- a/src/mir/from_hir_match.cpp +++ b/src/mir/from_hir_match.cpp @@ -275,6 +275,8 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod // NOTE: Paused block resumed upon successful match } + // TODO: If this pattern ignores fields with Drop impls, this will lead to leaks. + // - Ideally, this would trigger a drop of whatever wasn't already taken by the pattern. if( has_move_pattern ) { builder.moved_lvalue(node.span(), match_val); |