summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-11-04 10:30:20 +0800
committerJohn Hodge <tpg@mutabah.net>2016-11-04 10:30:20 +0800
commit72366722bcda90960f18d108cf2d523d4e7f0cd8 (patch)
tree0684d529816ec1e087658d7f3d09b197878b7115
parent996f0418da0efca90b7c3eb3a2839e9d766f6903 (diff)
downloadmrust-72366722bcda90960f18d108cf2d523d4e7f0cd8.tar.gz
HIR Annotate - Only borrow struct cosntructor base values when no fields are moved
-rw-r--r--src/hir/expr.hpp1
-rw-r--r--src/hir/hir.cpp9
-rw-r--r--src/hir/hir.hpp2
-rw-r--r--src/hir_expand/annotate_value_usage.cpp36
-rw-r--r--src/hir_typeck/expr_check.cpp2
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