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