diff options
author | John Hodge <tpg@mutabah.net> | 2016-11-04 10:30:20 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-11-04 10:30:20 +0800 |
commit | 72366722bcda90960f18d108cf2d523d4e7f0cd8 (patch) | |
tree | 0684d529816ec1e087658d7f3d09b197878b7115 /src/hir_expand | |
parent | 996f0418da0efca90b7c3eb3a2839e9d766f6903 (diff) | |
download | mrust-72366722bcda90960f18d108cf2d523d4e7f0cd8.tar.gz |
HIR Annotate - Only borrow struct cosntructor base values when no fields are moved
Diffstat (limited to 'src/hir_expand')
-rw-r--r-- | src/hir_expand/annotate_value_usage.cpp | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/src/hir_expand/annotate_value_usage.cpp b/src/hir_expand/annotate_value_usage.cpp index 04be9644..055070a0 100644 --- a/src/hir_expand/annotate_value_usage.cpp +++ b/src/hir_expand/annotate_value_usage.cpp @@ -313,8 +313,40 @@ namespace { void visit(::HIR::ExprNode_StructLiteral& node) override { if( node.m_base_value ) { - // TODO: If only Copy fields will be used, set usage to Borrow - auto _ = push_usage( ::HIR::ValueUsage::Move ); + bool is_moved = false; + const auto& tpb = node.m_base_value->m_res_type.m_data.as_Path().binding; + const ::HIR::t_struct_fields* fields_ptr; + if( tpb.is_Enum() ) { + const auto* var = tpb.as_Enum()->get_variant( node.m_path.m_path.m_components.back() ); + ASSERT_BUG(node.span(), var, ""); + fields_ptr = &var->as_Struct(); + } + else { + fields_ptr = &tpb.as_Struct()->m_data.as_Named(); + } + const auto& fields = *fields_ptr; + ::std::vector<bool> provided_mask( fields.size() ); + for( const auto& fld : node.m_values ) { + unsigned idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto& x){ return x.first == fld.first; }) - fields.begin(); + provided_mask[idx] = true; + } + + const auto monomorph_cb = monomorphise_type_get_cb(node.span(), nullptr, &node.m_path.m_params, nullptr); + for( unsigned int i = 0; i < fields.size(); i ++ ) { + if( ! provided_mask[i] ) { + const auto& ty_o = fields[i].second.ent; + ::HIR::TypeRef tmp; + const auto& ty_m = (monomorphise_type_needed(ty_o) ? tmp = monomorphise_type_with(node.span(), ty_o, monomorph_cb) : ty_o); + bool is_copy = m_resolve.type_is_copy(node.span(), ty_m); + if( !is_copy ) { + DEBUG("- Field " << i << " " << fields[i].first << ": " << ty_m << " moved"); + is_moved = true; + } + } + } + + // If only Copy fields will be used, set usage to Borrow + auto _ = push_usage( is_moved ? ::HIR::ValueUsage::Move : ::HIR::ValueUsage::Borrow ); this->visit_node_ptr(node.m_base_value); } |