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