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 | |
parent | 996f0418da0efca90b7c3eb3a2839e9d766f6903 (diff) | |
download | mrust-72366722bcda90960f18d108cf2d523d4e7f0cd8.tar.gz |
HIR Annotate - Only borrow struct cosntructor base values when no fields are moved
-rw-r--r-- | src/hir/expr.hpp | 1 | ||||
-rw-r--r-- | src/hir/hir.cpp | 9 | ||||
-rw-r--r-- | src/hir/hir.hpp | 2 | ||||
-rw-r--r-- | src/hir_expand/annotate_value_usage.cpp | 36 | ||||
-rw-r--r-- | src/hir_typeck/expr_check.cpp | 2 |
5 files changed, 47 insertions, 3 deletions
diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp index e22c1ab8..cd4a21ab 100644 --- a/src/hir/expr.hpp +++ b/src/hir/expr.hpp @@ -674,6 +674,7 @@ struct ExprNode_StructLiteral: ::HIR::ExprNodeP m_base_value; t_values m_values; + /// Monomorphised types of each field. ::std::vector< ::HIR::TypeRef> m_value_types; ExprNode_StructLiteral(Span sp, ::HIR::GenericPath path, bool is_struct, ::HIR::ExprNodeP base_value, t_values values): diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp index 3a8ab95b..5177f101 100644 --- a/src/hir/hir.cpp +++ b/src/hir/hir.cpp @@ -8,6 +8,7 @@ * HIR type helper code */ #include "hir.hpp" +#include <algorithm> namespace HIR { ::std::ostream& operator<<(::std::ostream& os, const ::HIR::Literal& v) @@ -45,6 +46,14 @@ namespace HIR { } } +const ::HIR::Enum::Variant* ::HIR::Enum::get_variant(const ::std::string& name) const +{ + auto it = ::std::find_if(m_variants.begin(), m_variants.end(), [&](const auto& x){ return x.first == name; }); + if( it == m_variants.end() ) + return nullptr; + return &it->second; +} + namespace { bool matches_genericpath(const ::HIR::GenericParams& params, const ::HIR::GenericPath& left, const ::HIR::GenericPath& right, ::HIR::t_cb_resolve_type ty_res, bool expand_generic); diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index be043e22..2e0e6592 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -181,6 +181,8 @@ public: ::std::vector< ::std::pair< ::std::string, Variant > > m_variants; TraitMarkings m_markings; + + const Variant* get_variant(const ::std::string& ) const; }; class Struct { 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); } diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp index 229bf388..6e7ae3f9 100644 --- a/src/hir_typeck/expr_check.cpp +++ b/src/hir_typeck/expr_check.cpp @@ -443,7 +443,7 @@ namespace { fields_ptr = &e->m_data.as_Named(); ) ) - assert(fields_ptr); + ASSERT_BUG(node.span(), fields_ptr, "Didn't get field for path in _StructLiteral - " << ty); const ::HIR::t_struct_fields& fields = *fields_ptr; #if 1 |