]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/check/_match.rs
Rollup merge of #33196 - mitaa:rdoc-crate-links, 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 hir::def::{self, Def};
12 use rustc::infer::{self, InferOk, TypeOrigin};
13 use hir::pat_util::{PatIdMap, pat_id_map, pat_is_binding};
14 use hir::pat_util::pat_is_resolved_const;
15 use rustc::ty::subst::Substs;
16 use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference};
17 use check::{check_expr, check_expr_has_type, check_expr_with_expectation};
18 use check::{demand, FnCtxt, Expectation};
19 use check::{check_expr_with_lvalue_pref};
20 use check::{instantiate_path, resolve_ty_and_def_ufcs, structurally_resolved_type};
21 use check::coercion;
22 use lint;
23 use require_same_types;
24 use util::nodemap::FnvHashMap;
25 use session::Session;
26
27 use std::cmp;
28 use std::collections::hash_map::Entry::{Occupied, Vacant};
29 use syntax::ast;
30 use syntax::codemap::{Span, Spanned};
31 use syntax::ptr::P;
32
33 use rustc::hir::{self, PatKind};
34 use rustc::hir::print as pprust;
35
36 pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
37                            pat: &'tcx hir::Pat,
38                            expected: Ty<'tcx>)
39 {
40     let fcx = pcx.fcx;
41     let tcx = pcx.fcx.ccx.tcx;
42
43     debug!("check_pat(pat={:?},expected={:?})",
44            pat,
45            expected);
46
47     match pat.node {
48         PatKind::Wild => {
49             fcx.write_ty(pat.id, expected);
50         }
51         PatKind::Lit(ref lt) => {
52             check_expr(fcx, &lt);
53             let expr_ty = fcx.expr_ty(&lt);
54
55             // Byte string patterns behave the same way as array patterns
56             // They can denote both statically and dynamically sized byte arrays
57             let mut pat_ty = expr_ty;
58             if let hir::ExprLit(ref lt) = lt.node {
59                 if let ast::LitKind::ByteStr(_) = lt.node {
60                     let expected_ty = structurally_resolved_type(fcx, pat.span, expected);
61                     if let ty::TyRef(_, mt) = expected_ty.sty {
62                         if let ty::TySlice(_) = mt.ty.sty {
63                             pat_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic),
64                                                      tcx.mk_slice(tcx.types.u8))
65                         }
66                     }
67                 }
68             }
69
70             fcx.write_ty(pat.id, pat_ty);
71
72             // somewhat surprising: in this case, the subtyping
73             // relation goes the opposite way as the other
74             // cases. Actually what we really want is not a subtyping
75             // relation at all but rather that there exists a LUB (so
76             // that they can be compared). However, in practice,
77             // constants are always scalars or strings.  For scalars
78             // subtyping is irrelevant, and for strings `expr_ty` is
79             // type is `&'static str`, so if we say that
80             //
81             //     &'static str <: expected
82             //
83             // that's equivalent to there existing a LUB.
84             demand::suptype(fcx, pat.span, expected, pat_ty);
85         }
86         PatKind::Range(ref begin, ref end) => {
87             check_expr(fcx, begin);
88             check_expr(fcx, end);
89
90             let lhs_ty = fcx.expr_ty(begin);
91             let rhs_ty = fcx.expr_ty(end);
92
93             // Check that both end-points are of numeric or char type.
94             let numeric_or_char = |ty: Ty| ty.is_numeric() || ty.is_char();
95             let lhs_compat = numeric_or_char(lhs_ty);
96             let rhs_compat = numeric_or_char(rhs_ty);
97
98             if !lhs_compat || !rhs_compat {
99                 let span = if !lhs_compat && !rhs_compat {
100                     pat.span
101                 } else if !lhs_compat {
102                     begin.span
103                 } else {
104                     end.span
105                 };
106
107                 // Note: spacing here is intentional, we want a space before "start" and "end".
108                 span_err!(tcx.sess, span, E0029,
109                           "only char and numeric types are allowed in range patterns\n \
110                            start type: {}\n end type: {}",
111                           fcx.infcx().ty_to_string(lhs_ty),
112                           fcx.infcx().ty_to_string(rhs_ty)
113                 );
114                 return;
115             }
116
117             // Check that the types of the end-points can be unified.
118             let types_unify = require_same_types(
119                     tcx, Some(fcx.infcx()), false, pat.span, rhs_ty, lhs_ty,
120                     || "mismatched types in range".to_string()
121             );
122
123             // It's ok to return without a message as `require_same_types` prints an error.
124             if !types_unify {
125                 return;
126             }
127
128             // Now that we know the types can be unified we find the unified type and use
129             // it to type the entire expression.
130             let common_type = fcx.infcx().resolve_type_vars_if_possible(&lhs_ty);
131
132             fcx.write_ty(pat.id, common_type);
133
134             // subtyping doesn't matter here, as the value is some kind of scalar
135             demand::eqtype(fcx, pat.span, expected, lhs_ty);
136         }
137         PatKind::Path(..) | PatKind::Ident(..)
138                 if pat_is_resolved_const(&tcx.def_map.borrow(), pat) => {
139             if let Some(pat_def) = tcx.def_map.borrow().get(&pat.id) {
140                 let const_did = pat_def.def_id();
141                 let const_scheme = tcx.lookup_item_type(const_did);
142                 assert!(const_scheme.generics.is_empty());
143                 let const_ty = pcx.fcx.instantiate_type_scheme(pat.span,
144                                                                &Substs::empty(),
145                                                                &const_scheme.ty);
146                 fcx.write_ty(pat.id, const_ty);
147
148                 // FIXME(#20489) -- we should limit the types here to scalars or something!
149
150                 // As with PatKind::Lit, what we really want here is that there
151                 // exist a LUB, but for the cases that can occur, subtype
152                 // is good enough.
153                 demand::suptype(fcx, pat.span, expected, const_ty);
154             } else {
155                 fcx.write_error(pat.id);
156             }
157         }
158         PatKind::Ident(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map.borrow(), pat) => {
159             let typ = fcx.local_ty(pat.span, pat.id);
160             match bm {
161                 hir::BindByRef(mutbl) => {
162                     // if the binding is like
163                     //    ref x | ref const x | ref mut x
164                     // then `x` is assigned a value of type `&M T` where M is the mutability
165                     // and T is the expected type.
166                     let region_var = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
167                     let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
168                     let region_ty = tcx.mk_ref(tcx.mk_region(region_var), mt);
169
170                     // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
171                     // required. However, we use equality, which is stronger. See (*) for
172                     // an explanation.
173                     demand::eqtype(fcx, pat.span, region_ty, typ);
174                 }
175                 // otherwise the type of x is the expected type T
176                 hir::BindByValue(_) => {
177                     // As above, `T <: typeof(x)` is required but we
178                     // use equality, see (*) below.
179                     demand::eqtype(fcx, pat.span, expected, typ);
180                 }
181             }
182
183             fcx.write_ty(pat.id, typ);
184
185             // if there are multiple arms, make sure they all agree on
186             // what the type of the binding `x` ought to be
187             if let Some(&canon_id) = pcx.map.get(&path.node.name) {
188                 if canon_id != pat.id {
189                     let ct = fcx.local_ty(pat.span, canon_id);
190                     demand::eqtype(fcx, pat.span, ct, typ);
191                 }
192
193                 if let Some(ref p) = *sub {
194                     check_pat(pcx, &p, expected);
195                 }
196             }
197         }
198         PatKind::Ident(_, ref path, _) => {
199             let path = hir::Path::from_ident(path.span, path.node);
200             check_pat_enum(pcx, pat, &path, Some(&[]), expected, false);
201         }
202         PatKind::TupleStruct(ref path, ref subpats) => {
203             check_pat_enum(pcx, pat, path, subpats.as_ref().map(|v| &v[..]), expected, true);
204         }
205         PatKind::Path(ref path) => {
206             check_pat_enum(pcx, pat, path, Some(&[]), expected, false);
207         }
208         PatKind::QPath(ref qself, ref path) => {
209             let self_ty = fcx.to_ty(&qself.ty);
210             let path_res = if let Some(&d) = tcx.def_map.borrow().get(&pat.id) {
211                 if d.base_def == Def::Err {
212                     fcx.infcx().set_tainted_by_errors();
213                     fcx.write_error(pat.id);
214                     return;
215                 }
216                 d
217             } else if qself.position == 0 {
218                 // This is just a sentinel for finish_resolving_def_to_ty.
219                 let sentinel = fcx.tcx().map.local_def_id(ast::CRATE_NODE_ID);
220                 def::PathResolution {
221                     base_def: Def::Mod(sentinel),
222                     depth: path.segments.len()
223                 }
224             } else {
225                 debug!("unbound path {:?}", pat);
226                 fcx.write_error(pat.id);
227                 return;
228             };
229             if let Some((opt_ty, segments, def)) =
230                     resolve_ty_and_def_ufcs(fcx, path_res, Some(self_ty),
231                                             path, pat.span, pat.id) {
232                 if check_assoc_item_is_const(pcx, def, pat.span) {
233                     let scheme = tcx.lookup_item_type(def.def_id());
234                     let predicates = tcx.lookup_predicates(def.def_id());
235                     instantiate_path(fcx, segments,
236                                      scheme, &predicates,
237                                      opt_ty, def, pat.span, pat.id);
238                     let const_ty = fcx.node_ty(pat.id);
239                     demand::suptype(fcx, pat.span, expected, const_ty);
240                 } else {
241                     fcx.write_error(pat.id)
242                 }
243             }
244         }
245         PatKind::Struct(ref path, ref fields, etc) => {
246             check_pat_struct(pcx, pat, path, fields, etc, expected);
247         }
248         PatKind::Tup(ref elements) => {
249             let element_tys: Vec<_> =
250                 (0..elements.len()).map(|_| fcx.infcx().next_ty_var())
251                                         .collect();
252             let pat_ty = tcx.mk_tup(element_tys.clone());
253             fcx.write_ty(pat.id, pat_ty);
254             demand::eqtype(fcx, pat.span, expected, pat_ty);
255             for (element_pat, element_ty) in elements.iter().zip(element_tys) {
256                 check_pat(pcx, &element_pat, element_ty);
257             }
258         }
259         PatKind::Box(ref inner) => {
260             let inner_ty = fcx.infcx().next_ty_var();
261             let uniq_ty = tcx.mk_box(inner_ty);
262
263             if check_dereferencable(pcx, pat.span, expected, &inner) {
264                 // Here, `demand::subtype` is good enough, but I don't
265                 // think any errors can be introduced by using
266                 // `demand::eqtype`.
267                 demand::eqtype(fcx, pat.span, expected, uniq_ty);
268                 fcx.write_ty(pat.id, uniq_ty);
269                 check_pat(pcx, &inner, inner_ty);
270             } else {
271                 fcx.write_error(pat.id);
272                 check_pat(pcx, &inner, tcx.types.err);
273             }
274         }
275         PatKind::Ref(ref inner, mutbl) => {
276             let expected = fcx.infcx().shallow_resolve(expected);
277             if check_dereferencable(pcx, pat.span, expected, &inner) {
278                 // `demand::subtype` would be good enough, but using
279                 // `eqtype` turns out to be equally general. See (*)
280                 // below for details.
281
282                 // Take region, inner-type from expected type if we
283                 // can, to avoid creating needless variables.  This
284                 // also helps with the bad interactions of the given
285                 // hack detailed in (*) below.
286                 let (rptr_ty, inner_ty) = match expected.sty {
287                     ty::TyRef(_, mt) if mt.mutbl == mutbl => {
288                         (expected, mt.ty)
289                     }
290                     _ => {
291                         let inner_ty = fcx.infcx().next_ty_var();
292                         let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
293                         let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
294                         let rptr_ty = tcx.mk_ref(tcx.mk_region(region), mt);
295                         demand::eqtype(fcx, pat.span, expected, rptr_ty);
296                         (rptr_ty, inner_ty)
297                     }
298                 };
299
300                 fcx.write_ty(pat.id, rptr_ty);
301                 check_pat(pcx, &inner, inner_ty);
302             } else {
303                 fcx.write_error(pat.id);
304                 check_pat(pcx, &inner, tcx.types.err);
305             }
306         }
307         PatKind::Vec(ref before, ref slice, ref after) => {
308             let expected_ty = structurally_resolved_type(fcx, pat.span, expected);
309             let inner_ty = fcx.infcx().next_ty_var();
310             let pat_ty = match expected_ty.sty {
311                 ty::TyArray(_, size) => tcx.mk_array(inner_ty, {
312                     let min_len = before.len() + after.len();
313                     match *slice {
314                         Some(_) => cmp::max(min_len, size),
315                         None => min_len
316                     }
317                 }),
318                 _ => {
319                     let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
320                     tcx.mk_ref(tcx.mk_region(region), ty::TypeAndMut {
321                         ty: tcx.mk_slice(inner_ty),
322                         mutbl: expected_ty.builtin_deref(true, ty::NoPreference).map(|mt| mt.mutbl)
323                                                               .unwrap_or(hir::MutImmutable)
324                     })
325                 }
326             };
327
328             fcx.write_ty(pat.id, pat_ty);
329
330             // `demand::subtype` would be good enough, but using
331             // `eqtype` turns out to be equally general. See (*)
332             // below for details.
333             demand::eqtype(fcx, pat.span, expected, pat_ty);
334
335             for elt in before {
336                 check_pat(pcx, &elt, inner_ty);
337             }
338             if let Some(ref slice) = *slice {
339                 let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
340                 let mutbl = expected_ty.builtin_deref(true, ty::NoPreference)
341                     .map_or(hir::MutImmutable, |mt| mt.mutbl);
342
343                 let slice_ty = tcx.mk_ref(tcx.mk_region(region), ty::TypeAndMut {
344                     ty: tcx.mk_slice(inner_ty),
345                     mutbl: mutbl
346                 });
347                 check_pat(pcx, &slice, slice_ty);
348             }
349             for elt in after {
350                 check_pat(pcx, &elt, inner_ty);
351             }
352         }
353     }
354
355
356     // (*) In most of the cases above (literals and constants being
357     // the exception), we relate types using strict equality, evewn
358     // though subtyping would be sufficient. There are a few reasons
359     // for this, some of which are fairly subtle and which cost me
360     // (nmatsakis) an hour or two debugging to remember, so I thought
361     // I'd write them down this time.
362     //
363     // 1. There is no loss of expressiveness here, though it does
364     // cause some inconvenience. What we are saying is that the type
365     // of `x` becomes *exactly* what is expected. This can cause unnecessary
366     // errors in some cases, such as this one:
367     // it will cause errors in a case like this:
368     //
369     // ```
370     // fn foo<'x>(x: &'x int) {
371     //    let a = 1;
372     //    let mut z = x;
373     //    z = &a;
374     // }
375     // ```
376     //
377     // The reason we might get an error is that `z` might be
378     // assigned a type like `&'x int`, and then we would have
379     // a problem when we try to assign `&a` to `z`, because
380     // the lifetime of `&a` (i.e., the enclosing block) is
381     // shorter than `'x`.
382     //
383     // HOWEVER, this code works fine. The reason is that the
384     // expected type here is whatever type the user wrote, not
385     // the initializer's type. In this case the user wrote
386     // nothing, so we are going to create a type variable `Z`.
387     // Then we will assign the type of the initializer (`&'x
388     // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
389     // will instantiate `Z` as a type `&'0 int` where `'0` is
390     // a fresh region variable, with the constraint that `'x :
391     // '0`.  So basically we're all set.
392     //
393     // Note that there are two tests to check that this remains true
394     // (`regions-reassign-{match,let}-bound-pointer.rs`).
395     //
396     // 2. Things go horribly wrong if we use subtype. The reason for
397     // THIS is a fairly subtle case involving bound regions. See the
398     // `givens` field in `region_inference`, as well as the test
399     // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
400     // for details. Short version is that we must sometimes detect
401     // relationships between specific region variables and regions
402     // bound in a closure signature, and that detection gets thrown
403     // off when we substitute fresh region variables here to enable
404     // subtyping.
405 }
406
407 fn check_assoc_item_is_const(pcx: &pat_ctxt, def: Def, span: Span) -> bool {
408     match def {
409         Def::AssociatedConst(..) => true,
410         Def::Method(..) => {
411             span_err!(pcx.fcx.ccx.tcx.sess, span, E0327,
412                       "associated items in match patterns must be constants");
413             false
414         }
415         _ => {
416             span_bug!(span, "non-associated item in check_assoc_item_is_const");
417         }
418     }
419 }
420
421 pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
422                                       span: Span, expected: Ty<'tcx>,
423                                       inner: &hir::Pat) -> bool {
424     let fcx = pcx.fcx;
425     let tcx = pcx.fcx.ccx.tcx;
426     if pat_is_binding(&tcx.def_map.borrow(), inner) {
427         let expected = fcx.infcx().shallow_resolve(expected);
428         expected.builtin_deref(true, ty::NoPreference).map_or(true, |mt| match mt.ty.sty {
429             ty::TyTrait(_) => {
430                 // This is "x = SomeTrait" being reduced from
431                 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
432                 span_err!(tcx.sess, span, E0033,
433                           "type `{}` cannot be dereferenced",
434                           fcx.infcx().ty_to_string(expected));
435                 false
436             }
437             _ => true
438         })
439     } else {
440         true
441     }
442 }
443
444 pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
445                              expr: &'tcx hir::Expr,
446                              discrim: &'tcx hir::Expr,
447                              arms: &'tcx [hir::Arm],
448                              expected: Expectation<'tcx>,
449                              match_src: hir::MatchSource) {
450     let tcx = fcx.ccx.tcx;
451
452     // Not entirely obvious: if matches may create ref bindings, we
453     // want to use the *precise* type of the discriminant, *not* some
454     // supertype, as the "discriminant type" (issue #23116).
455     let contains_ref_bindings = arms.iter()
456                                     .filter_map(|a| tcx.arm_contains_ref_binding(a))
457                                     .max_by_key(|m| match *m {
458                                         hir::MutMutable => 1,
459                                         hir::MutImmutable => 0,
460                                     });
461     let discrim_ty;
462     if let Some(m) = contains_ref_bindings {
463         check_expr_with_lvalue_pref(fcx, discrim, LvaluePreference::from_mutbl(m));
464         discrim_ty = fcx.expr_ty(discrim);
465     } else {
466         // ...but otherwise we want to use any supertype of the
467         // discriminant. This is sort of a workaround, see note (*) in
468         // `check_pat` for some details.
469         discrim_ty = fcx.infcx().next_ty_var();
470         check_expr_has_type(fcx, discrim, discrim_ty);
471     };
472
473     // Typecheck the patterns first, so that we get types for all the
474     // bindings.
475     for arm in arms {
476         let mut pcx = pat_ctxt {
477             fcx: fcx,
478             map: pat_id_map(&tcx.def_map, &arm.pats[0]),
479         };
480         for p in &arm.pats {
481             check_pat(&mut pcx, &p, discrim_ty);
482         }
483     }
484
485     // Now typecheck the blocks.
486     //
487     // The result of the match is the common supertype of all the
488     // arms. Start out the value as bottom, since it's the, well,
489     // bottom the type lattice, and we'll be moving up the lattice as
490     // we process each arm. (Note that any match with 0 arms is matching
491     // on any empty type and is therefore unreachable; should the flow
492     // of execution reach it, we will panic, so bottom is an appropriate
493     // type in that case)
494     let expected = expected.adjust_for_branches(fcx);
495     let mut result_ty = fcx.infcx().next_diverging_ty_var();
496     let coerce_first = match expected {
497         // We don't coerce to `()` so that if the match expression is a
498         // statement it's branches can have any consistent type. That allows
499         // us to give better error messages (pointing to a usually better
500         // arm for inconsistent arms or to the whole match when a `()` type
501         // is required).
502         Expectation::ExpectHasType(ety) if ety != fcx.tcx().mk_nil() => {
503             ety
504         }
505         _ => result_ty
506     };
507     for (i, arm) in arms.iter().enumerate() {
508         if let Some(ref e) = arm.guard {
509             check_expr_has_type(fcx, e, tcx.types.bool);
510         }
511         check_expr_with_expectation(fcx, &arm.body, expected);
512         let arm_ty = fcx.expr_ty(&arm.body);
513
514         if result_ty.references_error() || arm_ty.references_error() {
515             result_ty = tcx.types.err;
516             continue;
517         }
518
519         // Handle the fallback arm of a desugared if-let like a missing else.
520         let is_if_let_fallback = match match_src {
521             hir::MatchSource::IfLetDesugar { contains_else_clause: false } => {
522                 i == arms.len() - 1 && arm_ty.is_nil()
523             }
524             _ => false
525         };
526
527         let origin = if is_if_let_fallback {
528             TypeOrigin::IfExpressionWithNoElse(expr.span)
529         } else {
530             TypeOrigin::MatchExpressionArm(expr.span, arm.body.span, match_src)
531         };
532
533         let result = if is_if_let_fallback {
534             fcx.infcx().eq_types(true, origin, arm_ty, result_ty)
535                 .map(|InferOk { obligations, .. }| {
536                     // FIXME(#32730) propagate obligations
537                     assert!(obligations.is_empty());
538                     arm_ty
539                 })
540         } else if i == 0 {
541             // Special-case the first arm, as it has no "previous expressions".
542             coercion::try(fcx, &arm.body, coerce_first)
543         } else {
544             let prev_arms = || arms[..i].iter().map(|arm| &*arm.body);
545             coercion::try_find_lub(fcx, origin, prev_arms, result_ty, &arm.body)
546         };
547
548         result_ty = match result {
549             Ok(ty) => ty,
550             Err(e) => {
551                 let (expected, found) = if is_if_let_fallback {
552                     (arm_ty, result_ty)
553                 } else {
554                     (result_ty, arm_ty)
555                 };
556                 fcx.infcx().report_mismatched_types(origin, expected, found, e);
557                 fcx.tcx().types.err
558             }
559         };
560     }
561
562     fcx.write_ty(expr.id, result_ty);
563 }
564
565 pub struct pat_ctxt<'a, 'tcx: 'a> {
566     pub fcx: &'a FnCtxt<'a, 'tcx>,
567     pub map: PatIdMap,
568 }
569
570 pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx hir::Pat,
571                                   path: &hir::Path, fields: &'tcx [Spanned<hir::FieldPat>],
572                                   etc: bool, expected: Ty<'tcx>) {
573     let fcx = pcx.fcx;
574     let tcx = pcx.fcx.ccx.tcx;
575
576     let def = tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
577     let variant = match fcx.def_struct_variant(def, path.span) {
578         Some((_, variant)) => variant,
579         None => {
580             let name = pprust::path_to_string(path);
581             span_err!(tcx.sess, pat.span, E0163,
582                       "`{}` does not name a struct or a struct variant", name);
583             fcx.write_error(pat.id);
584
585             for field in fields {
586                 check_pat(pcx, &field.node.pat, tcx.types.err);
587             }
588             return;
589         }
590     };
591
592     let pat_ty = pcx.fcx.instantiate_type(def.def_id(), path);
593     let item_substs = match pat_ty.sty {
594         ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
595         _ => span_bug!(pat.span, "struct variant is not an ADT")
596     };
597     demand::eqtype(fcx, pat.span, expected, pat_ty);
598     check_struct_pat_fields(pcx, pat.span, fields, variant, &item_substs, etc);
599
600     fcx.write_ty(pat.id, pat_ty);
601     fcx.write_substs(pat.id, ty::ItemSubsts { substs: item_substs.clone() });
602 }
603
604 // This function exists due to the warning "diagnostic code E0164 already used"
605 fn bad_struct_kind_err(sess: &Session, pat: &hir::Pat, path: &hir::Path, lint: bool) {
606     let name = pprust::path_to_string(path);
607     let msg = format!("`{}` does not name a tuple variant or a tuple struct", name);
608     if lint {
609         sess.add_lint(lint::builtin::MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
610                       pat.id,
611                       pat.span,
612                       msg);
613     } else {
614         span_err!(sess, pat.span, E0164, "{}", msg);
615     }
616 }
617
618 fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
619                             pat: &hir::Pat,
620                             path: &hir::Path,
621                             subpats: Option<&'tcx [P<hir::Pat>]>,
622                             expected: Ty<'tcx>,
623                             is_tuple_struct_pat: bool)
624 {
625     // Typecheck the path.
626     let fcx = pcx.fcx;
627     let tcx = pcx.fcx.ccx.tcx;
628
629     let path_res = match tcx.def_map.borrow().get(&pat.id) {
630         Some(&path_res) if path_res.base_def != Def::Err => path_res,
631         _ => {
632             fcx.infcx().set_tainted_by_errors();
633             fcx.write_error(pat.id);
634
635             if let Some(subpats) = subpats {
636                 for pat in subpats {
637                     check_pat(pcx, &pat, tcx.types.err);
638                 }
639             }
640
641             return;
642         }
643     };
644
645     let (opt_ty, segments, def) = match resolve_ty_and_def_ufcs(fcx, path_res,
646                                                                 None, path,
647                                                                 pat.span, pat.id) {
648         Some(resolution) => resolution,
649         // Error handling done inside resolve_ty_and_def_ufcs, so if
650         // resolution fails just return.
651         None => {return;}
652     };
653
654     // Items that were partially resolved before should have been resolved to
655     // associated constants (i.e. not methods).
656     if path_res.depth != 0 && !check_assoc_item_is_const(pcx, def, pat.span) {
657         fcx.write_error(pat.id);
658         return;
659     }
660
661     let enum_def = def.variant_def_ids()
662         .map_or_else(|| def.def_id(), |(enum_def, _)| enum_def);
663
664     let ctor_scheme = tcx.lookup_item_type(enum_def);
665     let ctor_predicates = tcx.lookup_predicates(enum_def);
666     let path_scheme = if ctor_scheme.ty.is_fn() {
667         let fn_ret = tcx.no_late_bound_regions(&ctor_scheme.ty.fn_ret()).unwrap();
668         ty::TypeScheme {
669             ty: fn_ret.unwrap(),
670             generics: ctor_scheme.generics,
671         }
672     } else {
673         ctor_scheme
674     };
675     instantiate_path(pcx.fcx, segments,
676                      path_scheme, &ctor_predicates,
677                      opt_ty, def, pat.span, pat.id);
678
679     let report_bad_struct_kind = |is_warning| {
680         bad_struct_kind_err(tcx.sess, pat, path, is_warning);
681         if is_warning { return; }
682         fcx.write_error(pat.id);
683         if let Some(subpats) = subpats {
684             for pat in subpats {
685                 check_pat(pcx, &pat, tcx.types.err);
686             }
687         }
688     };
689
690     // If we didn't have a fully resolved path to start with, we had an
691     // associated const, and we should quit now, since the rest of this
692     // function uses checks specific to structs and enums.
693     if path_res.depth != 0 {
694         if is_tuple_struct_pat {
695             report_bad_struct_kind(false);
696         } else {
697             let pat_ty = fcx.node_ty(pat.id);
698             demand::suptype(fcx, pat.span, expected, pat_ty);
699         }
700         return;
701     }
702
703     let pat_ty = fcx.node_ty(pat.id);
704     demand::eqtype(fcx, pat.span, expected, pat_ty);
705
706     let real_path_ty = fcx.node_ty(pat.id);
707     let (kind_name, variant, expected_substs) = match real_path_ty.sty {
708         ty::TyEnum(enum_def, expected_substs) => {
709             let variant = enum_def.variant_of_def(def);
710             ("variant", variant, expected_substs)
711         }
712         ty::TyStruct(struct_def, expected_substs) => {
713             let variant = struct_def.struct_variant();
714             ("struct", variant, expected_substs)
715         }
716         _ => {
717             report_bad_struct_kind(false);
718             return;
719         }
720     };
721
722     match (is_tuple_struct_pat, variant.kind()) {
723         (true, ty::VariantKind::Unit) => {
724             // Matching unit structs with tuple variant patterns (`UnitVariant(..)`)
725             // is allowed for backward compatibility.
726             report_bad_struct_kind(true);
727         }
728         (_, ty::VariantKind::Struct) => {
729             report_bad_struct_kind(false);
730             return
731         }
732         _ => {}
733     }
734
735     if let Some(subpats) = subpats {
736         if subpats.len() == variant.fields.len() {
737             for (subpat, field) in subpats.iter().zip(&variant.fields) {
738                 let field_ty = fcx.field_ty(subpat.span, field, expected_substs);
739                 check_pat(pcx, &subpat, field_ty);
740             }
741         } else if variant.fields.is_empty() {
742             span_err!(tcx.sess, pat.span, E0024,
743                       "this pattern has {} field{}, but the corresponding {} has no fields",
744                       subpats.len(), if subpats.len() == 1 {""} else {"s"}, kind_name);
745
746             for pat in subpats {
747                 check_pat(pcx, &pat, tcx.types.err);
748             }
749         } else {
750             span_err!(tcx.sess, pat.span, E0023,
751                       "this pattern has {} field{}, but the corresponding {} has {} field{}",
752                       subpats.len(), if subpats.len() == 1 {""} else {"s"},
753                       kind_name,
754                       variant.fields.len(), if variant.fields.len() == 1 {""} else {"s"});
755
756             for pat in subpats {
757                 check_pat(pcx, &pat, tcx.types.err);
758             }
759         }
760     }
761 }
762
763 /// `path` is the AST path item naming the type of this struct.
764 /// `fields` is the field patterns of the struct pattern.
765 /// `struct_fields` describes the type of each field of the struct.
766 /// `struct_id` is the ID of the struct.
767 /// `etc` is true if the pattern said '...' and false otherwise.
768 pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
769                                          span: Span,
770                                          fields: &'tcx [Spanned<hir::FieldPat>],
771                                          variant: ty::VariantDef<'tcx>,
772                                          substs: &Substs<'tcx>,
773                                          etc: bool) {
774     let tcx = pcx.fcx.ccx.tcx;
775
776     // Index the struct fields' types.
777     let field_map = variant.fields
778         .iter()
779         .map(|field| (field.name, field))
780         .collect::<FnvHashMap<_, _>>();
781
782     // Keep track of which fields have already appeared in the pattern.
783     let mut used_fields = FnvHashMap();
784
785     // Typecheck each field.
786     for &Spanned { node: ref field, span } in fields {
787         let field_ty = match used_fields.entry(field.name) {
788             Occupied(occupied) => {
789                 let mut err = struct_span_err!(tcx.sess, span, E0025,
790                                                "field `{}` bound multiple times in the pattern",
791                                                field.name);
792                 span_note!(&mut err, *occupied.get(),
793                            "field `{}` previously bound here",
794                            field.name);
795                 err.emit();
796                 tcx.types.err
797             }
798             Vacant(vacant) => {
799                 vacant.insert(span);
800                 field_map.get(&field.name)
801                     .map(|f| pcx.fcx.field_ty(span, f, substs))
802                     .unwrap_or_else(|| {
803                         span_err!(tcx.sess, span, E0026,
804                             "struct `{}` does not have a field named `{}`",
805                             tcx.item_path_str(variant.did),
806                             field.name);
807                         tcx.types.err
808                     })
809             }
810         };
811
812         check_pat(pcx, &field.pat, field_ty);
813     }
814
815     // Report an error if not all the fields were specified.
816     if !etc {
817         for field in variant.fields
818             .iter()
819             .filter(|field| !used_fields.contains_key(&field.name)) {
820             span_err!(tcx.sess, span, E0027,
821                 "pattern does not mention field `{}`",
822                 field.name);
823         }
824     }
825 }