]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/check/_match.rs
review comments: change wording
[rust.git] / src / librustc_typeck / check / _match.rs
1 use crate::check::{FnCtxt, Expectation, Diverges, Needs};
2 use crate::check::coercion::CoerceMany;
3 use crate::util::nodemap::FxHashMap;
4 use errors::{Applicability, DiagnosticBuilder};
5 use rustc::hir::{self, PatKind, Pat};
6 use rustc::hir::def::{Def, CtorKind};
7 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
8 use rustc::infer;
9 use rustc::infer::type_variable::TypeVariableOrigin;
10 use rustc::traits::ObligationCauseCode;
11 use rustc::ty::{self, Ty, TypeFoldable};
12 use rustc::ty::subst::Kind;
13 use syntax::ast;
14 use syntax::source_map::Spanned;
15 use syntax::ptr::P;
16 use syntax::util::lev_distance::find_best_match_for_name;
17 use syntax_pos::Span;
18
19 use std::collections::hash_map::Entry::{Occupied, Vacant};
20 use std::cmp;
21
22 use super::report_unexpected_variant_def;
23
24 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
25     /// `match_discrim_span` argument having a `Span` indicates that this pattern is part of
26     /// a match expression arm guard, and it points to the match discriminant to add context
27     /// in type errors. In the folloowing example, `match_discrim_span` corresponds to the
28     /// `a + b` expression:
29     ///
30     /// ```text
31     /// error[E0308]: mismatched types
32     ///  --> src/main.rs:5:9
33     ///   |
34     /// 4 |    let temp: usize = match a + b {
35     ///   |                            ----- this expression has type `usize`
36     /// 5 |         Ok(num) => num,
37     ///   |         ^^^^^^^ expected usize, found enum `std::result::Result`
38     ///   |
39     ///   = note: expected type `usize`
40     ///              found type `std::result::Result<_, _>`
41     /// ```
42     pub fn check_pat_walk(
43         &self,
44         pat: &'gcx hir::Pat,
45         mut expected: Ty<'tcx>,
46         mut def_bm: ty::BindingMode,
47         match_discrim_span: Option<Span>,
48     ) {
49         let tcx = self.tcx;
50
51         debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?})", pat, expected, def_bm);
52
53         let is_non_ref_pat = match pat.node {
54             PatKind::Struct(..) |
55             PatKind::TupleStruct(..) |
56             PatKind::Tuple(..) |
57             PatKind::Box(_) |
58             PatKind::Range(..) |
59             PatKind::Slice(..) => true,
60             PatKind::Lit(ref lt) => {
61                 let ty = self.check_expr(lt);
62                 match ty.sty {
63                     ty::Ref(..) => false,
64                     _ => true,
65                 }
66             }
67             PatKind::Path(ref qpath) => {
68                 let (def, _, _) = self.resolve_ty_and_def_ufcs(qpath, pat.hir_id, pat.span);
69                 match def {
70                     Def::Const(..) | Def::AssociatedConst(..) => false,
71                     _ => true,
72                 }
73             }
74             PatKind::Wild |
75             PatKind::Binding(..) |
76             PatKind::Ref(..) => false,
77         };
78         if is_non_ref_pat {
79             debug!("pattern is non reference pattern");
80             let mut exp_ty = self.resolve_type_vars_with_obligations(&expected);
81
82             // Peel off as many `&` or `&mut` from the discriminant as possible. For example,
83             // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
84             // the `Some(5)` which is not of type Ref.
85             //
86             // For each ampersand peeled off, update the binding mode and push the original
87             // type into the adjustments vector.
88             //
89             // See the examples in `run-pass/match-defbm*.rs`.
90             let mut pat_adjustments = vec![];
91             while let ty::Ref(_, inner_ty, inner_mutability) = exp_ty.sty {
92                 debug!("inspecting {:?}", exp_ty);
93
94                 debug!("current discriminant is Ref, inserting implicit deref");
95                 // Preserve the reference type. We'll need it later during HAIR lowering.
96                 pat_adjustments.push(exp_ty);
97
98                 exp_ty = inner_ty;
99                 def_bm = match def_bm {
100                     // If default binding mode is by value, make it `ref` or `ref mut`
101                     // (depending on whether we observe `&` or `&mut`).
102                     ty::BindByValue(_) =>
103                         ty::BindByReference(inner_mutability),
104
105                     // Once a `ref`, always a `ref`. This is because a `& &mut` can't mutate
106                     // the underlying value.
107                     ty::BindByReference(hir::Mutability::MutImmutable) =>
108                         ty::BindByReference(hir::Mutability::MutImmutable),
109
110                     // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref`
111                     // (on `&`).
112                     ty::BindByReference(hir::Mutability::MutMutable) =>
113                         ty::BindByReference(inner_mutability),
114                 };
115             }
116             expected = exp_ty;
117
118             if pat_adjustments.len() > 0 {
119                 debug!("default binding mode is now {:?}", def_bm);
120                 self.inh.tables.borrow_mut()
121                     .pat_adjustments_mut()
122                     .insert(pat.hir_id, pat_adjustments);
123             }
124         } else if let PatKind::Ref(..) = pat.node {
125             // When you encounter a `&pat` pattern, reset to "by
126             // value". This is so that `x` and `y` here are by value,
127             // as they appear to be:
128             //
129             // ```
130             // match &(&22, &44) {
131             //   (&x, &y) => ...
132             // }
133             // ```
134             //
135             // cc #46688
136             def_bm = ty::BindByValue(hir::MutImmutable);
137         }
138
139         // Lose mutability now that we know binding mode and discriminant type.
140         let def_bm = def_bm;
141         let expected = expected;
142
143         let ty = match pat.node {
144             PatKind::Wild => {
145                 expected
146             }
147             PatKind::Lit(ref lt) => {
148                 // We've already computed the type above (when checking for a non-ref pat), so
149                 // avoid computing it again.
150                 let ty = self.node_ty(lt.hir_id);
151
152                 // Byte string patterns behave the same way as array patterns
153                 // They can denote both statically and dynamically sized byte arrays
154                 let mut pat_ty = ty;
155                 if let hir::ExprKind::Lit(ref lt) = lt.node {
156                     if let ast::LitKind::ByteStr(_) = lt.node {
157                         let expected_ty = self.structurally_resolved_type(pat.span, expected);
158                         if let ty::Ref(_, r_ty, _) = expected_ty.sty {
159                             if let ty::Slice(_) = r_ty.sty {
160                                 pat_ty = tcx.mk_imm_ref(tcx.types.re_static,
161                                                         tcx.mk_slice(tcx.types.u8))
162                             }
163                         }
164                     }
165                 }
166
167                 // somewhat surprising: in this case, the subtyping
168                 // relation goes the opposite way as the other
169                 // cases. Actually what we really want is not a subtyping
170                 // relation at all but rather that there exists a LUB (so
171                 // that they can be compared). However, in practice,
172                 // constants are always scalars or strings.  For scalars
173                 // subtyping is irrelevant, and for strings `ty` is
174                 // type is `&'static str`, so if we say that
175                 //
176                 //     &'static str <: expected
177                 //
178                 // that's equivalent to there existing a LUB.
179                 self.demand_suptype(pat.span, expected, pat_ty);
180                 pat_ty
181             }
182             PatKind::Range(ref begin, ref end, _) => {
183                 let lhs_ty = self.check_expr(begin);
184                 let rhs_ty = self.check_expr(end);
185
186                 // Check that both end-points are of numeric or char type.
187                 let numeric_or_char = |ty: Ty<'_>| ty.is_numeric() || ty.is_char();
188                 let lhs_compat = numeric_or_char(lhs_ty);
189                 let rhs_compat = numeric_or_char(rhs_ty);
190
191                 if !lhs_compat || !rhs_compat {
192                     let span = if !lhs_compat && !rhs_compat {
193                         pat.span
194                     } else if !lhs_compat {
195                         begin.span
196                     } else {
197                         end.span
198                     };
199
200                     let mut err = struct_span_err!(
201                         tcx.sess,
202                         span,
203                         E0029,
204                         "only char and numeric types are allowed in range patterns"
205                     );
206                     err.span_label(span, "ranges require char or numeric types");
207                     err.note(&format!("start type: {}", self.ty_to_string(lhs_ty)));
208                     err.note(&format!("end type: {}", self.ty_to_string(rhs_ty)));
209                     if tcx.sess.teach(&err.get_code().unwrap()) {
210                         err.note(
211                             "In a match expression, only numbers and characters can be matched \
212                              against a range. This is because the compiler checks that the range \
213                              is non-empty at compile-time, and is unable to evaluate arbitrary \
214                              comparison functions. If you want to capture values of an orderable \
215                              type between two end-points, you can use a guard."
216                          );
217                     }
218                     err.emit();
219                     return;
220                 }
221
222                 // Now that we know the types can be unified we find the unified type and use
223                 // it to type the entire expression.
224                 let common_type = self.resolve_type_vars_if_possible(&lhs_ty);
225
226                 // subtyping doesn't matter here, as the value is some kind of scalar
227                 self.demand_eqtype_pat(pat.span, expected, lhs_ty, match_discrim_span);
228                 self.demand_eqtype_pat(pat.span, expected, rhs_ty, match_discrim_span);
229                 common_type
230             }
231             PatKind::Binding(ba, var_id, _, ref sub) => {
232                 let bm = if ba == hir::BindingAnnotation::Unannotated {
233                     def_bm
234                 } else {
235                     ty::BindingMode::convert(ba)
236                 };
237                 self.inh
238                     .tables
239                     .borrow_mut()
240                     .pat_binding_modes_mut()
241                     .insert(pat.hir_id, bm);
242                 debug!("check_pat_walk: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
243                 let local_ty = self.local_ty(pat.span, pat.hir_id).decl_ty;
244                 match bm {
245                     ty::BindByReference(mutbl) => {
246                         // if the binding is like
247                         //    ref x | ref const x | ref mut x
248                         // then `x` is assigned a value of type `&M T` where M is the mutability
249                         // and T is the expected type.
250                         let region_var = self.next_region_var(infer::PatternRegion(pat.span));
251                         let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
252                         let region_ty = tcx.mk_ref(region_var, mt);
253
254                         // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
255                         // required. However, we use equality, which is stronger. See (*) for
256                         // an explanation.
257                         self.demand_eqtype_pat(pat.span, region_ty, local_ty, match_discrim_span);
258                     }
259                     // otherwise the type of x is the expected type T
260                     ty::BindByValue(_) => {
261                         // As above, `T <: typeof(x)` is required but we
262                         // use equality, see (*) below.
263                         self.demand_eqtype_pat(pat.span, expected, local_ty, match_discrim_span);
264                     }
265                 }
266
267                 // if there are multiple arms, make sure they all agree on
268                 // what the type of the binding `x` ought to be
269                 if var_id != pat.hir_id {
270                     let vt = self.local_ty(pat.span, var_id).decl_ty;
271                     self.demand_eqtype_pat(pat.span, vt, local_ty, match_discrim_span);
272                 }
273
274                 if let Some(ref p) = *sub {
275                     self.check_pat_walk(&p, expected, def_bm, match_discrim_span);
276                 }
277
278                 local_ty
279             }
280             PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
281                 self.check_pat_tuple_struct(
282                     pat,
283                     qpath,
284                     &subpats,
285                     ddpos,
286                     expected,
287                     def_bm,
288                     match_discrim_span,
289                 )
290             }
291             PatKind::Path(ref qpath) => {
292                 self.check_pat_path(pat, qpath, expected)
293             }
294             PatKind::Struct(ref qpath, ref fields, etc) => {
295                 self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, match_discrim_span)
296             }
297             PatKind::Tuple(ref elements, ddpos) => {
298                 let mut expected_len = elements.len();
299                 if ddpos.is_some() {
300                     // Require known type only when `..` is present.
301                     if let ty::Tuple(ref tys) =
302                             self.structurally_resolved_type(pat.span, expected).sty {
303                         expected_len = tys.len();
304                     }
305                 }
306                 let max_len = cmp::max(expected_len, elements.len());
307
308                 let element_tys_iter = (0..max_len).map(|_| {
309                     // FIXME: `MiscVariable` for now -- obtaining the span and name information
310                     // from all tuple elements isn't trivial.
311                     Kind::from(self.next_ty_var(TypeVariableOrigin::TypeInference(pat.span)))
312                 });
313                 let element_tys = tcx.mk_substs(element_tys_iter);
314                 let pat_ty = tcx.mk_ty(ty::Tuple(element_tys));
315                 if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) {
316                     err.emit();
317                     // Walk subpatterns with an expected type of `err` in this case to silence
318                     // further errors being emitted when using the bindings. #50333
319                     let element_tys_iter = (0..max_len).map(|_| tcx.types.err);
320                     for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
321                         self.check_pat_walk(elem, &tcx.types.err, def_bm, match_discrim_span);
322                     }
323                     tcx.mk_tup(element_tys_iter)
324                 } else {
325                     for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
326                         self.check_pat_walk(
327                             elem,
328                             &element_tys[i].expect_ty(),
329                             def_bm,
330                             match_discrim_span,
331                         );
332                     }
333                     pat_ty
334                 }
335             }
336             PatKind::Box(ref inner) => {
337                 let inner_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(inner.span));
338                 let uniq_ty = tcx.mk_box(inner_ty);
339
340                 if self.check_dereferencable(pat.span, expected, &inner) {
341                     // Here, `demand::subtype` is good enough, but I don't
342                     // think any errors can be introduced by using
343                     // `demand::eqtype`.
344                     self.demand_eqtype_pat(pat.span, expected, uniq_ty, match_discrim_span);
345                     self.check_pat_walk(&inner, inner_ty, def_bm, match_discrim_span);
346                     uniq_ty
347                 } else {
348                     self.check_pat_walk(&inner, tcx.types.err, def_bm, match_discrim_span);
349                     tcx.types.err
350                 }
351             }
352             PatKind::Ref(ref inner, mutbl) => {
353                 let expected = self.shallow_resolve(expected);
354                 if self.check_dereferencable(pat.span, expected, &inner) {
355                     // `demand::subtype` would be good enough, but using
356                     // `eqtype` turns out to be equally general. See (*)
357                     // below for details.
358
359                     // Take region, inner-type from expected type if we
360                     // can, to avoid creating needless variables.  This
361                     // also helps with the bad interactions of the given
362                     // hack detailed in (*) below.
363                     debug!("check_pat_walk: expected={:?}", expected);
364                     let (rptr_ty, inner_ty) = match expected.sty {
365                         ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => {
366                             (expected, r_ty)
367                         }
368                         _ => {
369                             let inner_ty = self.next_ty_var(
370                                 TypeVariableOrigin::TypeInference(inner.span));
371                             let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
372                             let region = self.next_region_var(infer::PatternRegion(pat.span));
373                             let rptr_ty = tcx.mk_ref(region, mt);
374                             debug!("check_pat_walk: demanding {:?} = {:?}", expected, rptr_ty);
375                             let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
376
377                             // Look for a case like `fn foo(&foo: u32)` and suggest
378                             // `fn foo(foo: &u32)`
379                             if let Some(mut err) = err {
380                                 self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected);
381                                 err.emit();
382                             }
383                             (rptr_ty, inner_ty)
384                         }
385                     };
386
387                     self.check_pat_walk(&inner, inner_ty, def_bm, match_discrim_span);
388                     rptr_ty
389                 } else {
390                     self.check_pat_walk(&inner, tcx.types.err, def_bm, match_discrim_span);
391                     tcx.types.err
392                 }
393             }
394             PatKind::Slice(ref before, ref slice, ref after) => {
395                 let expected_ty = self.structurally_resolved_type(pat.span, expected);
396                 let (inner_ty, slice_ty) = match expected_ty.sty {
397                     ty::Array(inner_ty, size) => {
398                         let size = size.unwrap_usize(tcx);
399                         let min_len = before.len() as u64 + after.len() as u64;
400                         if slice.is_none() {
401                             if min_len != size {
402                                 struct_span_err!(
403                                     tcx.sess, pat.span, E0527,
404                                     "pattern requires {} elements but array has {}",
405                                     min_len, size)
406                                     .span_label(pat.span, format!("expected {} elements", size))
407                                     .emit();
408                             }
409                             (inner_ty, tcx.types.err)
410                         } else if let Some(rest) = size.checked_sub(min_len) {
411                             (inner_ty, tcx.mk_array(inner_ty, rest))
412                         } else {
413                             struct_span_err!(tcx.sess, pat.span, E0528,
414                                     "pattern requires at least {} elements but array has {}",
415                                     min_len, size)
416                                 .span_label(pat.span,
417                                     format!("pattern cannot match array of {} elements", size))
418                                 .emit();
419                             (inner_ty, tcx.types.err)
420                         }
421                     }
422                     ty::Slice(inner_ty) => (inner_ty, expected_ty),
423                     _ => {
424                         if !expected_ty.references_error() {
425                             let mut err = struct_span_err!(
426                                 tcx.sess, pat.span, E0529,
427                                 "expected an array or slice, found `{}`",
428                                 expected_ty);
429                             if let ty::Ref(_, ty, _) = expected_ty.sty {
430                                 match ty.sty {
431                                     ty::Array(..) | ty::Slice(..) => {
432                                         err.help("the semantics of slice patterns changed \
433                                                   recently; see issue #23121");
434                                     }
435                                     _ => {}
436                                 }
437                             }
438
439                             err.span_label( pat.span,
440                                 format!("pattern cannot match with input type `{}`", expected_ty)
441                             ).emit();
442                         }
443                         (tcx.types.err, tcx.types.err)
444                     }
445                 };
446
447                 for elt in before {
448                     self.check_pat_walk(&elt, inner_ty, def_bm, match_discrim_span);
449                 }
450                 if let Some(ref slice) = *slice {
451                     self.check_pat_walk(&slice, slice_ty, def_bm, match_discrim_span);
452                 }
453                 for elt in after {
454                     self.check_pat_walk(&elt, inner_ty, def_bm, match_discrim_span);
455                 }
456                 expected_ty
457             }
458         };
459
460         self.write_ty(pat.hir_id, ty);
461
462         // (*) In most of the cases above (literals and constants being
463         // the exception), we relate types using strict equality, even
464         // though subtyping would be sufficient. There are a few reasons
465         // for this, some of which are fairly subtle and which cost me
466         // (nmatsakis) an hour or two debugging to remember, so I thought
467         // I'd write them down this time.
468         //
469         // 1. There is no loss of expressiveness here, though it does
470         // cause some inconvenience. What we are saying is that the type
471         // of `x` becomes *exactly* what is expected. This can cause unnecessary
472         // errors in some cases, such as this one:
473         //
474         // ```
475         // fn foo<'x>(x: &'x int) {
476         //    let a = 1;
477         //    let mut z = x;
478         //    z = &a;
479         // }
480         // ```
481         //
482         // The reason we might get an error is that `z` might be
483         // assigned a type like `&'x int`, and then we would have
484         // a problem when we try to assign `&a` to `z`, because
485         // the lifetime of `&a` (i.e., the enclosing block) is
486         // shorter than `'x`.
487         //
488         // HOWEVER, this code works fine. The reason is that the
489         // expected type here is whatever type the user wrote, not
490         // the initializer's type. In this case the user wrote
491         // nothing, so we are going to create a type variable `Z`.
492         // Then we will assign the type of the initializer (`&'x
493         // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
494         // will instantiate `Z` as a type `&'0 int` where `'0` is
495         // a fresh region variable, with the constraint that `'x :
496         // '0`.  So basically we're all set.
497         //
498         // Note that there are two tests to check that this remains true
499         // (`regions-reassign-{match,let}-bound-pointer.rs`).
500         //
501         // 2. Things go horribly wrong if we use subtype. The reason for
502         // THIS is a fairly subtle case involving bound regions. See the
503         // `givens` field in `region_constraints`, as well as the test
504         // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
505         // for details. Short version is that we must sometimes detect
506         // relationships between specific region variables and regions
507         // bound in a closure signature, and that detection gets thrown
508         // off when we substitute fresh region variables here to enable
509         // subtyping.
510     }
511
512     fn borrow_pat_suggestion(
513         &self,
514         err: &mut DiagnosticBuilder<'_>,
515         pat: &Pat,
516         inner: &Pat,
517         expected: Ty<'tcx>,
518     ) {
519         let tcx = self.tcx;
520         if let PatKind::Binding(..) = inner.node {
521             let parent_id = tcx.hir().get_parent_node_by_hir_id(pat.hir_id);
522             let parent = tcx.hir().get_by_hir_id(parent_id);
523             debug!("inner {:?} pat {:?} parent {:?}", inner, pat, parent);
524             match parent {
525                 hir::Node::Item(hir::Item { node: hir::ItemKind::Fn(..), .. }) |
526                 hir::Node::ForeignItem(hir::ForeignItem {
527                     node: hir::ForeignItemKind::Fn(..), ..
528                 }) |
529                 hir::Node::TraitItem(hir::TraitItem { node: hir::TraitItemKind::Method(..), .. }) |
530                 hir::Node::ImplItem(hir::ImplItem { node: hir::ImplItemKind::Method(..), .. }) => {
531                     // this pat is likely an argument
532                     if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
533                         // FIXME: turn into structured suggestion, will need a span that also
534                         // includes the the arg's type.
535                         err.help(&format!("did you mean `{}: &{}`?", snippet, expected));
536                     }
537                 }
538                 hir::Node::Expr(hir::Expr { node: hir::ExprKind::Match(..), .. }) |
539                 hir::Node::Pat(_) => {
540                     // rely on match ergonomics or it might be nested `&&pat`
541                     if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
542                         err.span_suggestion(
543                             pat.span,
544                             "you can probably remove the explicit borrow",
545                             snippet,
546                             Applicability::MaybeIncorrect,
547                         );
548                     }
549                 }
550                 _ => {} // don't provide suggestions in other cases #55175
551             }
552         }
553     }
554
555     pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
556         if let PatKind::Binding(..) = inner.node {
557             if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) {
558                 if let ty::Dynamic(..) = mt.ty.sty {
559                     // This is "x = SomeTrait" being reduced from
560                     // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
561                     let type_str = self.ty_to_string(expected);
562                     let mut err = struct_span_err!(
563                         self.tcx.sess,
564                         span,
565                         E0033,
566                         "type `{}` cannot be dereferenced",
567                         type_str
568                     );
569                     err.span_label(span, format!("type `{}` cannot be dereferenced", type_str));
570                     if self.tcx.sess.teach(&err.get_code().unwrap()) {
571                         err.note("\
572 This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \
573 pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \
574 this type has no compile-time size. Therefore, all accesses to trait types must be through \
575 pointers. If you encounter this error you should try to avoid dereferencing the pointer.
576
577 You can read more about trait objects in the Trait Objects section of the Reference: \
578 https://doc.rust-lang.org/reference/types.html#trait-objects");
579                     }
580                     err.emit();
581                     return false
582                 }
583             }
584         }
585         true
586     }
587
588     pub fn check_match(
589         &self,
590         expr: &'gcx hir::Expr,
591         discrim: &'gcx hir::Expr,
592         arms: &'gcx [hir::Arm],
593         expected: Expectation<'tcx>,
594         match_src: hir::MatchSource,
595     ) -> Ty<'tcx> {
596         let tcx = self.tcx;
597
598         // Not entirely obvious: if matches may create ref bindings, we want to
599         // use the *precise* type of the discriminant, *not* some supertype, as
600         // the "discriminant type" (issue #23116).
601         //
602         // arielb1 [writes here in this comment thread][c] that there
603         // is certainly *some* potential danger, e.g., for an example
604         // like:
605         //
606         // [c]: https://github.com/rust-lang/rust/pull/43399#discussion_r130223956
607         //
608         // ```
609         // let Foo(x) = f()[0];
610         // ```
611         //
612         // Then if the pattern matches by reference, we want to match
613         // `f()[0]` as a lexpr, so we can't allow it to be
614         // coerced. But if the pattern matches by value, `f()[0]` is
615         // still syntactically a lexpr, but we *do* want to allow
616         // coercions.
617         //
618         // However, *likely* we are ok with allowing coercions to
619         // happen if there are no explicit ref mut patterns - all
620         // implicit ref mut patterns must occur behind a reference, so
621         // they will have the "correct" variance and lifetime.
622         //
623         // This does mean that the following pattern would be legal:
624         //
625         // ```
626         // struct Foo(Bar);
627         // struct Bar(u32);
628         // impl Deref for Foo {
629         //     type Target = Bar;
630         //     fn deref(&self) -> &Bar { &self.0 }
631         // }
632         // impl DerefMut for Foo {
633         //     fn deref_mut(&mut self) -> &mut Bar { &mut self.0 }
634         // }
635         // fn foo(x: &mut Foo) {
636         //     {
637         //         let Bar(z): &mut Bar = x;
638         //         *z = 42;
639         //     }
640         //     assert_eq!(foo.0.0, 42);
641         // }
642         // ```
643         //
644         // FIXME(tschottdorf): don't call contains_explicit_ref_binding, which
645         // is problematic as the HIR is being scraped, but ref bindings may be
646         // implicit after #42640. We need to make sure that pat_adjustments
647         // (once introduced) is populated by the time we get here.
648         //
649         // See #44848.
650         let contains_ref_bindings = arms.iter()
651                                         .filter_map(|a| a.contains_explicit_ref_binding())
652                                         .max_by_key(|m| match *m {
653                                             hir::MutMutable => 1,
654                                             hir::MutImmutable => 0,
655                                         });
656         let discrim_ty;
657         if let Some(m) = contains_ref_bindings {
658             discrim_ty = self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m));
659         } else {
660             // ...but otherwise we want to use any supertype of the
661             // discriminant. This is sort of a workaround, see note (*) in
662             // `check_pat` for some details.
663             discrim_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(discrim.span));
664             self.check_expr_has_type_or_error(discrim, discrim_ty);
665         };
666
667         // If there are no arms, that is a diverging match; a special case.
668         if arms.is_empty() {
669             self.diverges.set(self.diverges.get() | Diverges::Always);
670             return tcx.types.never;
671         }
672
673         if self.diverges.get().always() {
674             for arm in arms {
675                 self.warn_if_unreachable(arm.body.hir_id, arm.body.span, "arm");
676             }
677         }
678
679         // Otherwise, we have to union together the types that the
680         // arms produce and so forth.
681         let discrim_diverges = self.diverges.get();
682         self.diverges.set(Diverges::Maybe);
683
684         // rust-lang/rust#55810: Typecheck patterns first (via eager
685         // collection into `Vec`), so we get types for all bindings.
686         let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| {
687             let mut all_pats_diverge = Diverges::WarnedAlways;
688             for p in &arm.pats {
689                 self.diverges.set(Diverges::Maybe);
690                 self.check_pat_walk(
691                     &p,
692                     discrim_ty,
693                     ty::BindingMode::BindByValue(hir::Mutability::MutImmutable),
694                     Some(discrim.span),
695                 );
696                 all_pats_diverge &= self.diverges.get();
697             }
698
699             // As discussed with @eddyb, this is for disabling unreachable_code
700             // warnings on patterns (they're now subsumed by unreachable_patterns
701             // warnings).
702             match all_pats_diverge {
703                 Diverges::Maybe => Diverges::Maybe,
704                 Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
705             }
706         }).collect();
707
708         // Now typecheck the blocks.
709         //
710         // The result of the match is the common supertype of all the
711         // arms. Start out the value as bottom, since it's the, well,
712         // bottom the type lattice, and we'll be moving up the lattice as
713         // we process each arm. (Note that any match with 0 arms is matching
714         // on any empty type and is therefore unreachable; should the flow
715         // of execution reach it, we will panic, so bottom is an appropriate
716         // type in that case)
717         let mut all_arms_diverge = Diverges::WarnedAlways;
718
719         let expected = expected.adjust_for_branches(self);
720
721         let mut coercion = {
722             let coerce_first = match expected {
723                 // We don't coerce to `()` so that if the match expression is a
724                 // statement it's branches can have any consistent type. That allows
725                 // us to give better error messages (pointing to a usually better
726                 // arm for inconsistent arms or to the whole match when a `()` type
727                 // is required).
728                 Expectation::ExpectHasType(ety) if ety != self.tcx.mk_unit() => ety,
729                 _ => self.next_ty_var(TypeVariableOrigin::MiscVariable(expr.span)),
730             };
731             CoerceMany::with_coercion_sites(coerce_first, arms)
732         };
733
734         let mut other_arms = vec![];  // used only for diagnostics
735         let mut prior_arm_ty = None;
736         for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
737             if let Some(ref g) = arm.guard {
738                 self.diverges.set(pats_diverge);
739                 match g {
740                     hir::Guard::If(e) => self.check_expr_has_type_or_error(e, tcx.types.bool),
741                 };
742             }
743
744             self.diverges.set(pats_diverge);
745             let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
746             all_arms_diverge &= self.diverges.get();
747
748             // Handle the fallback arm of a desugared if-let like a missing else.
749             let is_if_let_fallback = match match_src {
750                 hir::MatchSource::IfLetDesugar { contains_else_clause: false } => {
751                     i == arms.len() - 1 && arm_ty.is_unit()
752                 }
753                 _ => false
754             };
755
756             let arm_span = if let hir::ExprKind::Block(ref blk, _) = arm.body.node {
757                 // Point at the block expr instead of the entire block
758                 blk.expr.as_ref().map(|e| e.span).unwrap_or(arm.body.span)
759             } else {
760                 arm.body.span
761             };
762             if is_if_let_fallback {
763                 let cause = self.cause(expr.span, ObligationCauseCode::IfExpressionWithNoElse);
764                 assert!(arm_ty.is_unit());
765                 coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
766             } else {
767                 let cause = if i == 0 {
768                     // The reason for the first arm to fail is not that the match arms diverge,
769                     // but rather that there's a prior obligation that doesn't hold.
770                     self.cause(arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id))
771                 } else {
772                     self.cause(expr.span, ObligationCauseCode::MatchExpressionArm {
773                         arm_span,
774                         source: match_src,
775                         prior_arms: other_arms.clone(),
776                         last_ty: prior_arm_ty.unwrap(),
777                         discrim_hir_id: discrim.hir_id,
778                     })
779                 };
780                 coercion.coerce(self, &cause, &arm.body, arm_ty);
781             }
782             other_arms.push(arm_span);
783             if other_arms.len() > 5 {
784                 other_arms.remove(0);
785             }
786             prior_arm_ty = Some(arm_ty);
787         }
788
789         // We won't diverge unless the discriminant or all arms diverge.
790         self.diverges.set(discrim_diverges | all_arms_diverge);
791
792         coercion.complete(self)
793     }
794
795     fn check_pat_struct(
796         &self,
797         pat: &'gcx hir::Pat,
798         qpath: &hir::QPath,
799         fields: &'gcx [Spanned<hir::FieldPat>],
800         etc: bool,
801         expected: Ty<'tcx>,
802         def_bm: ty::BindingMode,
803         match_discrim_span: Option<Span>,
804     ) -> Ty<'tcx>
805     {
806         // Resolve the path and check the definition for errors.
807         let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.hir_id)
808         {
809             variant_ty
810         } else {
811             for field in fields {
812                 self.check_pat_walk(
813                     &field.node.pat,
814                     self.tcx.types.err,
815                     def_bm,
816                     match_discrim_span,
817                 );
818             }
819             return self.tcx.types.err;
820         };
821
822         // Type-check the path.
823         self.demand_eqtype_pat(pat.span, expected, pat_ty, match_discrim_span);
824
825         // Type-check subpatterns.
826         if self.check_struct_pat_fields(pat_ty, pat.hir_id, pat.span, variant, fields, etc, def_bm)
827         {
828             pat_ty
829         } else {
830             self.tcx.types.err
831         }
832     }
833
834     fn check_pat_path(
835         &self,
836         pat: &hir::Pat,
837         qpath: &hir::QPath,
838         expected: Ty<'tcx>,
839     ) -> Ty<'tcx> {
840         let tcx = self.tcx;
841
842         // Resolve the path and check the definition for errors.
843         let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.hir_id, pat.span);
844         match def {
845             Def::Err => {
846                 self.set_tainted_by_errors();
847                 return tcx.types.err;
848             }
849             Def::Method(..) => {
850                 report_unexpected_variant_def(tcx, &def, pat.span, qpath);
851                 return tcx.types.err;
852             }
853             Def::Ctor(_, _, CtorKind::Fictive) |
854             Def::Ctor(_, _, CtorKind::Fn) => {
855                 report_unexpected_variant_def(tcx, &def, pat.span, qpath);
856                 return tcx.types.err;
857             }
858             Def::Ctor(_, _, CtorKind::Const) | Def::SelfCtor(..) |
859             Def::Const(..) | Def::AssociatedConst(..) => {} // OK
860             _ => bug!("unexpected pattern definition: {:?}", def)
861         }
862
863         // Type-check the path.
864         let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.hir_id).0;
865         self.demand_suptype(pat.span, expected, pat_ty);
866         pat_ty
867     }
868
869     fn check_pat_tuple_struct(
870         &self,
871         pat: &hir::Pat,
872         qpath: &hir::QPath,
873         subpats: &'gcx [P<hir::Pat>],
874         ddpos: Option<usize>,
875         expected: Ty<'tcx>,
876         def_bm: ty::BindingMode,
877         match_arm_pat_span: Option<Span>,
878     ) -> Ty<'tcx> {
879         let tcx = self.tcx;
880         let on_error = || {
881             for pat in subpats {
882                 self.check_pat_walk(&pat, tcx.types.err, def_bm, match_arm_pat_span);
883             }
884         };
885         let report_unexpected_def = |def: Def| {
886             let msg = format!("expected tuple struct/variant, found {} `{}`",
887                               def.kind_name(),
888                               hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false)));
889             struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg)
890                 .span_label(pat.span, "not a tuple variant or struct").emit();
891             on_error();
892         };
893
894         // Resolve the path and check the definition for errors.
895         let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.hir_id, pat.span);
896         if def == Def::Err {
897             self.set_tainted_by_errors();
898             on_error();
899             return self.tcx.types.err;
900         }
901
902         // Type-check the path.
903         let (pat_ty, def) = self.instantiate_value_path(segments, opt_ty, def, pat.span,
904             pat.hir_id);
905         if !pat_ty.is_fn() {
906             report_unexpected_def(def);
907             return self.tcx.types.err;
908         }
909
910         let variant = match def {
911             Def::Err => {
912                 self.set_tainted_by_errors();
913                 on_error();
914                 return tcx.types.err;
915             }
916             Def::AssociatedConst(..) | Def::Method(..) => {
917                 report_unexpected_def(def);
918                 return tcx.types.err;
919             }
920             Def::Ctor(_, _, CtorKind::Fn) => {
921                 tcx.expect_variant_def(def)
922             }
923             _ => bug!("unexpected pattern definition: {:?}", def)
924         };
925
926         // Replace constructor type with constructed type for tuple struct patterns.
927         let pat_ty = pat_ty.fn_sig(tcx).output();
928         let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
929
930         self.demand_eqtype_pat(pat.span, expected, pat_ty, match_arm_pat_span);
931
932         // Type-check subpatterns.
933         if subpats.len() == variant.fields.len() ||
934                 subpats.len() < variant.fields.len() && ddpos.is_some() {
935             let substs = match pat_ty.sty {
936                 ty::Adt(_, substs) => substs,
937                 _ => bug!("unexpected pattern type {:?}", pat_ty),
938             };
939             for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
940                 let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
941                 self.check_pat_walk(&subpat, field_ty, def_bm, match_arm_pat_span);
942
943                 self.tcx.check_stability(variant.fields[i].did, Some(pat.hir_id), subpat.span);
944             }
945         } else {
946             let subpats_ending = if subpats.len() == 1 { "" } else { "s" };
947             let fields_ending = if variant.fields.len() == 1 { "" } else { "s" };
948             struct_span_err!(tcx.sess, pat.span, E0023,
949                              "this pattern has {} field{}, but the corresponding {} has {} field{}",
950                              subpats.len(), subpats_ending, def.kind_name(),
951                              variant.fields.len(),  fields_ending)
952                 .span_label(pat.span, format!("expected {} field{}, found {}",
953                                               variant.fields.len(), fields_ending, subpats.len()))
954                 .emit();
955             on_error();
956             return tcx.types.err;
957         }
958         pat_ty
959     }
960
961     fn check_struct_pat_fields(
962         &self,
963         adt_ty: Ty<'tcx>,
964         pat_id: hir::HirId,
965         span: Span,
966         variant: &'tcx ty::VariantDef,
967         fields: &'gcx [Spanned<hir::FieldPat>],
968         etc: bool,
969         def_bm: ty::BindingMode,
970     ) -> bool {
971         let tcx = self.tcx;
972
973         let (substs, adt) = match adt_ty.sty {
974             ty::Adt(adt, substs) => (substs, adt),
975             _ => span_bug!(span, "struct pattern is not an ADT")
976         };
977         let kind_name = adt.variant_descr();
978
979         // Index the struct fields' types.
980         let field_map = variant.fields
981             .iter()
982             .enumerate()
983             .map(|(i, field)| (field.ident.modern(), (i, field)))
984             .collect::<FxHashMap<_, _>>();
985
986         // Keep track of which fields have already appeared in the pattern.
987         let mut used_fields = FxHashMap::default();
988         let mut no_field_errors = true;
989
990         let mut inexistent_fields = vec![];
991         // Typecheck each field.
992         for &Spanned { node: ref field, span } in fields {
993             let ident = tcx.adjust_ident(field.ident, variant.def_id, self.body_id).0;
994             let field_ty = match used_fields.entry(ident) {
995                 Occupied(occupied) => {
996                     struct_span_err!(tcx.sess, span, E0025,
997                                      "field `{}` bound multiple times \
998                                       in the pattern",
999                                      field.ident)
1000                         .span_label(span,
1001                                     format!("multiple uses of `{}` in pattern", field.ident))
1002                         .span_label(*occupied.get(), format!("first use of `{}`", field.ident))
1003                         .emit();
1004                     no_field_errors = false;
1005                     tcx.types.err
1006                 }
1007                 Vacant(vacant) => {
1008                     vacant.insert(span);
1009                     field_map.get(&ident)
1010                         .map(|(i, f)| {
1011                             self.write_field_index(field.hir_id, *i);
1012                             self.tcx.check_stability(f.did, Some(pat_id), span);
1013                             self.field_ty(span, f, substs)
1014                         })
1015                         .unwrap_or_else(|| {
1016                             inexistent_fields.push(field.ident);
1017                             no_field_errors = false;
1018                             tcx.types.err
1019                         })
1020                 }
1021             };
1022
1023             self.check_pat_walk(&field.pat, field_ty, def_bm, None);
1024         }
1025         let mut unmentioned_fields = variant.fields
1026                 .iter()
1027                 .map(|field| field.ident.modern())
1028                 .filter(|ident| !used_fields.contains_key(&ident))
1029                 .collect::<Vec<_>>();
1030         if inexistent_fields.len() > 0 && !variant.recovered {
1031             let (field_names, t, plural) = if inexistent_fields.len() == 1 {
1032                 (format!("a field named `{}`", inexistent_fields[0]), "this", "")
1033             } else {
1034                 (format!("fields named {}",
1035                          inexistent_fields.iter()
1036                             .map(|ident| format!("`{}`", ident))
1037                             .collect::<Vec<String>>()
1038                             .join(", ")), "these", "s")
1039             };
1040             let spans = inexistent_fields.iter().map(|ident| ident.span).collect::<Vec<_>>();
1041             let mut err = struct_span_err!(tcx.sess,
1042                                            spans,
1043                                            E0026,
1044                                            "{} `{}` does not have {}",
1045                                            kind_name,
1046                                            tcx.def_path_str(variant.def_id),
1047                                            field_names);
1048             if let Some(ident) = inexistent_fields.last() {
1049                 err.span_label(ident.span,
1050                                format!("{} `{}` does not have {} field{}",
1051                                        kind_name,
1052                                        tcx.def_path_str(variant.def_id),
1053                                        t,
1054                                        plural));
1055                 if plural == "" {
1056                     let input = unmentioned_fields.iter().map(|field| &field.name);
1057                     let suggested_name =
1058                         find_best_match_for_name(input, &ident.as_str(), None);
1059                     if let Some(suggested_name) = suggested_name {
1060                         err.span_suggestion(
1061                             ident.span,
1062                             "a field with a similar name exists",
1063                             suggested_name.to_string(),
1064                             Applicability::MaybeIncorrect,
1065                         );
1066
1067                         // we don't want to throw `E0027` in case we have thrown `E0026` for them
1068                         unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str());
1069                     }
1070                 }
1071             }
1072             if tcx.sess.teach(&err.get_code().unwrap()) {
1073                 err.note(
1074                     "This error indicates that a struct pattern attempted to \
1075                      extract a non-existent field from a struct. Struct fields \
1076                      are identified by the name used before the colon : so struct \
1077                      patterns should resemble the declaration of the struct type \
1078                      being matched.\n\n\
1079                      If you are using shorthand field patterns but want to refer \
1080                      to the struct field by a different name, you should rename \
1081                      it explicitly."
1082                 );
1083             }
1084             err.emit();
1085         }
1086
1087         // Require `..` if struct has non_exhaustive attribute.
1088         if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
1089             span_err!(tcx.sess, span, E0638,
1090                       "`..` required with {} marked as non-exhaustive",
1091                       kind_name);
1092         }
1093
1094         // Report an error if incorrect number of the fields were specified.
1095         if kind_name == "union" {
1096             if fields.len() != 1 {
1097                 tcx.sess.span_err(span, "union patterns should have exactly one field");
1098             }
1099             if etc {
1100                 tcx.sess.span_err(span, "`..` cannot be used in union patterns");
1101             }
1102         } else if !etc {
1103             if unmentioned_fields.len() > 0 {
1104                 let field_names = if unmentioned_fields.len() == 1 {
1105                     format!("field `{}`", unmentioned_fields[0])
1106                 } else {
1107                     format!("fields {}",
1108                             unmentioned_fields.iter()
1109                                 .map(|name| format!("`{}`", name))
1110                                 .collect::<Vec<String>>()
1111                                 .join(", "))
1112                 };
1113                 let mut diag = struct_span_err!(tcx.sess, span, E0027,
1114                                                 "pattern does not mention {}",
1115                                                 field_names);
1116                 diag.span_label(span, format!("missing {}", field_names));
1117                 if variant.ctor_kind == CtorKind::Fn {
1118                     diag.note("trying to match a tuple variant with a struct variant pattern");
1119                 }
1120                 if tcx.sess.teach(&diag.get_code().unwrap()) {
1121                     diag.note(
1122                         "This error indicates that a pattern for a struct fails to specify a \
1123                          sub-pattern for every one of the struct's fields. Ensure that each field \
1124                          from the struct's definition is mentioned in the pattern, or use `..` to \
1125                          ignore unwanted fields."
1126                     );
1127                 }
1128                 diag.emit();
1129             }
1130         }
1131         no_field_errors
1132     }
1133 }