or-patterns: fix problems in typeck.

This commit is contained in:
Mazdak Farrokhzad 2019-09-15 02:49:37 +02:00
parent 89bbef3026
commit 4c346939b0

View File

@ -97,11 +97,10 @@ fn check_pat(
self.check_pat_struct(pat, qpath, fields, *etc, expected, def_bm, discrim_span) self.check_pat_struct(pat, qpath, fields, *etc, expected, def_bm, discrim_span)
} }
PatKind::Or(pats) => { PatKind::Or(pats) => {
let expected_ty = self.structurally_resolved_type(pat.span, expected);
for pat in pats { for pat in pats {
self.check_pat(pat, expected, def_bm, discrim_span); self.check_pat(pat, expected, def_bm, discrim_span);
} }
expected_ty expected
} }
PatKind::Tuple(elements, ddpos) => { PatKind::Tuple(elements, ddpos) => {
self.check_pat_tuple(pat.span, elements, *ddpos, expected, def_bm, discrim_span) self.check_pat_tuple(pat.span, elements, *ddpos, expected, def_bm, discrim_span)
@ -208,7 +207,6 @@ fn is_non_ref_pat(&self, pat: &'tcx Pat, opt_path_res: Option<Res>) -> bool {
match pat.node { match pat.node {
PatKind::Struct(..) | PatKind::Struct(..) |
PatKind::TupleStruct(..) | PatKind::TupleStruct(..) |
PatKind::Or(_) |
PatKind::Tuple(..) | PatKind::Tuple(..) |
PatKind::Box(_) | PatKind::Box(_) |
PatKind::Range(..) | PatKind::Range(..) |
@ -226,6 +224,18 @@ fn is_non_ref_pat(&self, pat: &'tcx Pat, opt_path_res: Option<Res>) -> bool {
_ => true, _ => true,
} }
} }
// FIXME(or_patterns; Centril | dlrobertson): To keep things compiling
// for or-patterns at the top level, we need to make `p_0 | ... | p_n`
// a "non reference pattern". For example the following currently compiles:
// ```
// match &1 {
// e @ &(1...2) | e @ &(3...4) => {}
// _ => {}
// }
// ```
//
// We should consider whether we should do something special in nested or-patterns.
PatKind::Or(_) |
PatKind::Wild | PatKind::Wild |
PatKind::Binding(..) | PatKind::Binding(..) |
PatKind::Ref(..) => false, PatKind::Ref(..) => false,
@ -426,12 +436,11 @@ fn check_pat_ident(
// If the binding is like `ref x | ref const x | ref mut x` // If the binding is like `ref x | ref const x | ref mut x`
// then `x` is assigned a value of type `&M T` where M is the // then `x` is assigned a value of type `&M T` where M is the
// mutability and T is the expected type. // mutability and T is the expected type.
let region_ty = self.new_ref_ty(pat.span, mutbl, expected); //
// `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)`
// is required. However, we use equality, which is stronger. // is required. However, we use equality, which is stronger.
// See (note_1) for an explanation. // See (note_1) for an explanation.
region_ty self.new_ref_ty(pat.span, mutbl, expected)
} }
// Otherwise, the type of x is the expected type `T`. // Otherwise, the type of x is the expected type `T`.
ty::BindByValue(_) => { ty::BindByValue(_) => {