summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-12-24 11:44:08 +1100
committerJohn Hodge <tpg@mutabah.net>2016-12-24 11:44:08 +1100
commit07e150e9d7d638977ba3a1561d2687950a2a4668 (patch)
tree153faf4ceff6b1397fb0c76e40ef51dd311578c2
parent4d8c5a1a0ea1fea86e0e8b4be30ce0c77411f9c2 (diff)
downloadmrust-07e150e9d7d638977ba3a1561d2687950a2a4668.tar.gz
HIR Expand Closures - Handle closures called from other closures
-rw-r--r--src/hir/expr.cpp5
-rw-r--r--src/hir_expand/closures.cpp34
-rw-r--r--src/mir/from_hir_match.cpp2
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);