]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/check/_match.rs
Auto merge of #41437 - cuviper:remove-unstable-deprecated, r=alexcrichton
[rust.git] / src / librustc_typeck / check / _match.rs
1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use rustc::hir::{self, PatKind};
12 use rustc::hir::def::{Def, CtorKind};
13 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
14 use rustc::infer;
15 use rustc::infer::type_variable::TypeVariableOrigin;
16 use rustc::traits::ObligationCauseCode;
17 use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference};
18 use check::{FnCtxt, Expectation, Diverges};
19 use check::coercion::CoerceMany;
20 use util::nodemap::FxHashMap;
21
22 use std::collections::hash_map::Entry::{Occupied, Vacant};
23 use std::cmp;
24 use syntax::ast;
25 use syntax::codemap::Spanned;
26 use syntax::ptr::P;
27 use syntax_pos::Span;
28
29 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
30     pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) {
31         self.check_pat_arg(pat, expected, false);
32     }
33
34     /// The `is_arg` argument indicates whether this pattern is the
35     /// *outermost* pattern in an argument (e.g., in `fn foo(&x:
36     /// &u32)`, it is true for the `&x` pattern but not `x`). This is
37     /// used to tailor error reporting.
38     pub fn check_pat_arg(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>, is_arg: bool) {
39         let tcx = self.tcx;
40
41         debug!("check_pat(pat={:?},expected={:?},is_arg={})", pat, expected, is_arg);
42
43         let ty = match pat.node {
44             PatKind::Wild => {
45                 expected
46             }
47             PatKind::Lit(ref lt) => {
48                 let ty = self.check_expr(&lt);
49
50                 // Byte string patterns behave the same way as array patterns
51                 // They can denote both statically and dynamically sized byte arrays
52                 let mut pat_ty = ty;
53                 if let hir::ExprLit(ref lt) = lt.node {
54                     if let ast::LitKind::ByteStr(_) = lt.node {
55                         let expected_ty = self.structurally_resolved_type(pat.span, expected);
56                         if let ty::TyRef(_, mt) = expected_ty.sty {
57                             if let ty::TySlice(_) = mt.ty.sty {
58                                 pat_ty = tcx.mk_imm_ref(tcx.types.re_static,
59                                                          tcx.mk_slice(tcx.types.u8))
60                             }
61                         }
62                     }
63                 }
64
65                 // somewhat surprising: in this case, the subtyping
66                 // relation goes the opposite way as the other
67                 // cases. Actually what we really want is not a subtyping
68                 // relation at all but rather that there exists a LUB (so
69                 // that they can be compared). However, in practice,
70                 // constants are always scalars or strings.  For scalars
71                 // subtyping is irrelevant, and for strings `ty` is
72                 // type is `&'static str`, so if we say that
73                 //
74                 //     &'static str <: expected
75                 //
76                 // that's equivalent to there existing a LUB.
77                 self.demand_suptype(pat.span, expected, pat_ty);
78                 pat_ty
79             }
80             PatKind::Range(ref begin, ref end, _) => {
81                 let lhs_ty = self.check_expr(begin);
82                 let rhs_ty = self.check_expr(end);
83
84                 // Check that both end-points are of numeric or char type.
85                 let numeric_or_char = |ty: Ty| ty.is_numeric() || ty.is_char();
86                 let lhs_compat = numeric_or_char(lhs_ty);
87                 let rhs_compat = numeric_or_char(rhs_ty);
88
89                 if !lhs_compat || !rhs_compat {
90                     let span = if !lhs_compat && !rhs_compat {
91                         pat.span
92                     } else if !lhs_compat {
93                         begin.span
94                     } else {
95                         end.span
96                     };
97
98                     struct_span_err!(tcx.sess, span, E0029,
99                         "only char and numeric types are allowed in range patterns")
100                         .span_label(span, &format!("ranges require char or numeric types"))
101                         .note(&format!("start type: {}", self.ty_to_string(lhs_ty)))
102                         .note(&format!("end type: {}", self.ty_to_string(rhs_ty)))
103                         .emit();
104                     return;
105                 }
106
107                 // Now that we know the types can be unified we find the unified type and use
108                 // it to type the entire expression.
109                 let common_type = self.resolve_type_vars_if_possible(&lhs_ty);
110
111                 // subtyping doesn't matter here, as the value is some kind of scalar
112                 self.demand_eqtype(pat.span, expected, lhs_ty);
113                 self.demand_eqtype(pat.span, expected, rhs_ty);
114                 common_type
115             }
116             PatKind::Binding(bm, def_id, _, ref sub) => {
117                 let typ = self.local_ty(pat.span, pat.id);
118                 match bm {
119                     hir::BindByRef(mutbl) => {
120                         // if the binding is like
121                         //    ref x | ref const x | ref mut x
122                         // then `x` is assigned a value of type `&M T` where M is the mutability
123                         // and T is the expected type.
124                         let region_var = self.next_region_var(infer::PatternRegion(pat.span));
125                         let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
126                         let region_ty = tcx.mk_ref(region_var, mt);
127
128                         // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
129                         // required. However, we use equality, which is stronger. See (*) for
130                         // an explanation.
131                         self.demand_eqtype(pat.span, region_ty, typ);
132                     }
133                     // otherwise the type of x is the expected type T
134                     hir::BindByValue(_) => {
135                         // As above, `T <: typeof(x)` is required but we
136                         // use equality, see (*) below.
137                         self.demand_eqtype(pat.span, expected, typ);
138                     }
139                 }
140
141                 // if there are multiple arms, make sure they all agree on
142                 // what the type of the binding `x` ought to be
143                 let var_id = tcx.hir.as_local_node_id(def_id).unwrap();
144                 if var_id != pat.id {
145                     let vt = self.local_ty(pat.span, var_id);
146                     self.demand_eqtype(pat.span, vt, typ);
147                 }
148
149                 if let Some(ref p) = *sub {
150                     self.check_pat(&p, expected);
151                 }
152
153                 typ
154             }
155             PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
156                 self.check_pat_tuple_struct(pat, qpath, &subpats, ddpos, expected)
157             }
158             PatKind::Path(ref qpath) => {
159                 self.check_pat_path(pat, qpath, expected)
160             }
161             PatKind::Struct(ref qpath, ref fields, etc) => {
162                 self.check_pat_struct(pat, qpath, fields, etc, expected)
163             }
164             PatKind::Tuple(ref elements, ddpos) => {
165                 let mut expected_len = elements.len();
166                 if ddpos.is_some() {
167                     // Require known type only when `..` is present
168                     if let ty::TyTuple(ref tys, _) =
169                             self.structurally_resolved_type(pat.span, expected).sty {
170                         expected_len = tys.len();
171                     }
172                 }
173                 let max_len = cmp::max(expected_len, elements.len());
174
175                 let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(
176                     // FIXME: MiscVariable for now, obtaining the span and name information
177                     //       from all tuple elements isn't trivial.
178                     TypeVariableOrigin::TypeInference(pat.span)));
179                 let element_tys = tcx.mk_type_list(element_tys_iter);
180                 let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys, false));
181                 self.demand_eqtype(pat.span, expected, pat_ty);
182                 for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
183                     self.check_pat(elem, &element_tys[i]);
184                 }
185                 pat_ty
186             }
187             PatKind::Box(ref inner) => {
188                 let inner_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(inner.span));
189                 let uniq_ty = tcx.mk_box(inner_ty);
190
191                 if self.check_dereferencable(pat.span, expected, &inner) {
192                     // Here, `demand::subtype` is good enough, but I don't
193                     // think any errors can be introduced by using
194                     // `demand::eqtype`.
195                     self.demand_eqtype(pat.span, expected, uniq_ty);
196                     self.check_pat(&inner, inner_ty);
197                     uniq_ty
198                 } else {
199                     self.check_pat(&inner, tcx.types.err);
200                     tcx.types.err
201                 }
202             }
203             PatKind::Ref(ref inner, mutbl) => {
204                 let expected = self.shallow_resolve(expected);
205                 if self.check_dereferencable(pat.span, expected, &inner) {
206                     // `demand::subtype` would be good enough, but using
207                     // `eqtype` turns out to be equally general. See (*)
208                     // below for details.
209
210                     // Take region, inner-type from expected type if we
211                     // can, to avoid creating needless variables.  This
212                     // also helps with the bad interactions of the given
213                     // hack detailed in (*) below.
214                     debug!("check_pat_arg: expected={:?}", expected);
215                     let (rptr_ty, inner_ty) = match expected.sty {
216                         ty::TyRef(_, mt) if mt.mutbl == mutbl => {
217                             (expected, mt.ty)
218                         }
219                         _ => {
220                             let inner_ty = self.next_ty_var(
221                                 TypeVariableOrigin::TypeInference(inner.span));
222                             let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
223                             let region = self.next_region_var(infer::PatternRegion(pat.span));
224                             let rptr_ty = tcx.mk_ref(region, mt);
225                             debug!("check_pat_arg: demanding {:?} = {:?}", expected, rptr_ty);
226                             let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
227
228                             // Look for a case like `fn foo(&foo: u32)` and suggest
229                             // `fn foo(foo: &u32)`
230                             if let Some(mut err) = err {
231                                 if is_arg {
232                                     if let PatKind::Binding(..) = inner.node {
233                                         if let Ok(snippet) = self.sess().codemap()
234                                                                         .span_to_snippet(pat.span)
235                                         {
236                                             err.help(&format!("did you mean `{}: &{}`?",
237                                                               &snippet[1..],
238                                                               expected));
239                                         }
240                                     }
241                                 }
242                                 err.emit();
243                             }
244                             (rptr_ty, inner_ty)
245                         }
246                     };
247
248                     self.check_pat(&inner, inner_ty);
249                     rptr_ty
250                 } else {
251                     self.check_pat(&inner, tcx.types.err);
252                     tcx.types.err
253                 }
254             }
255             PatKind::Slice(ref before, ref slice, ref after) => {
256                 let expected_ty = self.structurally_resolved_type(pat.span, expected);
257                 let (inner_ty, slice_ty) = match expected_ty.sty {
258                     ty::TyArray(inner_ty, size) => {
259                         let min_len = before.len() + after.len();
260                         if slice.is_none() {
261                             if min_len != size {
262                                 struct_span_err!(
263                                     tcx.sess, pat.span, E0527,
264                                     "pattern requires {} elements but array has {}",
265                                     min_len, size)
266                                     .span_label(pat.span, &format!("expected {} elements",size))
267                                     .emit();
268                             }
269                             (inner_ty, tcx.types.err)
270                         } else if let Some(rest) = size.checked_sub(min_len) {
271                             (inner_ty, tcx.mk_array(inner_ty, rest))
272                         } else {
273                             struct_span_err!(tcx.sess, pat.span, E0528,
274                                     "pattern requires at least {} elements but array has {}",
275                                     min_len, size)
276                                 .span_label(pat.span,
277                                     &format!("pattern cannot match array of {} elements", size))
278                                 .emit();
279                             (inner_ty, tcx.types.err)
280                         }
281                     }
282                     ty::TySlice(inner_ty) => (inner_ty, expected_ty),
283                     _ => {
284                         if !expected_ty.references_error() {
285                             let mut err = struct_span_err!(
286                                 tcx.sess, pat.span, E0529,
287                                 "expected an array or slice, found `{}`",
288                                 expected_ty);
289                             if let ty::TyRef(_, ty::TypeAndMut { mutbl: _, ty }) = expected_ty.sty {
290                                 match ty.sty {
291                                     ty::TyArray(..) | ty::TySlice(..) => {
292                                         err.help("the semantics of slice patterns changed \
293                                                   recently; see issue #23121");
294                                     }
295                                     _ => {}
296                                 }
297                             }
298
299                             err.span_label( pat.span,
300                                 &format!("pattern cannot match with input type `{}`", expected_ty)
301                             ).emit();
302                         }
303                         (tcx.types.err, tcx.types.err)
304                     }
305                 };
306
307                 for elt in before {
308                     self.check_pat(&elt, inner_ty);
309                 }
310                 if let Some(ref slice) = *slice {
311                     self.check_pat(&slice, slice_ty);
312                 }
313                 for elt in after {
314                     self.check_pat(&elt, inner_ty);
315                 }
316                 expected_ty
317             }
318         };
319
320         self.write_ty(pat.id, ty);
321
322         // (*) In most of the cases above (literals and constants being
323         // the exception), we relate types using strict equality, evewn
324         // though subtyping would be sufficient. There are a few reasons
325         // for this, some of which are fairly subtle and which cost me
326         // (nmatsakis) an hour or two debugging to remember, so I thought
327         // I'd write them down this time.
328         //
329         // 1. There is no loss of expressiveness here, though it does
330         // cause some inconvenience. What we are saying is that the type
331         // of `x` becomes *exactly* what is expected. This can cause unnecessary
332         // errors in some cases, such as this one:
333         // it will cause errors in a case like this:
334         //
335         // ```
336         // fn foo<'x>(x: &'x int) {
337         //    let a = 1;
338         //    let mut z = x;
339         //    z = &a;
340         // }
341         // ```
342         //
343         // The reason we might get an error is that `z` might be
344         // assigned a type like `&'x int`, and then we would have
345         // a problem when we try to assign `&a` to `z`, because
346         // the lifetime of `&a` (i.e., the enclosing block) is
347         // shorter than `'x`.
348         //
349         // HOWEVER, this code works fine. The reason is that the
350         // expected type here is whatever type the user wrote, not
351         // the initializer's type. In this case the user wrote
352         // nothing, so we are going to create a type variable `Z`.
353         // Then we will assign the type of the initializer (`&'x
354         // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
355         // will instantiate `Z` as a type `&'0 int` where `'0` is
356         // a fresh region variable, with the constraint that `'x :
357         // '0`.  So basically we're all set.
358         //
359         // Note that there are two tests to check that this remains true
360         // (`regions-reassign-{match,let}-bound-pointer.rs`).
361         //
362         // 2. Things go horribly wrong if we use subtype. The reason for
363         // THIS is a fairly subtle case involving bound regions. See the
364         // `givens` field in `region_inference`, as well as the test
365         // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
366         // for details. Short version is that we must sometimes detect
367         // relationships between specific region variables and regions
368         // bound in a closure signature, and that detection gets thrown
369         // off when we substitute fresh region variables here to enable
370         // subtyping.
371     }
372
373     pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
374         if let PatKind::Binding(..) = inner.node {
375             if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true, ty::NoPreference) {
376                 if let ty::TyDynamic(..) = mt.ty.sty {
377                     // This is "x = SomeTrait" being reduced from
378                     // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
379                     let type_str = self.ty_to_string(expected);
380                     struct_span_err!(self.tcx.sess, span, E0033,
381                               "type `{}` cannot be dereferenced", type_str)
382                         .span_label(span, &format!("type `{}` cannot be dereferenced", type_str))
383                         .emit();
384                     return false
385                 }
386             }
387         }
388         true
389     }
390
391     pub fn check_match(&self,
392                        expr: &'gcx hir::Expr,
393                        discrim: &'gcx hir::Expr,
394                        arms: &'gcx [hir::Arm],
395                        expected: Expectation<'tcx>,
396                        match_src: hir::MatchSource) -> Ty<'tcx> {
397         let tcx = self.tcx;
398
399         // Not entirely obvious: if matches may create ref bindings, we
400         // want to use the *precise* type of the discriminant, *not* some
401         // supertype, as the "discriminant type" (issue #23116).
402         let contains_ref_bindings = arms.iter()
403                                         .filter_map(|a| a.contains_ref_binding())
404                                         .max_by_key(|m| match *m {
405                                             hir::MutMutable => 1,
406                                             hir::MutImmutable => 0,
407                                         });
408         let discrim_ty;
409         if let Some(m) = contains_ref_bindings {
410             discrim_ty = self.check_expr_with_lvalue_pref(discrim, LvaluePreference::from_mutbl(m));
411         } else {
412             // ...but otherwise we want to use any supertype of the
413             // discriminant. This is sort of a workaround, see note (*) in
414             // `check_pat` for some details.
415             discrim_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(discrim.span));
416             self.check_expr_has_type(discrim, discrim_ty);
417         };
418
419         // If the discriminant diverges, the match is pointless (e.g.,
420         // `match (return) { }`).
421         self.warn_if_unreachable(expr.id, expr.span, "expression");
422
423         // If there are no arms, that is a diverging match; a special case.
424         if arms.is_empty() {
425             self.diverges.set(self.diverges.get() | Diverges::Always);
426             return tcx.types.never;
427         }
428
429         // Otherwise, we have to union together the types that the
430         // arms produce and so forth.
431
432         let discrim_diverges = self.diverges.get();
433         self.diverges.set(Diverges::Maybe);
434
435         // Typecheck the patterns first, so that we get types for all the
436         // bindings.
437         let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| {
438             let mut all_pats_diverge = Diverges::WarnedAlways;
439             for p in &arm.pats {
440                 self.diverges.set(Diverges::Maybe);
441                 self.check_pat(&p, discrim_ty);
442                 all_pats_diverge &= self.diverges.get();
443             }
444
445             // As discussed with @eddyb, this is for disabling unreachable_code
446             // warnings on patterns (they're now subsumed by unreachable_patterns
447             // warnings).
448             match all_pats_diverge {
449                 Diverges::Maybe => Diverges::Maybe,
450                 Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
451             }
452         }).collect();
453
454         // Now typecheck the blocks.
455         //
456         // The result of the match is the common supertype of all the
457         // arms. Start out the value as bottom, since it's the, well,
458         // bottom the type lattice, and we'll be moving up the lattice as
459         // we process each arm. (Note that any match with 0 arms is matching
460         // on any empty type and is therefore unreachable; should the flow
461         // of execution reach it, we will panic, so bottom is an appropriate
462         // type in that case)
463         let mut all_arms_diverge = Diverges::WarnedAlways;
464
465         let expected = expected.adjust_for_branches(self);
466
467         let mut coercion = {
468             let coerce_first = match expected {
469                 // We don't coerce to `()` so that if the match expression is a
470                 // statement it's branches can have any consistent type. That allows
471                 // us to give better error messages (pointing to a usually better
472                 // arm for inconsistent arms or to the whole match when a `()` type
473                 // is required).
474                 Expectation::ExpectHasType(ety) if ety != self.tcx.mk_nil() => ety,
475                 _ => self.next_ty_var(TypeVariableOrigin::MiscVariable(expr.span)),
476             };
477             CoerceMany::with_coercion_sites(coerce_first, arms)
478         };
479
480         for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
481             if let Some(ref e) = arm.guard {
482                 self.diverges.set(pats_diverge);
483                 self.check_expr_has_type(e, tcx.types.bool);
484             }
485
486             self.diverges.set(pats_diverge);
487             let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
488             all_arms_diverge &= self.diverges.get();
489
490             // Handle the fallback arm of a desugared if-let like a missing else.
491             let is_if_let_fallback = match match_src {
492                 hir::MatchSource::IfLetDesugar { contains_else_clause: false } => {
493                     i == arms.len() - 1 && arm_ty.is_nil()
494                 }
495                 _ => false
496             };
497
498             if is_if_let_fallback {
499                 let cause = self.cause(expr.span, ObligationCauseCode::IfExpressionWithNoElse);
500                 assert!(arm_ty.is_nil());
501                 coercion.coerce_forced_unit(self, &cause, &mut |_| ());
502             } else {
503                 let cause = self.cause(expr.span, ObligationCauseCode::MatchExpressionArm {
504                     arm_span: arm.body.span,
505                     source: match_src
506                 });
507                 coercion.coerce(self, &cause, &arm.body, arm_ty, self.diverges.get());
508             }
509         }
510
511         // We won't diverge unless the discriminant or all arms diverge.
512         self.diverges.set(discrim_diverges | all_arms_diverge);
513
514         coercion.complete(self)
515     }
516
517     fn check_pat_struct(&self,
518                         pat: &'gcx hir::Pat,
519                         qpath: &hir::QPath,
520                         fields: &'gcx [Spanned<hir::FieldPat>],
521                         etc: bool,
522                         expected: Ty<'tcx>) -> Ty<'tcx>
523     {
524         // Resolve the path and check the definition for errors.
525         let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.id) {
526             variant_ty
527         } else {
528             for field in fields {
529                 self.check_pat(&field.node.pat, self.tcx.types.err);
530             }
531             return self.tcx.types.err;
532         };
533
534         // Type check the path.
535         self.demand_eqtype(pat.span, expected, pat_ty);
536
537         // Type check subpatterns.
538         self.check_struct_pat_fields(pat_ty, pat.id, pat.span, variant, fields, etc);
539         pat_ty
540     }
541
542     fn check_pat_path(&self,
543                       pat: &hir::Pat,
544                       qpath: &hir::QPath,
545                       expected: Ty<'tcx>) -> Ty<'tcx>
546     {
547         let tcx = self.tcx;
548         let report_unexpected_def = |def: Def| {
549             span_err!(tcx.sess, pat.span, E0533,
550                       "expected unit struct/variant or constant, found {} `{}`",
551                       def.kind_name(),
552                       hir::print::to_string(&tcx.hir, |s| s.print_qpath(qpath, false)));
553         };
554
555         // Resolve the path and check the definition for errors.
556         let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
557         match def {
558             Def::Err => {
559                 self.set_tainted_by_errors();
560                 return tcx.types.err;
561             }
562             Def::Method(..) => {
563                 report_unexpected_def(def);
564                 return tcx.types.err;
565             }
566             Def::VariantCtor(_, CtorKind::Const) |
567             Def::StructCtor(_, CtorKind::Const) |
568             Def::Const(..) | Def::AssociatedConst(..) => {} // OK
569             _ => bug!("unexpected pattern definition: {:?}", def)
570         }
571
572         // Type check the path.
573         let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
574         self.demand_suptype(pat.span, expected, pat_ty);
575         pat_ty
576     }
577
578     fn check_pat_tuple_struct(&self,
579                               pat: &hir::Pat,
580                               qpath: &hir::QPath,
581                               subpats: &'gcx [P<hir::Pat>],
582                               ddpos: Option<usize>,
583                               expected: Ty<'tcx>) -> Ty<'tcx>
584     {
585         let tcx = self.tcx;
586         let on_error = || {
587             for pat in subpats {
588                 self.check_pat(&pat, tcx.types.err);
589             }
590         };
591         let report_unexpected_def = |def: Def| {
592             let msg = format!("expected tuple struct/variant, found {} `{}`",
593                               def.kind_name(),
594                               hir::print::to_string(&tcx.hir, |s| s.print_qpath(qpath, false)));
595             struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg)
596                 .span_label(pat.span, &format!("not a tuple variant or struct")).emit();
597             on_error();
598         };
599
600         // Resolve the path and check the definition for errors.
601         let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
602         let variant = match def {
603             Def::Err => {
604                 self.set_tainted_by_errors();
605                 on_error();
606                 return tcx.types.err;
607             }
608             Def::AssociatedConst(..) | Def::Method(..) => {
609                 report_unexpected_def(def);
610                 return tcx.types.err;
611             }
612             Def::VariantCtor(_, CtorKind::Fn) |
613             Def::StructCtor(_, CtorKind::Fn) => {
614                 tcx.expect_variant_def(def)
615             }
616             _ => bug!("unexpected pattern definition: {:?}", def)
617         };
618
619         // Type check the path.
620         let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
621         // Replace constructor type with constructed type for tuple struct patterns.
622         let pat_ty = tcx.no_late_bound_regions(&pat_ty.fn_ret()).expect("expected fn type");
623         self.demand_eqtype(pat.span, expected, pat_ty);
624
625         // Type check subpatterns.
626         if subpats.len() == variant.fields.len() ||
627                 subpats.len() < variant.fields.len() && ddpos.is_some() {
628             let substs = match pat_ty.sty {
629                 ty::TyAdt(_, substs) => substs,
630                 ref ty => bug!("unexpected pattern type {:?}", ty),
631             };
632             for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
633                 let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
634                 self.check_pat(&subpat, field_ty);
635
636                 self.tcx.check_stability(variant.fields[i].did, pat.id, subpat.span);
637             }
638         } else {
639             let subpats_ending = if subpats.len() == 1 { "" } else { "s" };
640             let fields_ending = if variant.fields.len() == 1 { "" } else { "s" };
641             struct_span_err!(tcx.sess, pat.span, E0023,
642                              "this pattern has {} field{}, but the corresponding {} has {} field{}",
643                              subpats.len(), subpats_ending, def.kind_name(),
644                              variant.fields.len(),  fields_ending)
645                 .span_label(pat.span, &format!("expected {} field{}, found {}",
646                                                variant.fields.len(), fields_ending, subpats.len()))
647                 .emit();
648             on_error();
649             return tcx.types.err;
650         }
651         pat_ty
652     }
653
654     fn check_struct_pat_fields(&self,
655                                adt_ty: Ty<'tcx>,
656                                pat_id: ast::NodeId,
657                                span: Span,
658                                variant: &'tcx ty::VariantDef,
659                                fields: &'gcx [Spanned<hir::FieldPat>],
660                                etc: bool) {
661         let tcx = self.tcx;
662
663         let (substs, kind_name) = match adt_ty.sty {
664             ty::TyAdt(adt, substs) => (substs, adt.variant_descr()),
665             _ => span_bug!(span, "struct pattern is not an ADT")
666         };
667
668         // Index the struct fields' types.
669         let field_map = variant.fields
670             .iter()
671             .map(|field| (field.name, field))
672             .collect::<FxHashMap<_, _>>();
673
674         // Keep track of which fields have already appeared in the pattern.
675         let mut used_fields = FxHashMap();
676
677         // Typecheck each field.
678         for &Spanned { node: ref field, span } in fields {
679             let field_ty = match used_fields.entry(field.name) {
680                 Occupied(occupied) => {
681                     struct_span_err!(tcx.sess, span, E0025,
682                                      "field `{}` bound multiple times \
683                                       in the pattern",
684                                      field.name)
685                         .span_label(span,
686                                     &format!("multiple uses of `{}` in pattern", field.name))
687                         .span_label(*occupied.get(), &format!("first use of `{}`", field.name))
688                         .emit();
689                     tcx.types.err
690                 }
691                 Vacant(vacant) => {
692                     vacant.insert(span);
693                     field_map.get(&field.name)
694                         .map(|f| {
695                             self.tcx.check_stability(f.did, pat_id, span);
696
697                             self.field_ty(span, f, substs)
698                         })
699                         .unwrap_or_else(|| {
700                             struct_span_err!(tcx.sess, span, E0026,
701                                              "{} `{}` does not have a field named `{}`",
702                                              kind_name,
703                                              tcx.item_path_str(variant.did),
704                                              field.name)
705                                 .span_label(span,
706                                             &format!("{} `{}` does not have field `{}`",
707                                                      kind_name,
708                                                      tcx.item_path_str(variant.did),
709                                                      field.name))
710                                 .emit();
711
712                             tcx.types.err
713                         })
714                 }
715             };
716
717             self.check_pat(&field.pat, field_ty);
718         }
719
720         // Report an error if incorrect number of the fields were specified.
721         if kind_name == "union" {
722             if fields.len() != 1 {
723                 tcx.sess.span_err(span, "union patterns should have exactly one field");
724             }
725             if etc {
726                 tcx.sess.span_err(span, "`..` cannot be used in union patterns");
727             }
728         } else if !etc {
729             for field in variant.fields
730                 .iter()
731                 .filter(|field| !used_fields.contains_key(&field.name)) {
732                 struct_span_err!(tcx.sess, span, E0027,
733                                 "pattern does not mention field `{}`",
734                                 field.name)
735                                 .span_label(span, &format!("missing field `{}`", field.name))
736                                 .emit();
737             }
738         }
739     }
740 }