]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/check/_match.rs
Make name resolution errors non-fatal
[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 middle::def;
12 use middle::infer::{self, TypeOrigin};
13 use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding};
14 use middle::pat_util::pat_is_resolved_const;
15 use middle::privacy::{AllPublic, LastMod};
16 use middle::subst::Substs;
17 use middle::ty::{self, Ty, HasTypeFlags, LvaluePreference};
18 use check::{check_expr, check_expr_has_type, check_expr_with_expectation};
19 use check::{check_expr_coercable_to_type, demand, FnCtxt, Expectation};
20 use check::{check_expr_with_lvalue_pref};
21 use check::{instantiate_path, resolve_ty_and_def_ufcs, structurally_resolved_type};
22 use require_same_types;
23 use util::nodemap::FnvHashMap;
24 use session::Session;
25
26 use std::cmp;
27 use std::collections::hash_map::Entry::{Occupied, Vacant};
28 use syntax::ast;
29 use syntax::codemap::{Span, Spanned};
30 use syntax::ptr::P;
31
32 use rustc_front::hir;
33 use rustc_front::print::pprust;
34 use rustc_front::util as hir_util;
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         hir::PatWild => {
49             fcx.write_ty(pat.id, expected);
50         }
51         hir::PatLit(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::LitByteStr(_) = 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         hir::PatRange(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         hir::PatEnum(..) | hir::PatIdent(..)
138                 if pat_is_resolved_const(&tcx.def_map.borrow(), pat) => {
139             if let hir::PatEnum(ref path, ref subpats) = pat.node {
140                 if !(subpats.is_some() && subpats.as_ref().unwrap().is_empty()) {
141                     bad_struct_kind_err(tcx.sess, pat.span, path, false);
142                     return;
143                 }
144             }
145             if let Some(pat_def) = tcx.def_map.borrow().get(&pat.id) {
146                 let const_did = pat_def.def_id();
147                 let const_scheme = tcx.lookup_item_type(const_did);
148                 assert!(const_scheme.generics.is_empty());
149                 let const_ty = pcx.fcx.instantiate_type_scheme(pat.span,
150                                                                &Substs::empty(),
151                                                                &const_scheme.ty);
152                 fcx.write_ty(pat.id, const_ty);
153
154                 // FIXME(#20489) -- we should limit the types here to scalars or something!
155
156                 // As with PatLit, what we really want here is that there
157                 // exist a LUB, but for the cases that can occur, subtype
158                 // is good enough.
159                 demand::suptype(fcx, pat.span, expected, const_ty);
160             } else {
161                 fcx.write_error(pat.id);
162             }
163         }
164         hir::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map.borrow(), pat) => {
165             let typ = fcx.local_ty(pat.span, pat.id);
166             match bm {
167                 hir::BindByRef(mutbl) => {
168                     // if the binding is like
169                     //    ref x | ref const x | ref mut x
170                     // then `x` is assigned a value of type `&M T` where M is the mutability
171                     // and T is the expected type.
172                     let region_var = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
173                     let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
174                     let region_ty = tcx.mk_ref(tcx.mk_region(region_var), mt);
175
176                     // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
177                     // required. However, we use equality, which is stronger. See (*) for
178                     // an explanation.
179                     demand::eqtype(fcx, pat.span, region_ty, typ);
180                 }
181                 // otherwise the type of x is the expected type T
182                 hir::BindByValue(_) => {
183                     // As above, `T <: typeof(x)` is required but we
184                     // use equality, see (*) below.
185                     demand::eqtype(fcx, pat.span, expected, typ);
186                 }
187             }
188
189             fcx.write_ty(pat.id, typ);
190
191             // if there are multiple arms, make sure they all agree on
192             // what the type of the binding `x` ought to be
193             if let Some(&canon_id) = pcx.map.get(&path.node.name) {
194                 if canon_id != pat.id {
195                     let ct = fcx.local_ty(pat.span, canon_id);
196                     demand::eqtype(fcx, pat.span, ct, typ);
197                 }
198
199                 if let Some(ref p) = *sub {
200                     check_pat(pcx, &**p, expected);
201                 }
202             }
203         }
204         hir::PatIdent(_, ref path, _) => {
205             let path = hir_util::ident_to_path(path.span, path.node);
206             check_pat_enum(pcx, pat, &path, Some(&[]), expected, false);
207         }
208         hir::PatEnum(ref path, ref subpats) => {
209             let subpats = subpats.as_ref().map(|v| &v[..]);
210             let is_tuple_struct_pat = !(subpats.is_some() && subpats.unwrap().is_empty());
211             check_pat_enum(pcx, pat, path, subpats, expected, is_tuple_struct_pat);
212         }
213         hir::PatQPath(ref qself, ref path) => {
214             let self_ty = fcx.to_ty(&qself.ty);
215             let path_res = if let Some(&d) = tcx.def_map.borrow().get(&pat.id) {
216                 if d.base_def == def::DefErr {
217                     fcx.write_error(pat.id);
218                     return;
219                 }
220                 d
221             } else if qself.position == 0 {
222                 // This is just a sentinel for finish_resolving_def_to_ty.
223                 let sentinel = fcx.tcx().map.local_def_id(ast::CRATE_NODE_ID);
224                 def::PathResolution {
225                     base_def: def::DefMod(sentinel),
226                     last_private: LastMod(AllPublic),
227                     depth: path.segments.len()
228                 }
229             } else {
230                 debug!("unbound path {:?}", pat);
231                 fcx.write_error(pat.id);
232                 return;
233             };
234             if let Some((opt_ty, segments, def)) =
235                     resolve_ty_and_def_ufcs(fcx, path_res, Some(self_ty),
236                                             path, pat.span, pat.id) {
237                 if check_assoc_item_is_const(pcx, def, pat.span) {
238                     let scheme = tcx.lookup_item_type(def.def_id());
239                     let predicates = tcx.lookup_predicates(def.def_id());
240                     instantiate_path(fcx, segments,
241                                      scheme, &predicates,
242                                      opt_ty, def, pat.span, pat.id);
243                     let const_ty = fcx.node_ty(pat.id);
244                     demand::suptype(fcx, pat.span, expected, const_ty);
245                 } else {
246                     fcx.write_error(pat.id)
247                 }
248             }
249         }
250         hir::PatStruct(ref path, ref fields, etc) => {
251             check_pat_struct(pcx, pat, path, fields, etc, expected);
252         }
253         hir::PatTup(ref elements) => {
254             let element_tys: Vec<_> =
255                 (0..elements.len()).map(|_| fcx.infcx().next_ty_var())
256                                         .collect();
257             let pat_ty = tcx.mk_tup(element_tys.clone());
258             fcx.write_ty(pat.id, pat_ty);
259             demand::eqtype(fcx, pat.span, expected, pat_ty);
260             for (element_pat, element_ty) in elements.iter().zip(element_tys) {
261                 check_pat(pcx, &**element_pat, element_ty);
262             }
263         }
264         hir::PatBox(ref inner) => {
265             let inner_ty = fcx.infcx().next_ty_var();
266             let uniq_ty = tcx.mk_box(inner_ty);
267
268             if check_dereferencable(pcx, pat.span, expected, &**inner) {
269                 // Here, `demand::subtype` is good enough, but I don't
270                 // think any errors can be introduced by using
271                 // `demand::eqtype`.
272                 demand::eqtype(fcx, pat.span, expected, uniq_ty);
273                 fcx.write_ty(pat.id, uniq_ty);
274                 check_pat(pcx, &**inner, inner_ty);
275             } else {
276                 fcx.write_error(pat.id);
277                 check_pat(pcx, &**inner, tcx.types.err);
278             }
279         }
280         hir::PatRegion(ref inner, mutbl) => {
281             let expected = fcx.infcx().shallow_resolve(expected);
282             if check_dereferencable(pcx, pat.span, expected, &**inner) {
283                 // `demand::subtype` would be good enough, but using
284                 // `eqtype` turns out to be equally general. See (*)
285                 // below for details.
286
287                 // Take region, inner-type from expected type if we
288                 // can, to avoid creating needless variables.  This
289                 // also helps with the bad interactions of the given
290                 // hack detailed in (*) below.
291                 let (rptr_ty, inner_ty) = match expected.sty {
292                     ty::TyRef(_, mt) if mt.mutbl == mutbl => {
293                         (expected, mt.ty)
294                     }
295                     _ => {
296                         let inner_ty = fcx.infcx().next_ty_var();
297                         let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
298                         let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
299                         let rptr_ty = tcx.mk_ref(tcx.mk_region(region), mt);
300                         demand::eqtype(fcx, pat.span, expected, rptr_ty);
301                         (rptr_ty, inner_ty)
302                     }
303                 };
304
305                 fcx.write_ty(pat.id, rptr_ty);
306                 check_pat(pcx, &**inner, inner_ty);
307             } else {
308                 fcx.write_error(pat.id);
309                 check_pat(pcx, &**inner, tcx.types.err);
310             }
311         }
312         hir::PatVec(ref before, ref slice, ref after) => {
313             let expected_ty = structurally_resolved_type(fcx, pat.span, expected);
314             let inner_ty = fcx.infcx().next_ty_var();
315             let pat_ty = match expected_ty.sty {
316                 ty::TyArray(_, size) => tcx.mk_array(inner_ty, {
317                     let min_len = before.len() + after.len();
318                     match *slice {
319                         Some(_) => cmp::max(min_len, size),
320                         None => min_len
321                     }
322                 }),
323                 _ => {
324                     let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
325                     tcx.mk_ref(tcx.mk_region(region), ty::TypeAndMut {
326                         ty: tcx.mk_slice(inner_ty),
327                         mutbl: expected_ty.builtin_deref(true, ty::NoPreference).map(|mt| mt.mutbl)
328                                                               .unwrap_or(hir::MutImmutable)
329                     })
330                 }
331             };
332
333             fcx.write_ty(pat.id, pat_ty);
334
335             // `demand::subtype` would be good enough, but using
336             // `eqtype` turns out to be equally general. See (*)
337             // below for details.
338             demand::eqtype(fcx, pat.span, expected, pat_ty);
339
340             for elt in before {
341                 check_pat(pcx, &**elt, inner_ty);
342             }
343             if let Some(ref slice) = *slice {
344                 let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
345                 let mutbl = expected_ty.builtin_deref(true, ty::NoPreference)
346                     .map_or(hir::MutImmutable, |mt| mt.mutbl);
347
348                 let slice_ty = tcx.mk_ref(tcx.mk_region(region), ty::TypeAndMut {
349                     ty: tcx.mk_slice(inner_ty),
350                     mutbl: mutbl
351                 });
352                 check_pat(pcx, &**slice, slice_ty);
353             }
354             for elt in after {
355                 check_pat(pcx, &**elt, inner_ty);
356             }
357         }
358     }
359
360
361     // (*) In most of the cases above (literals and constants being
362     // the exception), we relate types using strict equality, evewn
363     // though subtyping would be sufficient. There are a few reasons
364     // for this, some of which are fairly subtle and which cost me
365     // (nmatsakis) an hour or two debugging to remember, so I thought
366     // I'd write them down this time.
367     //
368     // 1. There is no loss of expressiveness here, though it does
369     // cause some inconvenience. What we are saying is that the type
370     // of `x` becomes *exactly* what is expected. This can cause unnecessary
371     // errors in some cases, such as this one:
372     // it will cause errors in a case like this:
373     //
374     // ```
375     // fn foo<'x>(x: &'x int) {
376     //    let a = 1;
377     //    let mut z = x;
378     //    z = &a;
379     // }
380     // ```
381     //
382     // The reason we might get an error is that `z` might be
383     // assigned a type like `&'x int`, and then we would have
384     // a problem when we try to assign `&a` to `z`, because
385     // the lifetime of `&a` (i.e., the enclosing block) is
386     // shorter than `'x`.
387     //
388     // HOWEVER, this code works fine. The reason is that the
389     // expected type here is whatever type the user wrote, not
390     // the initializer's type. In this case the user wrote
391     // nothing, so we are going to create a type variable `Z`.
392     // Then we will assign the type of the initializer (`&'x
393     // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
394     // will instantiate `Z` as a type `&'0 int` where `'0` is
395     // a fresh region variable, with the constraint that `'x :
396     // '0`.  So basically we're all set.
397     //
398     // Note that there are two tests to check that this remains true
399     // (`regions-reassign-{match,let}-bound-pointer.rs`).
400     //
401     // 2. Things go horribly wrong if we use subtype. The reason for
402     // THIS is a fairly subtle case involving bound regions. See the
403     // `givens` field in `region_inference`, as well as the test
404     // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
405     // for details. Short version is that we must sometimes detect
406     // relationships between specific region variables and regions
407     // bound in a closure signature, and that detection gets thrown
408     // off when we substitute fresh region variables here to enable
409     // subtyping.
410 }
411
412 fn check_assoc_item_is_const(pcx: &pat_ctxt, def: def::Def, span: Span) -> bool {
413     match def {
414         def::DefAssociatedConst(..) => true,
415         def::DefMethod(..) => {
416             span_err!(pcx.fcx.ccx.tcx.sess, span, E0327,
417                       "associated items in match patterns must be constants");
418             false
419         }
420         _ => {
421             pcx.fcx.ccx.tcx.sess.span_bug(span, "non-associated item in
422                                                  check_assoc_item_is_const");
423         }
424     }
425 }
426
427 pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
428                                       span: Span, expected: Ty<'tcx>,
429                                       inner: &hir::Pat) -> bool {
430     let fcx = pcx.fcx;
431     let tcx = pcx.fcx.ccx.tcx;
432     if pat_is_binding(&tcx.def_map.borrow(), inner) {
433         let expected = fcx.infcx().shallow_resolve(expected);
434         expected.builtin_deref(true, ty::NoPreference).map_or(true, |mt| match mt.ty.sty {
435             ty::TyTrait(_) => {
436                 // This is "x = SomeTrait" being reduced from
437                 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
438                 span_err!(tcx.sess, span, E0033,
439                           "type `{}` cannot be dereferenced",
440                           fcx.infcx().ty_to_string(expected));
441                 false
442             }
443             _ => true
444         })
445     } else {
446         true
447     }
448 }
449
450 pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
451                              expr: &'tcx hir::Expr,
452                              discrim: &'tcx hir::Expr,
453                              arms: &'tcx [hir::Arm],
454                              expected: Expectation<'tcx>,
455                              match_src: hir::MatchSource) {
456     let tcx = fcx.ccx.tcx;
457
458     // Not entirely obvious: if matches may create ref bindings, we
459     // want to use the *precise* type of the discriminant, *not* some
460     // supertype, as the "discriminant type" (issue #23116).
461     let contains_ref_bindings = arms.iter()
462                                     .filter_map(|a| tcx.arm_contains_ref_binding(a))
463                                     .max_by_key(|m| match *m {
464                                         hir::MutMutable => 1,
465                                         hir::MutImmutable => 0,
466                                     });
467     let discrim_ty;
468     if let Some(m) = contains_ref_bindings {
469         check_expr_with_lvalue_pref(fcx, discrim, LvaluePreference::from_mutbl(m));
470         discrim_ty = fcx.expr_ty(discrim);
471     } else {
472         // ...but otherwise we want to use any supertype of the
473         // discriminant. This is sort of a workaround, see note (*) in
474         // `check_pat` for some details.
475         discrim_ty = fcx.infcx().next_ty_var();
476         check_expr_has_type(fcx, discrim, discrim_ty);
477     };
478
479     // Typecheck the patterns first, so that we get types for all the
480     // bindings.
481     for arm in arms {
482         let mut pcx = pat_ctxt {
483             fcx: fcx,
484             map: pat_id_map(&tcx.def_map, &*arm.pats[0]),
485         };
486         for p in &arm.pats {
487             check_pat(&mut pcx, &**p, discrim_ty);
488         }
489     }
490
491     // Now typecheck the blocks.
492     //
493     // The result of the match is the common supertype of all the
494     // arms. Start out the value as bottom, since it's the, well,
495     // bottom the type lattice, and we'll be moving up the lattice as
496     // we process each arm. (Note that any match with 0 arms is matching
497     // on any empty type and is therefore unreachable; should the flow
498     // of execution reach it, we will panic, so bottom is an appropriate
499     // type in that case)
500     let expected = expected.adjust_for_branches(fcx);
501     let result_ty = arms.iter().fold(fcx.infcx().next_diverging_ty_var(), |result_ty, arm| {
502         let bty = match expected {
503             // We don't coerce to `()` so that if the match expression is a
504             // statement it's branches can have any consistent type. That allows
505             // us to give better error messages (pointing to a usually better
506             // arm for inconsistent arms or to the whole match when a `()` type
507             // is required).
508             Expectation::ExpectHasType(ety) if ety != fcx.tcx().mk_nil() => {
509                 check_expr_coercable_to_type(fcx, &*arm.body, ety);
510                 ety
511             }
512             _ => {
513                 check_expr_with_expectation(fcx, &*arm.body, expected);
514                 fcx.node_ty(arm.body.id)
515             }
516         };
517
518         if let Some(ref e) = arm.guard {
519             check_expr_has_type(fcx, &**e, tcx.types.bool);
520         }
521
522         if result_ty.references_error() || bty.references_error() {
523             tcx.types.err
524         } else {
525             let (origin, expected, found) = match match_src {
526                 /* if-let construct without an else block */
527                 hir::MatchSource::IfLetDesugar { contains_else_clause }
528                 if !contains_else_clause => (
529                     TypeOrigin::IfExpressionWithNoElse(expr.span),
530                     bty,
531                     result_ty,
532                 ),
533                 _ => (
534                     TypeOrigin::MatchExpressionArm(expr.span, arm.body.span, match_src),
535                     result_ty,
536                     bty,
537                 ),
538             };
539
540             infer::common_supertype(
541                 fcx.infcx(),
542                 origin,
543                 true,
544                 expected,
545                 found,
546             )
547         }
548     });
549
550     fcx.write_ty(expr.id, result_ty);
551 }
552
553 pub struct pat_ctxt<'a, 'tcx: 'a> {
554     pub fcx: &'a FnCtxt<'a, 'tcx>,
555     pub map: PatIdMap,
556 }
557
558 pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx hir::Pat,
559                                   path: &hir::Path, fields: &'tcx [Spanned<hir::FieldPat>],
560                                   etc: bool, expected: Ty<'tcx>) {
561     let fcx = pcx.fcx;
562     let tcx = pcx.fcx.ccx.tcx;
563
564     let def = tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
565     let variant = match fcx.def_struct_variant(def, path.span) {
566         Some((_, variant)) => variant,
567         None => {
568             let name = pprust::path_to_string(path);
569             span_err!(tcx.sess, pat.span, E0163,
570                       "`{}` does not name a struct or a struct variant", name);
571             fcx.write_error(pat.id);
572
573             for field in fields {
574                 check_pat(pcx, &field.node.pat, tcx.types.err);
575             }
576             return;
577         }
578     };
579
580     let pat_ty = pcx.fcx.instantiate_type(def.def_id(), path);
581     let item_substs = match pat_ty.sty {
582         ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
583         _ => tcx.sess.span_bug(pat.span, "struct variant is not an ADT")
584     };
585     demand::eqtype(fcx, pat.span, expected, pat_ty);
586     check_struct_pat_fields(pcx, pat.span, fields, variant, &item_substs, etc);
587
588     fcx.write_ty(pat.id, pat_ty);
589     fcx.write_substs(pat.id, ty::ItemSubsts { substs: item_substs.clone() });
590 }
591
592 // This function exists due to the warning "diagnostic code E0164 already used"
593 fn bad_struct_kind_err(sess: &Session, span: Span, path: &hir::Path, is_warning: bool) {
594     let name = pprust::path_to_string(path);
595     span_err_or_warn!(is_warning, sess, span, E0164,
596         "`{}` does not name a tuple variant or a tuple struct", name);
597 }
598
599 pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
600                                 pat: &hir::Pat,
601                                 path: &hir::Path,
602                                 subpats: Option<&'tcx [P<hir::Pat>]>,
603                                 expected: Ty<'tcx>,
604                                 is_tuple_struct_pat: bool)
605 {
606     // Typecheck the path.
607     let fcx = pcx.fcx;
608     let tcx = pcx.fcx.ccx.tcx;
609
610     let path_res = match tcx.def_map.borrow().get(&pat.id) {
611         Some(&path_res) if path_res.base_def != def::DefErr => path_res,
612         _ => {
613             fcx.write_error(pat.id);
614
615             if let Some(subpats) = subpats {
616                 for pat in subpats {
617                     check_pat(pcx, &**pat, tcx.types.err);
618                 }
619             }
620
621             return;
622         }
623     };
624
625     let (opt_ty, segments, def) = match resolve_ty_and_def_ufcs(fcx, path_res,
626                                                                 None, path,
627                                                                 pat.span, pat.id) {
628         Some(resolution) => resolution,
629         // Error handling done inside resolve_ty_and_def_ufcs, so if
630         // resolution fails just return.
631         None => {return;}
632     };
633
634     // Items that were partially resolved before should have been resolved to
635     // associated constants (i.e. not methods).
636     if path_res.depth != 0 && !check_assoc_item_is_const(pcx, def, pat.span) {
637         fcx.write_error(pat.id);
638         return;
639     }
640
641     let enum_def = def.variant_def_ids()
642         .map_or_else(|| def.def_id(), |(enum_def, _)| enum_def);
643
644     let ctor_scheme = tcx.lookup_item_type(enum_def);
645     let ctor_predicates = tcx.lookup_predicates(enum_def);
646     let path_scheme = if ctor_scheme.ty.is_fn() {
647         let fn_ret = tcx.no_late_bound_regions(&ctor_scheme.ty.fn_ret()).unwrap();
648         ty::TypeScheme {
649             ty: fn_ret.unwrap(),
650             generics: ctor_scheme.generics,
651         }
652     } else {
653         ctor_scheme
654     };
655     instantiate_path(pcx.fcx, segments,
656                      path_scheme, &ctor_predicates,
657                      opt_ty, def, pat.span, pat.id);
658
659     let report_bad_struct_kind = |is_warning| {
660         bad_struct_kind_err(tcx.sess, pat.span, path, is_warning);
661         if is_warning {
662             return;
663         }
664
665         fcx.write_error(pat.id);
666         if let Some(subpats) = subpats {
667             for pat in subpats {
668                 check_pat(pcx, &**pat, tcx.types.err);
669             }
670         }
671     };
672
673     // If we didn't have a fully resolved path to start with, we had an
674     // associated const, and we should quit now, since the rest of this
675     // function uses checks specific to structs and enums.
676     if path_res.depth != 0 {
677         if is_tuple_struct_pat {
678             report_bad_struct_kind(false);
679         } else {
680             let pat_ty = fcx.node_ty(pat.id);
681             demand::suptype(fcx, pat.span, expected, pat_ty);
682         }
683         return;
684     }
685
686     let pat_ty = fcx.node_ty(pat.id);
687     demand::eqtype(fcx, pat.span, expected, pat_ty);
688
689     let real_path_ty = fcx.node_ty(pat.id);
690     let (arg_tys, kind_name): (Vec<_>, &'static str) = match real_path_ty.sty {
691         ty::TyEnum(enum_def, expected_substs)
692             if def == def::DefVariant(enum_def.did, def.def_id(), false) =>
693         {
694             let variant = enum_def.variant_of_def(def);
695             if is_tuple_struct_pat && variant.kind() != ty::VariantKind::Tuple {
696                 // Matching unit variants with tuple variant patterns (`UnitVariant(..)`)
697                 // is allowed for backward compatibility.
698                 let is_special_case = variant.kind() == ty::VariantKind::Unit;
699                 report_bad_struct_kind(is_special_case);
700                 if !is_special_case {
701                     return
702                 } else {
703                     span_note!(tcx.sess, pat.span,
704                         "this warning will become a HARD ERROR in a future release. \
705                         See RFC 218 for details.");
706                 }
707             }
708             (variant.fields
709                     .iter()
710                     .map(|f| fcx.instantiate_type_scheme(pat.span,
711                                                          expected_substs,
712                                                          &f.unsubst_ty()))
713                     .collect(),
714              "variant")
715         }
716         ty::TyStruct(struct_def, expected_substs) => {
717             let variant = struct_def.struct_variant();
718             if is_tuple_struct_pat && variant.kind() != ty::VariantKind::Tuple {
719                 report_bad_struct_kind(false);
720                 return;
721             }
722             (variant.fields
723                     .iter()
724                     .map(|f| fcx.instantiate_type_scheme(pat.span,
725                                                          expected_substs,
726                                                          &f.unsubst_ty()))
727                     .collect(),
728              "struct")
729         }
730         _ => {
731             report_bad_struct_kind(false);
732             return;
733         }
734     };
735
736     if let Some(subpats) = subpats {
737         if subpats.len() == arg_tys.len() {
738             for (subpat, arg_ty) in subpats.iter().zip(arg_tys) {
739                 check_pat(pcx, &**subpat, arg_ty);
740             }
741         } else if arg_tys.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                       arg_tys.len(), if arg_tys.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                 span_err!(tcx.sess, span, E0025,
790                     "field `{}` bound multiple times in the pattern",
791                     field.name);
792                 span_note!(tcx.sess, *occupied.get(),
793                     "field `{}` previously bound here",
794                     field.name);
795                 tcx.types.err
796             }
797             Vacant(vacant) => {
798                 vacant.insert(span);
799                 field_map.get(&field.name)
800                     .map(|f| pcx.fcx.field_ty(span, f, substs))
801                     .unwrap_or_else(|| {
802                         span_err!(tcx.sess, span, E0026,
803                             "struct `{}` does not have a field named `{}`",
804                             tcx.item_path_str(variant.did),
805                             field.name);
806                         tcx.types.err
807                     })
808             }
809         };
810
811         check_pat(pcx, &*field.pat, field_ty);
812     }
813
814     // Report an error if not all the fields were specified.
815     if !etc {
816         for field in variant.fields
817             .iter()
818             .filter(|field| !used_fields.contains_key(&field.name)) {
819             span_err!(tcx.sess, span, E0027,
820                 "pattern does not mention field `{}`",
821                 field.name);
822         }
823     }
824 }