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.
11 use rustc::hir::{self, PatKind};
12 use rustc::hir::def::{Def, CtorKind};
13 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
15 use rustc::infer::type_variable::TypeVariableOrigin;
16 use rustc::traits::ObligationCauseCode;
17 use rustc::ty::{self, Ty, TypeFoldable};
18 use check::{FnCtxt, Expectation, Diverges, Needs};
19 use check::coercion::CoerceMany;
20 use util::nodemap::FxHashMap;
22 use std::collections::hash_map::Entry::{Occupied, Vacant};
25 use syntax::source_map::Spanned;
29 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
30 /// The `is_arg` argument indicates whether this pattern is the
31 /// *outermost* pattern in an argument (e.g., in `fn foo(&x:
32 /// &u32)`, it is true for the `&x` pattern but not `x`). This is
33 /// used to tailor error reporting.
34 pub fn check_pat_walk(
37 mut expected: Ty<'tcx>,
38 mut def_bm: ty::BindingMode,
43 debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?},is_arg={})",
44 pat, expected, def_bm, is_arg);
46 let is_non_ref_pat = match pat.node {
48 PatKind::TupleStruct(..) |
52 PatKind::Slice(..) => true,
53 PatKind::Lit(ref lt) => {
54 let ty = self.check_expr(lt);
60 PatKind::Path(ref qpath) => {
61 let (def, _, _) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
63 Def::Const(..) | Def::AssociatedConst(..) => false,
68 PatKind::Binding(..) |
69 PatKind::Ref(..) => false,
72 debug!("pattern is non reference pattern");
73 let mut exp_ty = self.resolve_type_vars_with_obligations(&expected);
75 // Peel off as many `&` or `&mut` from the discriminant as possible. For example,
76 // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
77 // the `Some(5)` which is not of type Ref.
79 // For each ampersand peeled off, update the binding mode and push the original
80 // type into the adjustments vector.
82 // See the examples in `run-pass/match-defbm*.rs`.
83 let mut pat_adjustments = vec![];
85 debug!("inspecting {:?} with type {:?}", exp_ty, exp_ty.sty);
87 ty::Ref(_, inner_ty, inner_mutability) => {
88 debug!("current discriminant is Ref, inserting implicit deref");
89 // Preserve the reference type. We'll need it later during HAIR lowering.
90 pat_adjustments.push(exp_ty);
93 def_bm = match def_bm {
94 // If default binding mode is by value, make it `ref` or `ref mut`
95 // (depending on whether we observe `&` or `&mut`).
97 ty::BindByReference(inner_mutability),
99 // Once a `ref`, always a `ref`. This is because a `& &mut` can't mutate
100 // the underlying value.
101 ty::BindByReference(hir::Mutability::MutImmutable) =>
102 ty::BindByReference(hir::Mutability::MutImmutable),
104 // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref`
106 ty::BindByReference(hir::Mutability::MutMutable) =>
107 ty::BindByReference(inner_mutability),
113 if pat_adjustments.len() > 0 {
114 debug!("default binding mode is now {:?}", def_bm);
115 self.inh.tables.borrow_mut()
116 .pat_adjustments_mut()
117 .insert(pat.hir_id, pat_adjustments);
119 } else if let PatKind::Ref(..) = pat.node {
120 // When you encounter a `&pat` pattern, reset to "by
121 // value". This is so that `x` and `y` here are by value,
122 // as they appear to be:
125 // match &(&22, &44) {
131 def_bm = ty::BindByValue(hir::MutImmutable);
134 // Lose mutability now that we know binding mode and discriminant type.
136 let expected = expected;
138 let ty = match pat.node {
142 PatKind::Lit(ref lt) => {
143 // We've already computed the type above (when checking for a non-ref pat), so
144 // avoid computing it again.
145 let ty = self.node_ty(lt.hir_id);
147 // Byte string patterns behave the same way as array patterns
148 // They can denote both statically and dynamically sized byte arrays
150 if let hir::ExprKind::Lit(ref lt) = lt.node {
151 if let ast::LitKind::ByteStr(_) = lt.node {
152 let expected_ty = self.structurally_resolved_type(pat.span, expected);
153 if let ty::Ref(_, r_ty, _) = expected_ty.sty {
154 if let ty::Slice(_) = r_ty.sty {
155 pat_ty = tcx.mk_imm_ref(tcx.types.re_static,
156 tcx.mk_slice(tcx.types.u8))
162 // somewhat surprising: in this case, the subtyping
163 // relation goes the opposite way as the other
164 // cases. Actually what we really want is not a subtyping
165 // relation at all but rather that there exists a LUB (so
166 // that they can be compared). However, in practice,
167 // constants are always scalars or strings. For scalars
168 // subtyping is irrelevant, and for strings `ty` is
169 // type is `&'static str`, so if we say that
171 // &'static str <: expected
173 // that's equivalent to there existing a LUB.
174 self.demand_suptype(pat.span, expected, pat_ty);
177 PatKind::Range(ref begin, ref end, _) => {
178 let lhs_ty = self.check_expr(begin);
179 let rhs_ty = self.check_expr(end);
181 // Check that both end-points are of numeric or char type.
182 let numeric_or_char = |ty: Ty| ty.is_numeric() || ty.is_char();
183 let lhs_compat = numeric_or_char(lhs_ty);
184 let rhs_compat = numeric_or_char(rhs_ty);
186 if !lhs_compat || !rhs_compat {
187 let span = if !lhs_compat && !rhs_compat {
189 } else if !lhs_compat {
195 let mut err = struct_span_err!(
199 "only char and numeric types are allowed in range patterns"
201 err.span_label(span, "ranges require char or numeric types");
202 err.note(&format!("start type: {}", self.ty_to_string(lhs_ty)));
203 err.note(&format!("end type: {}", self.ty_to_string(rhs_ty)));
204 if tcx.sess.teach(&err.get_code().unwrap()) {
206 "In a match expression, only numbers and characters can be matched \
207 against a range. This is because the compiler checks that the range \
208 is non-empty at compile-time, and is unable to evaluate arbitrary \
209 comparison functions. If you want to capture values of an orderable \
210 type between two end-points, you can use a guard."
217 // Now that we know the types can be unified we find the unified type and use
218 // it to type the entire expression.
219 let common_type = self.resolve_type_vars_if_possible(&lhs_ty);
221 // subtyping doesn't matter here, as the value is some kind of scalar
222 self.demand_eqtype(pat.span, expected, lhs_ty);
223 self.demand_eqtype(pat.span, expected, rhs_ty);
226 PatKind::Binding(ba, var_id, _, ref sub) => {
227 let bm = if ba == hir::BindingAnnotation::Unannotated {
230 ty::BindingMode::convert(ba)
235 .pat_binding_modes_mut()
236 .insert(pat.hir_id, bm);
237 debug!("check_pat_walk: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
238 let typ = self.local_ty(pat.span, pat.id);
240 ty::BindByReference(mutbl) => {
241 // if the binding is like
242 // ref x | ref const x | ref mut x
243 // then `x` is assigned a value of type `&M T` where M is the mutability
244 // and T is the expected type.
245 let region_var = self.next_region_var(infer::PatternRegion(pat.span));
246 let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
247 let region_ty = tcx.mk_ref(region_var, mt);
249 // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
250 // required. However, we use equality, which is stronger. See (*) for
252 self.demand_eqtype(pat.span, region_ty, typ);
254 // otherwise the type of x is the expected type T
255 ty::BindByValue(_) => {
256 // As above, `T <: typeof(x)` is required but we
257 // use equality, see (*) below.
258 self.demand_eqtype(pat.span, expected, typ);
262 // if there are multiple arms, make sure they all agree on
263 // what the type of the binding `x` ought to be
264 if var_id != pat.id {
265 let vt = self.local_ty(pat.span, var_id);
266 self.demand_eqtype(pat.span, vt, typ);
269 if let Some(ref p) = *sub {
270 self.check_pat_walk(&p, expected, def_bm, true);
275 PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
276 self.check_pat_tuple_struct(pat, qpath, &subpats, ddpos, expected, def_bm)
278 PatKind::Path(ref qpath) => {
279 self.check_pat_path(pat, qpath, expected)
281 PatKind::Struct(ref qpath, ref fields, etc) => {
282 self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm)
284 PatKind::Tuple(ref elements, ddpos) => {
285 let mut expected_len = elements.len();
287 // Require known type only when `..` is present
288 if let ty::Tuple(ref tys) =
289 self.structurally_resolved_type(pat.span, expected).sty {
290 expected_len = tys.len();
293 let max_len = cmp::max(expected_len, elements.len());
295 let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(
296 // FIXME: MiscVariable for now, obtaining the span and name information
297 // from all tuple elements isn't trivial.
298 TypeVariableOrigin::TypeInference(pat.span)));
299 let element_tys = tcx.mk_type_list(element_tys_iter);
300 let pat_ty = tcx.mk_ty(ty::Tuple(element_tys));
301 self.demand_eqtype(pat.span, expected, pat_ty);
302 for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
303 self.check_pat_walk(elem, &element_tys[i], def_bm, true);
307 PatKind::Box(ref inner) => {
308 let inner_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(inner.span));
309 let uniq_ty = tcx.mk_box(inner_ty);
311 if self.check_dereferencable(pat.span, expected, &inner) {
312 // Here, `demand::subtype` is good enough, but I don't
313 // think any errors can be introduced by using
315 self.demand_eqtype(pat.span, expected, uniq_ty);
316 self.check_pat_walk(&inner, inner_ty, def_bm, true);
319 self.check_pat_walk(&inner, tcx.types.err, def_bm, true);
323 PatKind::Ref(ref inner, mutbl) => {
324 let expected = self.shallow_resolve(expected);
325 if self.check_dereferencable(pat.span, expected, &inner) {
326 // `demand::subtype` would be good enough, but using
327 // `eqtype` turns out to be equally general. See (*)
328 // below for details.
330 // Take region, inner-type from expected type if we
331 // can, to avoid creating needless variables. This
332 // also helps with the bad interactions of the given
333 // hack detailed in (*) below.
334 debug!("check_pat_walk: expected={:?}", expected);
335 let (rptr_ty, inner_ty) = match expected.sty {
336 ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => {
340 let inner_ty = self.next_ty_var(
341 TypeVariableOrigin::TypeInference(inner.span));
342 let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
343 let region = self.next_region_var(infer::PatternRegion(pat.span));
344 let rptr_ty = tcx.mk_ref(region, mt);
345 debug!("check_pat_walk: demanding {:?} = {:?}", expected, rptr_ty);
346 let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
348 // Look for a case like `fn foo(&foo: u32)` and suggest
349 // `fn foo(foo: &u32)`
350 if let Some(mut err) = err {
352 if let PatKind::Binding(..) = inner.node {
353 if let Ok(snippet) = tcx.sess.source_map()
354 .span_to_snippet(pat.span)
356 err.help(&format!("did you mean `{}: &{}`?",
368 self.check_pat_walk(&inner, inner_ty, def_bm, true);
371 self.check_pat_walk(&inner, tcx.types.err, def_bm, true);
375 PatKind::Slice(ref before, ref slice, ref after) => {
376 let expected_ty = self.structurally_resolved_type(pat.span, expected);
377 let (inner_ty, slice_ty) = match expected_ty.sty {
378 ty::Array(inner_ty, size) => {
379 let size = size.unwrap_usize(tcx);
380 let min_len = before.len() as u64 + after.len() as u64;
384 tcx.sess, pat.span, E0527,
385 "pattern requires {} elements but array has {}",
387 .span_label(pat.span, format!("expected {} elements",size))
390 (inner_ty, tcx.types.err)
391 } else if let Some(rest) = size.checked_sub(min_len) {
392 (inner_ty, tcx.mk_array(inner_ty, rest))
394 struct_span_err!(tcx.sess, pat.span, E0528,
395 "pattern requires at least {} elements but array has {}",
397 .span_label(pat.span,
398 format!("pattern cannot match array of {} elements", size))
400 (inner_ty, tcx.types.err)
403 ty::Slice(inner_ty) => (inner_ty, expected_ty),
405 if !expected_ty.references_error() {
406 let mut err = struct_span_err!(
407 tcx.sess, pat.span, E0529,
408 "expected an array or slice, found `{}`",
410 if let ty::Ref(_, ty, _) = expected_ty.sty {
412 ty::Array(..) | ty::Slice(..) => {
413 err.help("the semantics of slice patterns changed \
414 recently; see issue #23121");
420 err.span_label( pat.span,
421 format!("pattern cannot match with input type `{}`", expected_ty)
424 (tcx.types.err, tcx.types.err)
429 self.check_pat_walk(&elt, inner_ty, def_bm, true);
431 if let Some(ref slice) = *slice {
432 self.check_pat_walk(&slice, slice_ty, def_bm, true);
435 self.check_pat_walk(&elt, inner_ty, def_bm, true);
441 self.write_ty(pat.hir_id, ty);
443 // (*) In most of the cases above (literals and constants being
444 // the exception), we relate types using strict equality, even
445 // though subtyping would be sufficient. There are a few reasons
446 // for this, some of which are fairly subtle and which cost me
447 // (nmatsakis) an hour or two debugging to remember, so I thought
448 // I'd write them down this time.
450 // 1. There is no loss of expressiveness here, though it does
451 // cause some inconvenience. What we are saying is that the type
452 // of `x` becomes *exactly* what is expected. This can cause unnecessary
453 // errors in some cases, such as this one:
456 // fn foo<'x>(x: &'x int) {
463 // The reason we might get an error is that `z` might be
464 // assigned a type like `&'x int`, and then we would have
465 // a problem when we try to assign `&a` to `z`, because
466 // the lifetime of `&a` (i.e., the enclosing block) is
467 // shorter than `'x`.
469 // HOWEVER, this code works fine. The reason is that the
470 // expected type here is whatever type the user wrote, not
471 // the initializer's type. In this case the user wrote
472 // nothing, so we are going to create a type variable `Z`.
473 // Then we will assign the type of the initializer (`&'x
474 // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
475 // will instantiate `Z` as a type `&'0 int` where `'0` is
476 // a fresh region variable, with the constraint that `'x :
477 // '0`. So basically we're all set.
479 // Note that there are two tests to check that this remains true
480 // (`regions-reassign-{match,let}-bound-pointer.rs`).
482 // 2. Things go horribly wrong if we use subtype. The reason for
483 // THIS is a fairly subtle case involving bound regions. See the
484 // `givens` field in `region_constraints`, as well as the test
485 // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
486 // for details. Short version is that we must sometimes detect
487 // relationships between specific region variables and regions
488 // bound in a closure signature, and that detection gets thrown
489 // off when we substitute fresh region variables here to enable
493 pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
494 if let PatKind::Binding(..) = inner.node {
495 if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) {
496 if let ty::Dynamic(..) = mt.ty.sty {
497 // This is "x = SomeTrait" being reduced from
498 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
499 let type_str = self.ty_to_string(expected);
500 let mut err = struct_span_err!(
504 "type `{}` cannot be dereferenced",
507 err.span_label(span, format!("type `{}` cannot be dereferenced", type_str));
508 if self.tcx.sess.teach(&err.get_code().unwrap()) {
510 This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \
511 pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \
512 this type has no compile-time size. Therefore, all accesses to trait types must be through \
513 pointers. If you encounter this error you should try to avoid dereferencing the pointer.
515 You can read more about trait objects in the Trait Objects section of the Reference: \
516 https://doc.rust-lang.org/reference/types.html#trait-objects");
526 pub fn check_match(&self,
527 expr: &'gcx hir::Expr,
528 discrim: &'gcx hir::Expr,
529 arms: &'gcx [hir::Arm],
530 expected: Expectation<'tcx>,
531 match_src: hir::MatchSource) -> Ty<'tcx> {
534 // Not entirely obvious: if matches may create ref bindings, we want to
535 // use the *precise* type of the discriminant, *not* some supertype, as
536 // the "discriminant type" (issue #23116).
538 // arielb1 [writes here in this comment thread][c] that there
539 // is certainly *some* potential danger, e.g. for an example
542 // [c]: https://github.com/rust-lang/rust/pull/43399#discussion_r130223956
545 // let Foo(x) = f()[0];
548 // Then if the pattern matches by reference, we want to match
549 // `f()[0]` as a lexpr, so we can't allow it to be
550 // coerced. But if the pattern matches by value, `f()[0]` is
551 // still syntactically a lexpr, but we *do* want to allow
554 // However, *likely* we are ok with allowing coercions to
555 // happen if there are no explicit ref mut patterns - all
556 // implicit ref mut patterns must occur behind a reference, so
557 // they will have the "correct" variance and lifetime.
559 // This does mean that the following pattern would be legal:
564 // impl Deref for Foo {
565 // type Target = Bar;
566 // fn deref(&self) -> &Bar { &self.0 }
568 // impl DerefMut for Foo {
569 // fn deref_mut(&mut self) -> &mut Bar { &mut self.0 }
571 // fn foo(x: &mut Foo) {
573 // let Bar(z): &mut Bar = x;
576 // assert_eq!(foo.0.0, 42);
580 // FIXME(tschottdorf): don't call contains_explicit_ref_binding, which
581 // is problematic as the HIR is being scraped, but ref bindings may be
582 // implicit after #42640. We need to make sure that pat_adjustments
583 // (once introduced) is populated by the time we get here.
586 let contains_ref_bindings = arms.iter()
587 .filter_map(|a| a.contains_explicit_ref_binding())
588 .max_by_key(|m| match *m {
589 hir::MutMutable => 1,
590 hir::MutImmutable => 0,
593 if let Some(m) = contains_ref_bindings {
594 discrim_ty = self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m));
596 // ...but otherwise we want to use any supertype of the
597 // discriminant. This is sort of a workaround, see note (*) in
598 // `check_pat` for some details.
599 discrim_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(discrim.span));
600 self.check_expr_has_type_or_error(discrim, discrim_ty);
603 // If the discriminant diverges, the match is pointless (e.g.,
604 // `match (return) { }`).
605 self.warn_if_unreachable(expr.id, expr.span, "expression");
607 // If there are no arms, that is a diverging match; a special case.
609 self.diverges.set(self.diverges.get() | Diverges::Always);
610 return tcx.types.never;
613 // Otherwise, we have to union together the types that the
614 // arms produce and so forth.
616 let discrim_diverges = self.diverges.get();
617 self.diverges.set(Diverges::Maybe);
619 // Typecheck the patterns first, so that we get types for all the
621 let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| {
622 let mut all_pats_diverge = Diverges::WarnedAlways;
624 self.diverges.set(Diverges::Maybe);
625 self.check_pat_walk(&p, discrim_ty,
626 ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), true);
627 all_pats_diverge &= self.diverges.get();
630 // As discussed with @eddyb, this is for disabling unreachable_code
631 // warnings on patterns (they're now subsumed by unreachable_patterns
633 match all_pats_diverge {
634 Diverges::Maybe => Diverges::Maybe,
635 Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
639 // Now typecheck the blocks.
641 // The result of the match is the common supertype of all the
642 // arms. Start out the value as bottom, since it's the, well,
643 // bottom the type lattice, and we'll be moving up the lattice as
644 // we process each arm. (Note that any match with 0 arms is matching
645 // on any empty type and is therefore unreachable; should the flow
646 // of execution reach it, we will panic, so bottom is an appropriate
647 // type in that case)
648 let mut all_arms_diverge = Diverges::WarnedAlways;
650 let expected = expected.adjust_for_branches(self);
653 let coerce_first = match expected {
654 // We don't coerce to `()` so that if the match expression is a
655 // statement it's branches can have any consistent type. That allows
656 // us to give better error messages (pointing to a usually better
657 // arm for inconsistent arms or to the whole match when a `()` type
659 Expectation::ExpectHasType(ety) if ety != self.tcx.mk_nil() => ety,
660 _ => self.next_ty_var(TypeVariableOrigin::MiscVariable(expr.span)),
662 CoerceMany::with_coercion_sites(coerce_first, arms)
665 for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
666 if let Some(ref g) = arm.guard {
667 self.diverges.set(pats_diverge);
669 hir::Guard::If(e) => self.check_expr_has_type_or_error(e, tcx.types.bool),
673 self.diverges.set(pats_diverge);
674 let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
675 all_arms_diverge &= self.diverges.get();
677 // Handle the fallback arm of a desugared if-let like a missing else.
678 let is_if_let_fallback = match match_src {
679 hir::MatchSource::IfLetDesugar { contains_else_clause: false } => {
680 i == arms.len() - 1 && arm_ty.is_nil()
685 if is_if_let_fallback {
686 let cause = self.cause(expr.span, ObligationCauseCode::IfExpressionWithNoElse);
687 assert!(arm_ty.is_nil());
688 coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
690 let cause = self.cause(expr.span, ObligationCauseCode::MatchExpressionArm {
691 arm_span: arm.body.span,
694 coercion.coerce(self, &cause, &arm.body, arm_ty);
698 // We won't diverge unless the discriminant or all arms diverge.
699 self.diverges.set(discrim_diverges | all_arms_diverge);
701 coercion.complete(self)
704 fn check_pat_struct(&self,
707 fields: &'gcx [Spanned<hir::FieldPat>],
710 def_bm: ty::BindingMode) -> Ty<'tcx>
712 // Resolve the path and check the definition for errors.
713 let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.id) {
716 for field in fields {
717 self.check_pat_walk(&field.node.pat, self.tcx.types.err, def_bm, true);
719 return self.tcx.types.err;
722 // Type check the path.
723 self.demand_eqtype(pat.span, expected, pat_ty);
725 // Type check subpatterns.
726 if self.check_struct_pat_fields(pat_ty, pat.id, pat.span, variant, fields, etc, def_bm) {
733 fn check_pat_path(&self,
736 expected: Ty<'tcx>) -> Ty<'tcx>
739 let report_unexpected_def = |def: Def| {
740 span_err!(tcx.sess, pat.span, E0533,
741 "expected unit struct/variant or constant, found {} `{}`",
743 hir::print::to_string(&tcx.hir, |s| s.print_qpath(qpath, false)));
746 // Resolve the path and check the definition for errors.
747 let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
750 self.set_tainted_by_errors();
751 return tcx.types.err;
754 report_unexpected_def(def);
755 return tcx.types.err;
757 Def::VariantCtor(_, CtorKind::Const) |
758 Def::StructCtor(_, CtorKind::Const) |
759 Def::Const(..) | Def::AssociatedConst(..) => {} // OK
760 _ => bug!("unexpected pattern definition: {:?}", def)
763 // Type check the path.
764 let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
765 self.demand_suptype(pat.span, expected, pat_ty);
769 fn check_pat_tuple_struct(&self,
772 subpats: &'gcx [P<hir::Pat>],
773 ddpos: Option<usize>,
775 def_bm: ty::BindingMode) -> Ty<'tcx>
780 self.check_pat_walk(&pat, tcx.types.err, def_bm, true);
783 let report_unexpected_def = |def: Def| {
784 let msg = format!("expected tuple struct/variant, found {} `{}`",
786 hir::print::to_string(&tcx.hir, |s| s.print_qpath(qpath, false)));
787 struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg)
788 .span_label(pat.span, "not a tuple variant or struct").emit();
792 // Resolve the path and check the definition for errors.
793 let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
794 let variant = match def {
796 self.set_tainted_by_errors();
798 return tcx.types.err;
800 Def::AssociatedConst(..) | Def::Method(..) => {
801 report_unexpected_def(def);
802 return tcx.types.err;
804 Def::VariantCtor(_, CtorKind::Fn) |
805 Def::StructCtor(_, CtorKind::Fn) => {
806 tcx.expect_variant_def(def)
808 _ => bug!("unexpected pattern definition: {:?}", def)
811 // Type check the path.
812 let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
813 // Replace constructor type with constructed type for tuple struct patterns.
814 let pat_ty = pat_ty.fn_sig(tcx).output();
815 let pat_ty = pat_ty.no_late_bound_regions().expect("expected fn type");
817 self.demand_eqtype(pat.span, expected, pat_ty);
819 // Type check subpatterns.
820 if subpats.len() == variant.fields.len() ||
821 subpats.len() < variant.fields.len() && ddpos.is_some() {
822 let substs = match pat_ty.sty {
823 ty::Adt(_, substs) => substs,
824 ref ty => bug!("unexpected pattern type {:?}", ty),
826 for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
827 let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
828 self.check_pat_walk(&subpat, field_ty, def_bm, true);
830 self.tcx.check_stability(variant.fields[i].did, Some(pat.id), subpat.span);
833 let subpats_ending = if subpats.len() == 1 { "" } else { "s" };
834 let fields_ending = if variant.fields.len() == 1 { "" } else { "s" };
835 struct_span_err!(tcx.sess, pat.span, E0023,
836 "this pattern has {} field{}, but the corresponding {} has {} field{}",
837 subpats.len(), subpats_ending, def.kind_name(),
838 variant.fields.len(), fields_ending)
839 .span_label(pat.span, format!("expected {} field{}, found {}",
840 variant.fields.len(), fields_ending, subpats.len()))
843 return tcx.types.err;
848 fn check_struct_pat_fields(&self,
852 variant: &'tcx ty::VariantDef,
853 fields: &'gcx [Spanned<hir::FieldPat>],
855 def_bm: ty::BindingMode) -> bool {
858 let (substs, adt) = match adt_ty.sty {
859 ty::Adt(adt, substs) => (substs, adt),
860 _ => span_bug!(span, "struct pattern is not an ADT")
862 let kind_name = adt.variant_descr();
864 // Index the struct fields' types.
865 let field_map = variant.fields
868 .map(|(i, field)| (field.ident.modern(), (i, field)))
869 .collect::<FxHashMap<_, _>>();
871 // Keep track of which fields have already appeared in the pattern.
872 let mut used_fields = FxHashMap();
873 let mut no_field_errors = true;
875 let mut inexistent_fields = vec![];
876 // Typecheck each field.
877 for &Spanned { node: ref field, span } in fields {
878 let ident = tcx.adjust_ident(field.ident, variant.did, self.body_id).0;
879 let field_ty = match used_fields.entry(ident) {
880 Occupied(occupied) => {
881 struct_span_err!(tcx.sess, span, E0025,
882 "field `{}` bound multiple times \
886 format!("multiple uses of `{}` in pattern", field.ident))
887 .span_label(*occupied.get(), format!("first use of `{}`", field.ident))
889 no_field_errors = false;
894 field_map.get(&ident)
896 self.write_field_index(field.id, *i);
897 self.tcx.check_stability(f.did, Some(pat_id), span);
898 self.field_ty(span, f, substs)
901 inexistent_fields.push((span, field.ident));
902 no_field_errors = false;
908 self.check_pat_walk(&field.pat, field_ty, def_bm, true);
911 if inexistent_fields.len() > 0 {
912 let (field_names, t, plural) = if inexistent_fields.len() == 1 {
913 (format!("a field named `{}`", inexistent_fields[0].1), "this", "")
915 (format!("fields named {}",
916 inexistent_fields.iter()
917 .map(|(_, name)| format!("`{}`", name))
918 .collect::<Vec<String>>()
919 .join(", ")), "these", "s")
921 let spans = inexistent_fields.iter().map(|(span, _)| *span).collect::<Vec<_>>();
922 let mut err = struct_span_err!(tcx.sess,
925 "{} `{}` does not have {}",
927 tcx.item_path_str(variant.did),
929 if let Some((span, _)) = inexistent_fields.last() {
930 err.span_label(*span,
931 format!("{} `{}` does not have {} field{}",
933 tcx.item_path_str(variant.did),
937 if tcx.sess.teach(&err.get_code().unwrap()) {
939 "This error indicates that a struct pattern attempted to \
940 extract a non-existent field from a struct. Struct fields \
941 are identified by the name used before the colon : so struct \
942 patterns should resemble the declaration of the struct type \
944 If you are using shorthand field patterns but want to refer \
945 to the struct field by a different name, you should rename \
952 // Require `..` if struct has non_exhaustive attribute.
953 if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
954 span_err!(tcx.sess, span, E0638,
955 "`..` required with {} marked as non-exhaustive",
959 // Report an error if incorrect number of the fields were specified.
960 if kind_name == "union" {
961 if fields.len() != 1 {
962 tcx.sess.span_err(span, "union patterns should have exactly one field");
965 tcx.sess.span_err(span, "`..` cannot be used in union patterns");
968 let unmentioned_fields = variant.fields
970 .map(|field| field.ident.modern())
971 .filter(|ident| !used_fields.contains_key(&ident))
972 .collect::<Vec<_>>();
973 if unmentioned_fields.len() > 0 {
974 let field_names = if unmentioned_fields.len() == 1 {
975 format!("field `{}`", unmentioned_fields[0])
978 unmentioned_fields.iter()
979 .map(|name| format!("`{}`", name))
980 .collect::<Vec<String>>()
983 let mut diag = struct_span_err!(tcx.sess, span, E0027,
984 "pattern does not mention {}",
986 diag.span_label(span, format!("missing {}", field_names));
987 if variant.ctor_kind == CtorKind::Fn {
988 diag.note("trying to match a tuple variant with a struct variant pattern");
990 if tcx.sess.teach(&diag.get_code().unwrap()) {
992 "This error indicates that a pattern for a struct fails to specify a \
993 sub-pattern for every one of the struct's fields. Ensure that each field \
994 from the struct's definition is mentioned in the pattern, or use `..` to \
995 ignore unwanted fields."