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.
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.
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;
26 use std::collections::hash_map::Entry::{Occupied, Vacant};
28 use syntax::codemap::{Span, Spanned};
32 use rustc_front::print::pprust;
33 use rustc_front::util as hir_util;
35 pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
40 let tcx = pcx.fcx.ccx.tcx;
42 debug!("check_pat(pat={:?},expected={:?})",
48 fcx.write_ty(pat.id, expected);
50 hir::PatLit(ref lt) => {
51 check_expr(fcx, &**lt);
52 let expr_ty = fcx.expr_ty(&**lt);
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))
69 fcx.write_ty(pat.id, pat_ty);
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
80 // &'static str <: expected
82 // that's equivalent to there existing a LUB.
83 demand::suptype(fcx, pat.span, expected, pat_ty);
85 hir::PatRange(ref begin, ref end) => {
86 check_expr(fcx, begin);
89 let lhs_ty = fcx.expr_ty(begin);
90 let rhs_ty = fcx.expr_ty(end);
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);
97 if !lhs_compat || !rhs_compat {
98 let span = if !lhs_compat && !rhs_compat {
100 } else if !lhs_compat {
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)
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()
122 // It's ok to return without a message as `require_same_types` prints an error.
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);
131 fcx.write_ty(pat.id, common_type);
133 // subtyping doesn't matter here, as the value is some kind of scalar
134 demand::eqtype(fcx, pat.span, expected, lhs_ty);
136 hir::PatEnum(..) | hir::PatIdent(..) if pat_is_resolved_const(&tcx.def_map, pat) => {
137 let const_did = tcx.def_map.borrow().get(&pat.id).unwrap().def_id();
138 let const_scheme = tcx.lookup_item_type(const_did);
139 assert!(const_scheme.generics.is_empty());
140 let const_ty = pcx.fcx.instantiate_type_scheme(pat.span,
143 fcx.write_ty(pat.id, const_ty);
145 // FIXME(#20489) -- we should limit the types here to scalars or something!
147 // As with PatLit, what we really want here is that there
148 // exist a LUB, but for the cases that can occur, subtype
150 demand::suptype(fcx, pat.span, expected, const_ty);
152 hir::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map, pat) => {
153 let typ = fcx.local_ty(pat.span, pat.id);
155 hir::BindByRef(mutbl) => {
156 // if the binding is like
157 // ref x | ref const x | ref mut x
158 // then `x` is assigned a value of type `&M T` where M is the mutability
159 // and T is the expected type.
160 let region_var = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
161 let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
162 let region_ty = tcx.mk_ref(tcx.mk_region(region_var), mt);
164 // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
165 // required. However, we use equality, which is stronger. See (*) for
167 demand::eqtype(fcx, pat.span, region_ty, typ);
169 // otherwise the type of x is the expected type T
170 hir::BindByValue(_) => {
171 // As above, `T <: typeof(x)` is required but we
172 // use equality, see (*) below.
173 demand::eqtype(fcx, pat.span, expected, typ);
177 fcx.write_ty(pat.id, typ);
179 // if there are multiple arms, make sure they all agree on
180 // what the type of the binding `x` ought to be
181 let canon_id = *pcx.map.get(&path.node.name).unwrap();
182 if canon_id != pat.id {
183 let ct = fcx.local_ty(pat.span, canon_id);
184 demand::eqtype(fcx, pat.span, ct, typ);
187 if let Some(ref p) = *sub {
188 check_pat(pcx, &**p, expected);
191 hir::PatIdent(_, ref path, _) => {
192 let path = hir_util::ident_to_path(path.span, path.node);
193 check_pat_enum(pcx, pat, &path, Some(&[]), expected);
195 hir::PatEnum(ref path, ref subpats) => {
196 let subpats = subpats.as_ref().map(|v| &v[..]);
197 check_pat_enum(pcx, pat, path, subpats, expected);
199 hir::PatQPath(ref qself, ref path) => {
200 let self_ty = fcx.to_ty(&qself.ty);
201 let path_res = if let Some(&d) = tcx.def_map.borrow().get(&pat.id) {
203 } else if qself.position == 0 {
204 // This is just a sentinel for finish_resolving_def_to_ty.
205 let sentinel = fcx.tcx().map.local_def_id(ast::CRATE_NODE_ID);
206 def::PathResolution {
207 base_def: def::DefMod(sentinel),
208 last_private: LastMod(AllPublic),
209 depth: path.segments.len()
212 tcx.sess.span_bug(pat.span,
213 &format!("unbound path {:?}", pat))
215 if let Some((opt_ty, segments, def)) =
216 resolve_ty_and_def_ufcs(fcx, path_res, Some(self_ty),
217 path, pat.span, pat.id) {
218 if check_assoc_item_is_const(pcx, def, pat.span) {
219 let scheme = tcx.lookup_item_type(def.def_id());
220 let predicates = tcx.lookup_predicates(def.def_id());
221 instantiate_path(fcx, segments,
223 opt_ty, def, pat.span, pat.id);
224 let const_ty = fcx.node_ty(pat.id);
225 demand::suptype(fcx, pat.span, expected, const_ty);
227 fcx.write_error(pat.id)
231 hir::PatStruct(ref path, ref fields, etc) => {
232 check_pat_struct(pcx, pat, path, fields, etc, expected);
234 hir::PatTup(ref elements) => {
235 let element_tys: Vec<_> =
236 (0..elements.len()).map(|_| fcx.infcx().next_ty_var())
238 let pat_ty = tcx.mk_tup(element_tys.clone());
239 fcx.write_ty(pat.id, pat_ty);
240 demand::eqtype(fcx, pat.span, expected, pat_ty);
241 for (element_pat, element_ty) in elements.iter().zip(element_tys) {
242 check_pat(pcx, &**element_pat, element_ty);
245 hir::PatBox(ref inner) => {
246 let inner_ty = fcx.infcx().next_ty_var();
247 let uniq_ty = tcx.mk_box(inner_ty);
249 if check_dereferencable(pcx, pat.span, expected, &**inner) {
250 // Here, `demand::subtype` is good enough, but I don't
251 // think any errors can be introduced by using
253 demand::eqtype(fcx, pat.span, expected, uniq_ty);
254 fcx.write_ty(pat.id, uniq_ty);
255 check_pat(pcx, &**inner, inner_ty);
257 fcx.write_error(pat.id);
258 check_pat(pcx, &**inner, tcx.types.err);
261 hir::PatRegion(ref inner, mutbl) => {
262 let expected = fcx.infcx().shallow_resolve(expected);
263 if check_dereferencable(pcx, pat.span, expected, &**inner) {
264 // `demand::subtype` would be good enough, but using
265 // `eqtype` turns out to be equally general. See (*)
266 // below for details.
268 // Take region, inner-type from expected type if we
269 // can, to avoid creating needless variables. This
270 // also helps with the bad interactions of the given
271 // hack detailed in (*) below.
272 let (rptr_ty, inner_ty) = match expected.sty {
273 ty::TyRef(_, mt) if mt.mutbl == mutbl => {
277 let inner_ty = fcx.infcx().next_ty_var();
278 let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
279 let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
280 let rptr_ty = tcx.mk_ref(tcx.mk_region(region), mt);
281 demand::eqtype(fcx, pat.span, expected, rptr_ty);
286 fcx.write_ty(pat.id, rptr_ty);
287 check_pat(pcx, &**inner, inner_ty);
289 fcx.write_error(pat.id);
290 check_pat(pcx, &**inner, tcx.types.err);
293 hir::PatVec(ref before, ref slice, ref after) => {
294 let expected_ty = structurally_resolved_type(fcx, pat.span, expected);
295 let inner_ty = fcx.infcx().next_ty_var();
296 let pat_ty = match expected_ty.sty {
297 ty::TyArray(_, size) => tcx.mk_array(inner_ty, {
298 let min_len = before.len() + after.len();
300 Some(_) => cmp::max(min_len, size),
305 let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
306 tcx.mk_ref(tcx.mk_region(region), ty::TypeAndMut {
307 ty: tcx.mk_slice(inner_ty),
308 mutbl: expected_ty.builtin_deref(true, ty::NoPreference).map(|mt| mt.mutbl)
309 .unwrap_or(hir::MutImmutable)
314 fcx.write_ty(pat.id, pat_ty);
316 // `demand::subtype` would be good enough, but using
317 // `eqtype` turns out to be equally general. See (*)
318 // below for details.
319 demand::eqtype(fcx, pat.span, expected, pat_ty);
322 check_pat(pcx, &**elt, inner_ty);
324 if let Some(ref slice) = *slice {
325 let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
326 let mutbl = expected_ty.builtin_deref(true, ty::NoPreference)
327 .map_or(hir::MutImmutable, |mt| mt.mutbl);
329 let slice_ty = tcx.mk_ref(tcx.mk_region(region), ty::TypeAndMut {
330 ty: tcx.mk_slice(inner_ty),
333 check_pat(pcx, &**slice, slice_ty);
336 check_pat(pcx, &**elt, inner_ty);
342 // (*) In most of the cases above (literals and constants being
343 // the exception), we relate types using strict equality, evewn
344 // though subtyping would be sufficient. There are a few reasons
345 // for this, some of which are fairly subtle and which cost me
346 // (nmatsakis) an hour or two debugging to remember, so I thought
347 // I'd write them down this time.
349 // 1. There is no loss of expressiveness here, though it does
350 // cause some inconvenience. What we are saying is that the type
351 // of `x` becomes *exactly* what is expected. This can cause unnecessary
352 // errors in some cases, such as this one:
353 // it will cause errors in a case like this:
356 // fn foo<'x>(x: &'x int) {
363 // The reason we might get an error is that `z` might be
364 // assigned a type like `&'x int`, and then we would have
365 // a problem when we try to assign `&a` to `z`, because
366 // the lifetime of `&a` (i.e., the enclosing block) is
367 // shorter than `'x`.
369 // HOWEVER, this code works fine. The reason is that the
370 // expected type here is whatever type the user wrote, not
371 // the initializer's type. In this case the user wrote
372 // nothing, so we are going to create a type variable `Z`.
373 // Then we will assign the type of the initializer (`&'x
374 // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
375 // will instantiate `Z` as a type `&'0 int` where `'0` is
376 // a fresh region variable, with the constraint that `'x :
377 // '0`. So basically we're all set.
379 // Note that there are two tests to check that this remains true
380 // (`regions-reassign-{match,let}-bound-pointer.rs`).
382 // 2. Things go horribly wrong if we use subtype. The reason for
383 // THIS is a fairly subtle case involving bound regions. See the
384 // `givens` field in `region_inference`, as well as the test
385 // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
386 // for details. Short version is that we must sometimes detect
387 // relationships between specific region variables and regions
388 // bound in a closure signature, and that detection gets thrown
389 // off when we substitute fresh region variables here to enable
393 fn check_assoc_item_is_const(pcx: &pat_ctxt, def: def::Def, span: Span) -> bool {
395 def::DefAssociatedConst(..) => true,
396 def::DefMethod(..) => {
397 span_err!(pcx.fcx.ccx.tcx.sess, span, E0327,
398 "associated items in match patterns must be constants");
402 pcx.fcx.ccx.tcx.sess.span_bug(span, "non-associated item in
403 check_assoc_item_is_const");
408 pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
409 span: Span, expected: Ty<'tcx>,
410 inner: &hir::Pat) -> bool {
412 let tcx = pcx.fcx.ccx.tcx;
413 if pat_is_binding(&tcx.def_map, inner) {
414 let expected = fcx.infcx().shallow_resolve(expected);
415 expected.builtin_deref(true, ty::NoPreference).map_or(true, |mt| match mt.ty.sty {
417 // This is "x = SomeTrait" being reduced from
418 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
419 span_err!(tcx.sess, span, E0033,
420 "type `{}` cannot be dereferenced",
421 fcx.infcx().ty_to_string(expected));
431 pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
432 expr: &'tcx hir::Expr,
433 discrim: &'tcx hir::Expr,
434 arms: &'tcx [hir::Arm],
435 expected: Expectation<'tcx>,
436 match_src: hir::MatchSource) {
437 let tcx = fcx.ccx.tcx;
439 // Not entirely obvious: if matches may create ref bindings, we
440 // want to use the *precise* type of the discriminant, *not* some
441 // supertype, as the "discriminant type" (issue #23116).
442 let contains_ref_bindings = arms.iter()
443 .filter_map(|a| tcx.arm_contains_ref_binding(a))
444 .max_by(|m| match *m {
445 hir::MutMutable => 1,
446 hir::MutImmutable => 0,
449 if let Some(m) = contains_ref_bindings {
450 check_expr_with_lvalue_pref(fcx, discrim, LvaluePreference::from_mutbl(m));
451 discrim_ty = fcx.expr_ty(discrim);
453 // ...but otherwise we want to use any supertype of the
454 // discriminant. This is sort of a workaround, see note (*) in
455 // `check_pat` for some details.
456 discrim_ty = fcx.infcx().next_ty_var();
457 check_expr_has_type(fcx, discrim, discrim_ty);
460 // Typecheck the patterns first, so that we get types for all the
463 let mut pcx = pat_ctxt {
465 map: pat_id_map(&tcx.def_map, &*arm.pats[0]),
468 check_pat(&mut pcx, &**p, discrim_ty);
472 // Now typecheck the blocks.
474 // The result of the match is the common supertype of all the
475 // arms. Start out the value as bottom, since it's the, well,
476 // bottom the type lattice, and we'll be moving up the lattice as
477 // we process each arm. (Note that any match with 0 arms is matching
478 // on any empty type and is therefore unreachable; should the flow
479 // of execution reach it, we will panic, so bottom is an appropriate
480 // type in that case)
481 let expected = expected.adjust_for_branches(fcx);
482 let result_ty = arms.iter().fold(fcx.infcx().next_diverging_ty_var(), |result_ty, arm| {
483 let bty = match expected {
484 // We don't coerce to `()` so that if the match expression is a
485 // statement it's branches can have any consistent type. That allows
486 // us to give better error messages (pointing to a usually better
487 // arm for inconsistent arms or to the whole match when a `()` type
489 Expectation::ExpectHasType(ety) if ety != fcx.tcx().mk_nil() => {
490 check_expr_coercable_to_type(fcx, &*arm.body, ety);
494 check_expr_with_expectation(fcx, &*arm.body, expected);
495 fcx.node_ty(arm.body.id)
499 if let Some(ref e) = arm.guard {
500 check_expr_has_type(fcx, &**e, tcx.types.bool);
503 if result_ty.references_error() || bty.references_error() {
506 let (origin, expected, found) = match match_src {
507 /* if-let construct without an else block */
508 hir::MatchSource::IfLetDesugar { contains_else_clause }
509 if !contains_else_clause => (
510 infer::IfExpressionWithNoElse(expr.span),
515 infer::MatchExpressionArm(expr.span, arm.body.span, match_src),
521 infer::common_supertype(
531 fcx.write_ty(expr.id, result_ty);
534 pub struct pat_ctxt<'a, 'tcx: 'a> {
535 pub fcx: &'a FnCtxt<'a, 'tcx>,
539 pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx hir::Pat,
540 path: &hir::Path, fields: &'tcx [Spanned<hir::FieldPat>],
541 etc: bool, expected: Ty<'tcx>) {
543 let tcx = pcx.fcx.ccx.tcx;
545 let def = tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
546 let variant = match fcx.def_struct_variant(def, path.span) {
547 Some((_, variant)) => variant,
549 let name = pprust::path_to_string(path);
550 span_err!(tcx.sess, pat.span, E0163,
551 "`{}` does not name a struct or a struct variant", name);
552 fcx.write_error(pat.id);
554 for field in fields {
555 check_pat(pcx, &field.node.pat, tcx.types.err);
561 let pat_ty = pcx.fcx.instantiate_type(def.def_id(), path);
562 let item_substs = match pat_ty.sty {
563 ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
564 _ => tcx.sess.span_bug(pat.span, "struct variant is not an ADT")
566 demand::eqtype(fcx, pat.span, expected, pat_ty);
567 check_struct_pat_fields(pcx, pat.span, fields, variant, &item_substs, etc);
569 fcx.write_ty(pat.id, pat_ty);
570 fcx.write_substs(pat.id, ty::ItemSubsts { substs: item_substs.clone() });
573 pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
576 subpats: Option<&'tcx [P<hir::Pat>]>,
579 // Typecheck the path.
581 let tcx = pcx.fcx.ccx.tcx;
583 let path_res = *tcx.def_map.borrow().get(&pat.id).unwrap();
585 let (opt_ty, segments, def) = match resolve_ty_and_def_ufcs(fcx, path_res,
588 Some(resolution) => resolution,
589 // Error handling done inside resolve_ty_and_def_ufcs, so if
590 // resolution fails just return.
594 // Items that were partially resolved before should have been resolved to
595 // associated constants (i.e. not methods).
596 if path_res.depth != 0 && !check_assoc_item_is_const(pcx, def, pat.span) {
597 fcx.write_error(pat.id);
601 let enum_def = def.variant_def_ids()
602 .map_or_else(|| def.def_id(), |(enum_def, _)| enum_def);
604 let ctor_scheme = tcx.lookup_item_type(enum_def);
605 let ctor_predicates = tcx.lookup_predicates(enum_def);
606 let path_scheme = if ctor_scheme.ty.is_fn() {
607 let fn_ret = tcx.no_late_bound_regions(&ctor_scheme.ty.fn_ret()).unwrap();
610 generics: ctor_scheme.generics,
615 instantiate_path(pcx.fcx, segments,
616 path_scheme, &ctor_predicates,
617 opt_ty, def, pat.span, pat.id);
619 // If we didn't have a fully resolved path to start with, we had an
620 // associated const, and we should quit now, since the rest of this
621 // function uses checks specific to structs and enums.
622 if path_res.depth != 0 {
623 let pat_ty = fcx.node_ty(pat.id);
624 demand::suptype(fcx, pat.span, expected, pat_ty);
628 let pat_ty = fcx.node_ty(pat.id);
629 demand::eqtype(fcx, pat.span, expected, pat_ty);
632 let real_path_ty = fcx.node_ty(pat.id);
633 let (arg_tys, kind_name): (Vec<_>, &'static str) = match real_path_ty.sty {
634 ty::TyEnum(enum_def, expected_substs)
635 if def == def::DefVariant(enum_def.did, def.def_id(), false) =>
637 let variant = enum_def.variant_of_def(def);
640 .map(|f| fcx.instantiate_type_scheme(pat.span,
646 ty::TyStruct(struct_def, expected_substs) => {
647 (struct_def.struct_variant()
650 .map(|f| fcx.instantiate_type_scheme(pat.span,
657 let name = pprust::path_to_string(path);
658 span_err!(tcx.sess, pat.span, E0164,
659 "`{}` does not name a non-struct variant or a tuple struct", name);
660 fcx.write_error(pat.id);
662 if let Some(subpats) = subpats {
664 check_pat(pcx, &**pat, tcx.types.err);
671 if let Some(subpats) = subpats {
672 if subpats.len() == arg_tys.len() {
673 for (subpat, arg_ty) in subpats.iter().zip(arg_tys) {
674 check_pat(pcx, &**subpat, arg_ty);
676 } else if arg_tys.is_empty() {
677 span_err!(tcx.sess, pat.span, E0024,
678 "this pattern has {} field{}, but the corresponding {} has no fields",
679 subpats.len(), if subpats.len() == 1 {""} else {"s"}, kind_name);
682 check_pat(pcx, &**pat, tcx.types.err);
685 span_err!(tcx.sess, pat.span, E0023,
686 "this pattern has {} field{}, but the corresponding {} has {} field{}",
687 subpats.len(), if subpats.len() == 1 {""} else {"s"},
689 arg_tys.len(), if arg_tys.len() == 1 {""} else {"s"});
692 check_pat(pcx, &**pat, tcx.types.err);
698 /// `path` is the AST path item naming the type of this struct.
699 /// `fields` is the field patterns of the struct pattern.
700 /// `struct_fields` describes the type of each field of the struct.
701 /// `struct_id` is the ID of the struct.
702 /// `etc` is true if the pattern said '...' and false otherwise.
703 pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
705 fields: &'tcx [Spanned<hir::FieldPat>],
706 variant: ty::VariantDef<'tcx>,
707 substs: &Substs<'tcx>,
709 let tcx = pcx.fcx.ccx.tcx;
711 // Index the struct fields' types.
712 let field_map = variant.fields
714 .map(|field| (field.name, field))
715 .collect::<FnvHashMap<_, _>>();
717 // Keep track of which fields have already appeared in the pattern.
718 let mut used_fields = FnvHashMap();
720 // Typecheck each field.
721 for &Spanned { node: ref field, span } in fields {
722 let field_ty = match used_fields.entry(field.name) {
723 Occupied(occupied) => {
724 span_err!(tcx.sess, span, E0025,
725 "field `{}` bound multiple times in the pattern",
727 span_note!(tcx.sess, *occupied.get(),
728 "field `{}` previously bound here",
734 field_map.get(&field.name)
735 .map(|f| pcx.fcx.field_ty(span, f, substs))
737 span_err!(tcx.sess, span, E0026,
738 "struct `{}` does not have a field named `{}`",
739 tcx.item_path_str(variant.did),
746 check_pat(pcx, &*field.pat, field_ty);
749 // Report an error if not all the fields were specified.
751 for field in variant.fields
753 .filter(|field| !used_fields.contains_key(&field.name)) {
754 span_err!(tcx.sess, span, E0027,
755 "pattern does not mention field `{}`",