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 | 
