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