summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2019-05-04 17:36:07 +0800
committerJohn Hodge <tpg@ucc.asn.au>2019-05-04 17:36:07 +0800
commit8a74857d5a6323a46757f12078b46718464a006d (patch)
tree59995482609e4ebf33a4de6a1316377b2181d92f /src
parent771c9385a5d7213cb12c1d7b969553b3402c498b (diff)
downloadmrust-8a74857d5a6323a46757f12078b46718464a006d.tar.gz
Match Ergonomics - Auto-deref in `ref` patterns to get `&T`
Diffstat (limited to 'src')
-rw-r--r--src/hir/pattern.hpp8
-rw-r--r--src/hir_typeck/expr_cs.cpp25
-rw-r--r--src/mir/check.cpp6
-rw-r--r--src/mir/from_hir.cpp5
4 files changed, 26 insertions, 18 deletions
diff --git a/src/hir/pattern.hpp b/src/hir/pattern.hpp
index cd6c7422..d16fd942 100644
--- a/src/hir/pattern.hpp
+++ b/src/hir/pattern.hpp
@@ -32,19 +32,23 @@ struct PatternBinding
::std::string m_name;
unsigned int m_slot;
+ unsigned m_implicit_deref_count = 0;
+
bool is_valid() const { return m_name != ""; }
PatternBinding():
m_mutable(false),
m_type(Type::Move),
m_name(""),
- m_slot(0)
+ m_slot(0),
+ m_implicit_deref_count(0)
{}
PatternBinding(bool mut, Type type, ::std::string name, unsigned int slot):
m_mutable(mut),
m_type(type),
m_name( mv$(name) ),
- m_slot( slot )
+ m_slot( slot ),
+ m_implicit_deref_count(0)
{}
};
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index a8e80a56..0b6b0089 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -4134,33 +4134,30 @@ void Context::handle_pattern(const Span& sp, ::HIR::Pattern& pat, const ::HIR::T
break;
case ::HIR::PatternBinding::Type::MutRef:
// NOTE: Needs to deref and borrow to get just `&mut T` (where T isn't a &mut T)
- //while( TU_TEST1(type_p->m_data, Borrow, .type >= ::HIR::BorrowType::Unique) )
- //{
- // n_deref ++;
- // type_p = &context.m_ivars.get_type(*type_p->m_data.as_Borrow().inner);
- //}
+ while( TU_TEST1(type_p->m_data, Borrow, .type >= ::HIR::BorrowType::Unique) )
+ {
+ n_deref ++;
+ type_p = &context.m_ivars.get_type(*type_p->m_data.as_Borrow().inner);
+ }
DEBUG(n_deref << " from " << type << " to " << *type_p);
binding_type = &(tmp = ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Unique, type_p->clone()));
break;
case ::HIR::PatternBinding::Type::Ref:
// NOTE: Needs to deref and borrow to get just `&mut T` (where T isn't a &mut T)
- //while( type_p->m_data.is_Borrow() )
- //{
- // n_deref ++;
- // type_p = &context.m_ivars.get_type(*type_p->m_data.as_Borrow().inner);
- //}
+ while( type_p->m_data.is_Borrow() )
+ {
+ n_deref ++;
+ type_p = &context.m_ivars.get_type(*type_p->m_data.as_Borrow().inner);
+ }
DEBUG(n_deref << " from " << type << " to " << *type_p);
binding_type = &(tmp = ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, type_p->clone()));
break;
default:
TODO(sp, "Assign variable type using mode " << (int)binding_mode << " and " << type);
}
- if( n_deref > 0 ) {
- TODO(sp, "Handle autoderef of ref bindings in match ergonomics");
- }
assert(binding_type);
context.equate_types(sp, context.get_var(sp, pattern.m_binding.m_slot), *binding_type);
- //pattern.m_binding.n_deref = n_deref;
+ pattern.m_binding.m_implicit_deref_count = n_deref;
}
// For `_` patterns, there's nothing to match, so they just succeed with no derefs
diff --git a/src/mir/check.cpp b/src/mir/check.cpp
index b2d86590..b5abdb0a 100644
--- a/src/mir/check.cpp
+++ b/src/mir/check.cpp
@@ -686,10 +686,12 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
// TODO: Check that the input type is Copy
),
(Borrow,
- // TODO: Check return type
+ ::HIR::TypeRef tmp;
+ check_types( dst_ty, ::HIR::TypeRef::new_borrow(e.type, state.get_lvalue_type(tmp, e.val).clone()) );
),
(Cast,
- // TODO: Check return type
+ // Check return type
+ check_types( dst_ty, e.type );
// TODO: Check suitability of source type (COMPLEX)
),
(BinOp,
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index 912b8c78..8d51bf55 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -174,6 +174,11 @@ namespace {
destructure_from_ex(sp, pat, lval.clone(), 3);
}
+ for(size_t i = 0; i < pat.m_binding.m_implicit_deref_count; i ++)
+ {
+ lval = ::MIR::LValue::make_Deref({ box$(lval) });
+ }
+
switch( pat.m_binding.m_type )
{
case ::HIR::PatternBinding::Type::Move: