]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/check/_match.rs
Auto merge of #43710 - zackmdavis:field_init_shorthand_power_slam, r=Mark-Simulacrum
[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, "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(ba, def_id, _, ref sub) => {
117                 // Note the binding mode in the typeck tables. For now, what we store is always
118                 // identical to what could be scraped from the HIR, but this will change with
119                 // default binding modes (#42640).
120                 let bm = ty::BindingMode::convert(ba);
121                 self.inh
122                     .tables
123                     .borrow_mut()
124                     .pat_binding_modes_mut()
125                     .insert(pat.hir_id, bm);
126                 let typ = self.local_ty(pat.span, pat.id);
127                 match bm {
128                     ty::BindByReference(mutbl) => {
129                         // if the binding is like
130                         //    ref x | ref const x | ref mut x
131                         // then `x` is assigned a value of type `&M T` where M is the mutability
132                         // and T is the expected type.
133                         let region_var = self.next_region_var(infer::PatternRegion(pat.span));
134                         let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
135                         let region_ty = tcx.mk_ref(region_var, mt);
136
137                         // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
138                         // required. However, we use equality, which is stronger. See (*) for
139                         // an explanation.
140                         self.demand_eqtype(pat.span, region_ty, typ);
141                     }
142                     // otherwise the type of x is the expected type T
143                     ty::BindByValue(_) => {
144                         // As above, `T <: typeof(x)` is required but we
145                         // use equality, see (*) below.
146                         self.demand_eqtype(pat.span, expected, typ);
147                     }
148                 }
149
150                 // if there are multiple arms, make sure they all agree on
151                 // what the type of the binding `x` ought to be
152                 let var_id = tcx.hir.as_local_node_id(def_id).unwrap();
153                 if var_id != pat.id {
154                     let vt = self.local_ty(pat.span, var_id);
155                     self.demand_eqtype(pat.span, vt, typ);
156                 }
157
158                 if let Some(ref p) = *sub {
159                     self.check_pat(&p, expected);
160                 }
161
162                 typ
163             }
164             PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
165                 self.check_pat_tuple_struct(pat, qpath, &subpats, ddpos, expected)
166             }
167             PatKind::Path(ref qpath) => {
168                 self.check_pat_path(pat, qpath, expected)
169             }
170             PatKind::Struct(ref qpath, ref fields, etc) => {
171                 self.check_pat_struct(pat, qpath, fields, etc, expected)
172             }
173             PatKind::Tuple(ref elements, ddpos) => {
174                 let mut expected_len = elements.len();
175                 if ddpos.is_some() {
176                     // Require known type only when `..` is present
177                     if let ty::TyTuple(ref tys, _) =
178                             self.structurally_resolved_type(pat.span, expected).sty {
179                         expected_len = tys.len();
180                     }
181                 }
182                 let max_len = cmp::max(expected_len, elements.len());
183
184                 let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(
185                     // FIXME: MiscVariable for now, obtaining the span and name information
186                     //       from all tuple elements isn't trivial.
187                     TypeVariableOrigin::TypeInference(pat.span)));
188                 let element_tys = tcx.mk_type_list(element_tys_iter);
189                 let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys, false));
190                 self.demand_eqtype(pat.span, expected, pat_ty);
191                 for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
192                     self.check_pat(elem, &element_tys[i]);
193                 }
194                 pat_ty
195             }
196             PatKind::Box(ref inner) => {
197                 let inner_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(inner.span));
198                 let uniq_ty = tcx.mk_box(inner_ty);
199
200                 if self.check_dereferencable(pat.span, expected, &inner) {
201                     // Here, `demand::subtype` is good enough, but I don't
202                     // think any errors can be introduced by using
203                     // `demand::eqtype`.
204                     self.demand_eqtype(pat.span, expected, uniq_ty);
205                     self.check_pat(&inner, inner_ty);
206                     uniq_ty
207                 } else {
208                     self.check_pat(&inner, tcx.types.err);
209                     tcx.types.err
210                 }
211             }
212             PatKind::Ref(ref inner, mutbl) => {
213                 let expected = self.shallow_resolve(expected);
214                 if self.check_dereferencable(pat.span, expected, &inner) {
215                     // `demand::subtype` would be good enough, but using
216                     // `eqtype` turns out to be equally general. See (*)
217                     // below for details.
218
219                     // Take region, inner-type from expected type if we
220                     // can, to avoid creating needless variables.  This
221                     // also helps with the bad interactions of the given
222                     // hack detailed in (*) below.
223                     debug!("check_pat_arg: expected={:?}", expected);
224                     let (rptr_ty, inner_ty) = match expected.sty {
225                         ty::TyRef(_, mt) if mt.mutbl == mutbl => {
226                             (expected, mt.ty)
227                         }
228                         _ => {
229                             let inner_ty = self.next_ty_var(
230                                 TypeVariableOrigin::TypeInference(inner.span));
231                             let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
232                             let region = self.next_region_var(infer::PatternRegion(pat.span));
233                             let rptr_ty = tcx.mk_ref(region, mt);
234                             debug!("check_pat_arg: demanding {:?} = {:?}", expected, rptr_ty);
235                             let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
236
237                             // Look for a case like `fn foo(&foo: u32)` and suggest
238                             // `fn foo(foo: &u32)`
239                             if let Some(mut err) = err {
240                                 if is_arg {
241                                     if let PatKind::Binding(..) = inner.node {
242                                         if let Ok(snippet) = self.sess().codemap()
243                                                                         .span_to_snippet(pat.span)
244                                         {
245                                             err.help(&format!("did you mean `{}: &{}`?",
246                                                               &snippet[1..],
247                                                               expected));
248                                         }
249                                     }
250                                 }
251                                 err.emit();
252                             }
253                             (rptr_ty, inner_ty)
254                         }
255                     };
256
257                     self.check_pat(&inner, inner_ty);
258                     rptr_ty
259                 } else {
260                     self.check_pat(&inner, tcx.types.err);
261                     tcx.types.err
262                 }
263             }
264             PatKind::Slice(ref before, ref slice, ref after) => {
265                 let expected_ty = self.structurally_resolved_type(pat.span, expected);
266                 let (inner_ty, slice_ty) = match expected_ty.sty {
267                     ty::TyArray(inner_ty, size) => {
268                         let min_len = before.len() + after.len();
269                         if slice.is_none() {
270                             if min_len != size {
271                                 struct_span_err!(
272                                     tcx.sess, pat.span, E0527,
273                                     "pattern requires {} elements but array has {}",
274                                     min_len, size)
275                                     .span_label(pat.span, format!("expected {} elements",size))
276                                     .emit();
277                             }
278                             (inner_ty, tcx.types.err)
279                         } else if let Some(rest) = size.checked_sub(min_len) {
280                             (inner_ty, tcx.mk_array(inner_ty, rest))
281                         } else {
282                             struct_span_err!(tcx.sess, pat.span, E0528,
283                                     "pattern requires at least {} elements but array has {}",
284                                     min_len, size)
285                                 .span_label(pat.span,
286                                     format!("pattern cannot match array of {} elements", size))
287                                 .emit();
288                             (inner_ty, tcx.types.err)
289                         }
290                     }
291                     ty::TySlice(inner_ty) => (inner_ty, expected_ty),
292                     _ => {
293                         if !expected_ty.references_error() {
294                             let mut err = struct_span_err!(
295                                 tcx.sess, pat.span, E0529,
296                                 "expected an array or slice, found `{}`",
297                                 expected_ty);
298                             if let ty::TyRef(_, ty::TypeAndMut { mutbl: _, ty }) = expected_ty.sty {
299                                 match ty.sty {
300                                     ty::TyArray(..) | ty::TySlice(..) => {
301                                         err.help("the semantics of slice patterns changed \
302                                                   recently; see issue #23121");
303                                     }
304                                     _ => {}
305                                 }
306                             }
307
308                             err.span_label( pat.span,
309                                 format!("pattern cannot match with input type `{}`", expected_ty)
310                             ).emit();
311                         }
312                         (tcx.types.err, tcx.types.err)
313                     }
314                 };
315
316                 for elt in before {
317                     self.check_pat(&elt, inner_ty);
318                 }
319                 if let Some(ref slice) = *slice {
320                     self.check_pat(&slice, slice_ty);
321                 }
322                 for elt in after {
323                     self.check_pat(&elt, inner_ty);
324                 }
325                 expected_ty
326             }
327         };
328
329         self.write_ty(pat.hir_id, ty);
330
331         // (*) In most of the cases above (literals and constants being
332         // the exception), we relate types using strict equality, evewn
333         // though subtyping would be sufficient. There are a few reasons
334         // for this, some of which are fairly subtle and which cost me
335         // (nmatsakis) an hour or two debugging to remember, so I thought
336         // I'd write them down this time.
337         //
338         // 1. There is no loss of expressiveness here, though it does
339         // cause some inconvenience. What we are saying is that the type
340         // of `x` becomes *exactly* what is expected. This can cause unnecessary
341         // errors in some cases, such as this one:
342         // it will cause errors in a case like this:
343         //
344         // ```
345         // fn foo<'x>(x: &'x int) {
346         //    let a = 1;
347         //    let mut z = x;
348         //    z = &a;
349         // }
350         // ```
351         //
352         // The reason we might get an error is that `z` might be
353         // assigned a type like `&'x int`, and then we would have
354         // a problem when we try to assign `&a` to `z`, because
355         // the lifetime of `&a` (i.e., the enclosing block) is
356         // shorter than `'x`.
357         //
358         // HOWEVER, this code works fine. The reason is that the
359         // expected type here is whatever type the user wrote, not
360         // the initializer's type. In this case the user wrote
361         // nothing, so we are going to create a type variable `Z`.
362         // Then we will assign the type of the initializer (`&'x
363         // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
364         // will instantiate `Z` as a type `&'0 int` where `'0` is
365         // a fresh region variable, with the constraint that `'x :
366         // '0`.  So basically we're all set.
367         //
368         // Note that there are two tests to check that this remains true
369         // (`regions-reassign-{match,let}-bound-pointer.rs`).
370         //
371         // 2. Things go horribly wrong if we use subtype. The reason for
372         // THIS is a fairly subtle case involving bound regions. See the
373         // `givens` field in `region_inference`, as well as the test
374         // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
375         // for details. Short version is that we must sometimes detect
376         // relationships between specific region variables and regions
377         // bound in a closure signature, and that detection gets thrown
378         // off when we substitute fresh region variables here to enable
379         // subtyping.
380     }
381
382     pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
383         if let PatKind::Binding(..) = inner.node {
384             if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true, ty::NoPreference) {
385                 if let ty::TyDynamic(..) = mt.ty.sty {
386                     // This is "x = SomeTrait" being reduced from
387                     // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
388                     let type_str = self.ty_to_string(expected);
389                     struct_span_err!(self.tcx.sess, span, E0033,
390                               "type `{}` cannot be dereferenced", type_str)
391                         .span_label(span, format!("type `{}` cannot be dereferenced", type_str))
392                         .emit();
393                     return false
394                 }
395             }
396         }
397         true
398     }
399
400     pub fn check_match(&self,
401                        expr: &'gcx hir::Expr,
402                        discrim: &'gcx hir::Expr,
403                        arms: &'gcx [hir::Arm],
404                        expected: Expectation<'tcx>,
405                        match_src: hir::MatchSource) -> Ty<'tcx> {
406         let tcx = self.tcx;
407
408         // Not entirely obvious: if matches may create ref bindings, we want to
409         // use the *precise* type of the discriminant, *not* some supertype, as
410         // the "discriminant type" (issue #23116).
411         //
412         // FIXME(tschottdorf): don't call contains_explicit_ref_binding, which
413         // is problematic as the HIR is being scraped, but ref bindings may be
414         // implicit after #42640. We need to make sure that pat_adjustments
415         // (once introduced) is populated by the time we get here.
416         //
417         // arielb1 [writes here in this comment thread][c] that there
418         // is certainly *some* potential danger, e.g. for an example
419         // like:
420         //
421         // [c]: https://github.com/rust-lang/rust/pull/43399#discussion_r130223956
422         //
423         // ```
424         // let Foo(x) = f()[0];
425         // ```
426         //
427         // Then if the pattern matches by reference, we want to match
428         // `f()[0]` as a lexpr, so we can't allow it to be
429         // coerced. But if the pattern matches by value, `f()[0]` is
430         // still syntactically a lexpr, but we *do* want to allow
431         // coercions.
432         //
433         // However, *likely* we are ok with allowing coercions to
434         // happen if there are no explicit ref mut patterns - all
435         // implicit ref mut patterns must occur behind a reference, so
436         // they will have the "correct" variance and lifetime.
437         //
438         // This does mean that the following pattern would be legal:
439         //
440         // ```
441         // struct Foo(Bar);
442         // struct Bar(u32);
443         // impl Deref for Foo {
444         //     type Target = Bar;
445         //     fn deref(&self) -> &Bar { &self.0 }
446         // }
447         // impl DerefMut for Foo {
448         //     fn deref_mut(&mut self) -> &mut Bar { &mut self.0 }
449         // }
450         // fn foo(x: &mut Foo) {
451         //     {
452         //         let Bar(z): &mut Bar = x;
453         //         *z = 42;
454         //     }
455         //     assert_eq!(foo.0.0, 42);
456         // }
457         // ```
458
459         let contains_ref_bindings = arms.iter()
460                                         .filter_map(|a| a.contains_explicit_ref_binding())
461                                         .max_by_key(|m| match *m {
462                                             hir::MutMutable => 1,
463                                             hir::MutImmutable => 0,
464                                         });
465         let discrim_ty;
466         if let Some(m) = contains_ref_bindings {
467             discrim_ty = self.check_expr_with_lvalue_pref(discrim, LvaluePreference::from_mutbl(m));
468         } else {
469             // ...but otherwise we want to use any supertype of the
470             // discriminant. This is sort of a workaround, see note (*) in
471             // `check_pat` for some details.
472             discrim_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(discrim.span));
473             self.check_expr_has_type_or_error(discrim, discrim_ty);
474         };
475
476         // If the discriminant diverges, the match is pointless (e.g.,
477         // `match (return) { }`).
478         self.warn_if_unreachable(expr.id, expr.span, "expression");
479
480         // If there are no arms, that is a diverging match; a special case.
481         if arms.is_empty() {
482             self.diverges.set(self.diverges.get() | Diverges::Always);
483             return tcx.types.never;
484         }
485
486         // Otherwise, we have to union together the types that the
487         // arms produce and so forth.
488
489         let discrim_diverges = self.diverges.get();
490         self.diverges.set(Diverges::Maybe);
491
492         // Typecheck the patterns first, so that we get types for all the
493         // bindings.
494         let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| {
495             let mut all_pats_diverge = Diverges::WarnedAlways;
496             for p in &arm.pats {
497                 self.diverges.set(Diverges::Maybe);
498                 self.check_pat(&p, discrim_ty);
499                 all_pats_diverge &= self.diverges.get();
500             }
501
502             // As discussed with @eddyb, this is for disabling unreachable_code
503             // warnings on patterns (they're now subsumed by unreachable_patterns
504             // warnings).
505             match all_pats_diverge {
506                 Diverges::Maybe => Diverges::Maybe,
507                 Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
508             }
509         }).collect();
510
511         // Now typecheck the blocks.
512         //
513         // The result of the match is the common supertype of all the
514         // arms. Start out the value as bottom, since it's the, well,
515         // bottom the type lattice, and we'll be moving up the lattice as
516         // we process each arm. (Note that any match with 0 arms is matching
517         // on any empty type and is therefore unreachable; should the flow
518         // of execution reach it, we will panic, so bottom is an appropriate
519         // type in that case)
520         let mut all_arms_diverge = Diverges::WarnedAlways;
521
522         let expected = expected.adjust_for_branches(self);
523
524         let mut coercion = {
525             let coerce_first = match expected {
526                 // We don't coerce to `()` so that if the match expression is a
527                 // statement it's branches can have any consistent type. That allows
528                 // us to give better error messages (pointing to a usually better
529                 // arm for inconsistent arms or to the whole match when a `()` type
530                 // is required).
531                 Expectation::ExpectHasType(ety) if ety != self.tcx.mk_nil() => ety,
532                 _ => self.next_ty_var(TypeVariableOrigin::MiscVariable(expr.span)),
533             };
534             CoerceMany::with_coercion_sites(coerce_first, arms)
535         };
536
537         for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
538             if let Some(ref e) = arm.guard {
539                 self.diverges.set(pats_diverge);
540                 self.check_expr_has_type_or_error(e, tcx.types.bool);
541             }
542
543             self.diverges.set(pats_diverge);
544             let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
545             all_arms_diverge &= self.diverges.get();
546
547             // Handle the fallback arm of a desugared if-let like a missing else.
548             let is_if_let_fallback = match match_src {
549                 hir::MatchSource::IfLetDesugar { contains_else_clause: false } => {
550                     i == arms.len() - 1 && arm_ty.is_nil()
551                 }
552                 _ => false
553             };
554
555             if is_if_let_fallback {
556                 let cause = self.cause(expr.span, ObligationCauseCode::IfExpressionWithNoElse);
557                 assert!(arm_ty.is_nil());
558                 coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
559             } else {
560                 let cause = self.cause(expr.span, ObligationCauseCode::MatchExpressionArm {
561                     arm_span: arm.body.span,
562                     source: match_src
563                 });
564                 coercion.coerce(self, &cause, &arm.body, arm_ty, self.diverges.get());
565             }
566         }
567
568         // We won't diverge unless the discriminant or all arms diverge.
569         self.diverges.set(discrim_diverges | all_arms_diverge);
570
571         coercion.complete(self)
572     }
573
574     fn check_pat_struct(&self,
575                         pat: &'gcx hir::Pat,
576                         qpath: &hir::QPath,
577                         fields: &'gcx [Spanned<hir::FieldPat>],
578                         etc: bool,
579                         expected: Ty<'tcx>) -> Ty<'tcx>
580     {
581         // Resolve the path and check the definition for errors.
582         let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.id) {
583             variant_ty
584         } else {
585             for field in fields {
586                 self.check_pat(&field.node.pat, self.tcx.types.err);
587             }
588             return self.tcx.types.err;
589         };
590
591         // Type check the path.
592         self.demand_eqtype(pat.span, expected, pat_ty);
593
594         // Type check subpatterns.
595         self.check_struct_pat_fields(pat_ty, pat.id, pat.span, variant, fields, etc);
596         pat_ty
597     }
598
599     fn check_pat_path(&self,
600                       pat: &hir::Pat,
601                       qpath: &hir::QPath,
602                       expected: Ty<'tcx>) -> Ty<'tcx>
603     {
604         let tcx = self.tcx;
605         let report_unexpected_def = |def: Def| {
606             span_err!(tcx.sess, pat.span, E0533,
607                       "expected unit struct/variant or constant, found {} `{}`",
608                       def.kind_name(),
609                       hir::print::to_string(&tcx.hir, |s| s.print_qpath(qpath, false)));
610         };
611
612         // Resolve the path and check the definition for errors.
613         let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
614         match def {
615             Def::Err => {
616                 self.set_tainted_by_errors();
617                 return tcx.types.err;
618             }
619             Def::Method(..) => {
620                 report_unexpected_def(def);
621                 return tcx.types.err;
622             }
623             Def::VariantCtor(_, CtorKind::Const) |
624             Def::StructCtor(_, CtorKind::Const) |
625             Def::Const(..) | Def::AssociatedConst(..) => {} // OK
626             _ => bug!("unexpected pattern definition: {:?}", def)
627         }
628
629         // Type check the path.
630         let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
631         self.demand_suptype(pat.span, expected, pat_ty);
632         pat_ty
633     }
634
635     fn check_pat_tuple_struct(&self,
636                               pat: &hir::Pat,
637                               qpath: &hir::QPath,
638                               subpats: &'gcx [P<hir::Pat>],
639                               ddpos: Option<usize>,
640                               expected: Ty<'tcx>) -> Ty<'tcx>
641     {
642         let tcx = self.tcx;
643         let on_error = || {
644             for pat in subpats {
645                 self.check_pat(&pat, tcx.types.err);
646             }
647         };
648         let report_unexpected_def = |def: Def| {
649             let msg = format!("expected tuple struct/variant, found {} `{}`",
650                               def.kind_name(),
651                               hir::print::to_string(&tcx.hir, |s| s.print_qpath(qpath, false)));
652             struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg)
653                 .span_label(pat.span, "not a tuple variant or struct").emit();
654             on_error();
655         };
656
657         // Resolve the path and check the definition for errors.
658         let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
659         let variant = match def {
660             Def::Err => {
661                 self.set_tainted_by_errors();
662                 on_error();
663                 return tcx.types.err;
664             }
665             Def::AssociatedConst(..) | Def::Method(..) => {
666                 report_unexpected_def(def);
667                 return tcx.types.err;
668             }
669             Def::VariantCtor(_, CtorKind::Fn) |
670             Def::StructCtor(_, CtorKind::Fn) => {
671                 tcx.expect_variant_def(def)
672             }
673             _ => bug!("unexpected pattern definition: {:?}", def)
674         };
675
676         // Type check the path.
677         let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
678         // Replace constructor type with constructed type for tuple struct patterns.
679         let pat_ty = pat_ty.fn_sig(tcx).output();
680         let pat_ty = tcx.no_late_bound_regions(&pat_ty).expect("expected fn type");
681         self.demand_eqtype(pat.span, expected, pat_ty);
682
683         // Type check subpatterns.
684         if subpats.len() == variant.fields.len() ||
685                 subpats.len() < variant.fields.len() && ddpos.is_some() {
686             let substs = match pat_ty.sty {
687                 ty::TyAdt(_, substs) => substs,
688                 ref ty => bug!("unexpected pattern type {:?}", ty),
689             };
690             for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
691                 let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
692                 self.check_pat(&subpat, field_ty);
693
694                 self.tcx.check_stability(variant.fields[i].did, pat.id, subpat.span);
695             }
696         } else {
697             let subpats_ending = if subpats.len() == 1 { "" } else { "s" };
698             let fields_ending = if variant.fields.len() == 1 { "" } else { "s" };
699             struct_span_err!(tcx.sess, pat.span, E0023,
700                              "this pattern has {} field{}, but the corresponding {} has {} field{}",
701                              subpats.len(), subpats_ending, def.kind_name(),
702                              variant.fields.len(),  fields_ending)
703                 .span_label(pat.span, format!("expected {} field{}, found {}",
704                                                variant.fields.len(), fields_ending, subpats.len()))
705                 .emit();
706             on_error();
707             return tcx.types.err;
708         }
709         pat_ty
710     }
711
712     fn check_struct_pat_fields(&self,
713                                adt_ty: Ty<'tcx>,
714                                pat_id: ast::NodeId,
715                                span: Span,
716                                variant: &'tcx ty::VariantDef,
717                                fields: &'gcx [Spanned<hir::FieldPat>],
718                                etc: bool) {
719         let tcx = self.tcx;
720
721         let (substs, kind_name) = match adt_ty.sty {
722             ty::TyAdt(adt, substs) => (substs, adt.variant_descr()),
723             _ => span_bug!(span, "struct pattern is not an ADT")
724         };
725
726         // Index the struct fields' types.
727         let field_map = variant.fields
728             .iter()
729             .map(|field| (field.name, field))
730             .collect::<FxHashMap<_, _>>();
731
732         // Keep track of which fields have already appeared in the pattern.
733         let mut used_fields = FxHashMap();
734
735         // Typecheck each field.
736         for &Spanned { node: ref field, span } in fields {
737             let field_ty = match used_fields.entry(field.name) {
738                 Occupied(occupied) => {
739                     struct_span_err!(tcx.sess, span, E0025,
740                                      "field `{}` bound multiple times \
741                                       in the pattern",
742                                      field.name)
743                         .span_label(span,
744                                     format!("multiple uses of `{}` in pattern", field.name))
745                         .span_label(*occupied.get(), format!("first use of `{}`", field.name))
746                         .emit();
747                     tcx.types.err
748                 }
749                 Vacant(vacant) => {
750                     vacant.insert(span);
751                     field_map.get(&field.name)
752                         .map(|f| {
753                             self.tcx.check_stability(f.did, pat_id, span);
754
755                             self.field_ty(span, f, substs)
756                         })
757                         .unwrap_or_else(|| {
758                             struct_span_err!(tcx.sess, span, E0026,
759                                              "{} `{}` does not have a field named `{}`",
760                                              kind_name,
761                                              tcx.item_path_str(variant.did),
762                                              field.name)
763                                 .span_label(span,
764                                             format!("{} `{}` does not have field `{}`",
765                                                      kind_name,
766                                                      tcx.item_path_str(variant.did),
767                                                      field.name))
768                                 .emit();
769
770                             tcx.types.err
771                         })
772                 }
773             };
774
775             self.check_pat(&field.pat, field_ty);
776         }
777
778         // Report an error if incorrect number of the fields were specified.
779         if kind_name == "union" {
780             if fields.len() != 1 {
781                 tcx.sess.span_err(span, "union patterns should have exactly one field");
782             }
783             if etc {
784                 tcx.sess.span_err(span, "`..` cannot be used in union patterns");
785             }
786         } else if !etc {
787             for field in variant.fields
788                 .iter()
789                 .filter(|field| !used_fields.contains_key(&field.name)) {
790                 struct_span_err!(tcx.sess, span, E0027,
791                                 "pattern does not mention field `{}`",
792                                 field.name)
793                                 .span_label(span, format!("missing field `{}`", field.name))
794                                 .emit();
795             }
796         }
797     }
798 }