1 use crate::check::{FnCtxt, Expectation, Diverges, Needs};
2 use crate::check::coercion::CoerceMany;
3 use crate::util::nodemap::FxHashMap;
4 use errors::Applicability;
5 use rustc::hir::{self, PatKind};
6 use rustc::hir::def::{Def, CtorKind};
7 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
9 use rustc::infer::type_variable::TypeVariableOrigin;
10 use rustc::traits::ObligationCauseCode;
11 use rustc::ty::{self, Ty, TypeFoldable};
13 use syntax::source_map::Spanned;
15 use syntax::util::lev_distance::find_best_match_for_name;
18 use std::collections::hash_map::Entry::{Occupied, Vacant};
21 use super::report_unexpected_variant_def;
23 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
24 /// `match_discrim_span` argument having a `Span` indicates that this pattern is part of
25 /// a match expression arm guard, and it points to the match discriminant to add context
26 /// in type errors. In the folloowing example, `match_discrim_span` corresponds to the
27 /// `a + b` expression:
30 /// error[E0308]: mismatched types
31 /// --> src/main.rs:5:9
33 /// 4 | let temp: usize = match a + b {
34 /// | ----- this expression has type `usize`
35 /// 5 | Ok(num) => num,
36 /// | ^^^^^^^ expected usize, found enum `std::result::Result`
38 /// = note: expected type `usize`
39 /// found type `std::result::Result<_, _>`
41 pub fn check_pat_walk(
44 mut expected: Ty<'tcx>,
45 mut def_bm: ty::BindingMode,
46 match_discrim_span: Option<Span>,
50 debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?})", pat, expected, def_bm);
52 let is_non_ref_pat = match pat.node {
54 PatKind::TupleStruct(..) |
58 PatKind::Slice(..) => true,
59 PatKind::Lit(ref lt) => {
60 let ty = self.check_expr(lt);
66 PatKind::Path(ref qpath) => {
67 let (def, _, _) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
69 Def::Const(..) | Def::AssociatedConst(..) => false,
74 PatKind::Binding(..) |
75 PatKind::Ref(..) => false,
78 debug!("pattern is non reference pattern");
79 let mut exp_ty = self.resolve_type_vars_with_obligations(&expected);
81 // Peel off as many `&` or `&mut` from the discriminant as possible. For example,
82 // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
83 // the `Some(5)` which is not of type Ref.
85 // For each ampersand peeled off, update the binding mode and push the original
86 // type into the adjustments vector.
88 // See the examples in `run-pass/match-defbm*.rs`.
89 let mut pat_adjustments = vec![];
90 while let ty::Ref(_, inner_ty, inner_mutability) = exp_ty.sty {
91 debug!("inspecting {:?} with type {:?}", exp_ty, exp_ty.sty);
93 debug!("current discriminant is Ref, inserting implicit deref");
94 // Preserve the reference type. We'll need it later during HAIR lowering.
95 pat_adjustments.push(exp_ty);
98 def_bm = match def_bm {
99 // If default binding mode is by value, make it `ref` or `ref mut`
100 // (depending on whether we observe `&` or `&mut`).
101 ty::BindByValue(_) =>
102 ty::BindByReference(inner_mutability),
104 // Once a `ref`, always a `ref`. This is because a `& &mut` can't mutate
105 // the underlying value.
106 ty::BindByReference(hir::Mutability::MutImmutable) =>
107 ty::BindByReference(hir::Mutability::MutImmutable),
109 // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref`
111 ty::BindByReference(hir::Mutability::MutMutable) =>
112 ty::BindByReference(inner_mutability),
117 if pat_adjustments.len() > 0 {
118 debug!("default binding mode is now {:?}", def_bm);
119 self.inh.tables.borrow_mut()
120 .pat_adjustments_mut()
121 .insert(pat.hir_id, pat_adjustments);
123 } else if let PatKind::Ref(..) = pat.node {
124 // When you encounter a `&pat` pattern, reset to "by
125 // value". This is so that `x` and `y` here are by value,
126 // as they appear to be:
129 // match &(&22, &44) {
135 def_bm = ty::BindByValue(hir::MutImmutable);
138 // Lose mutability now that we know binding mode and discriminant type.
140 let expected = expected;
142 let ty = match pat.node {
146 PatKind::Lit(ref lt) => {
147 // We've already computed the type above (when checking for a non-ref pat), so
148 // avoid computing it again.
149 let ty = self.node_ty(lt.hir_id);
151 // Byte string patterns behave the same way as array patterns
152 // They can denote both statically and dynamically sized byte arrays
154 if let hir::ExprKind::Lit(ref lt) = lt.node {
155 if let ast::LitKind::ByteStr(_) = lt.node {
156 let expected_ty = self.structurally_resolved_type(pat.span, expected);
157 if let ty::Ref(_, r_ty, _) = expected_ty.sty {
158 if let ty::Slice(_) = r_ty.sty {
159 pat_ty = tcx.mk_imm_ref(tcx.types.re_static,
160 tcx.mk_slice(tcx.types.u8))
166 // somewhat surprising: in this case, the subtyping
167 // relation goes the opposite way as the other
168 // cases. Actually what we really want is not a subtyping
169 // relation at all but rather that there exists a LUB (so
170 // that they can be compared). However, in practice,
171 // constants are always scalars or strings. For scalars
172 // subtyping is irrelevant, and for strings `ty` is
173 // type is `&'static str`, so if we say that
175 // &'static str <: expected
177 // that's equivalent to there existing a LUB.
178 self.demand_suptype(pat.span, expected, pat_ty);
181 PatKind::Range(ref begin, ref end, _) => {
182 let lhs_ty = self.check_expr(begin);
183 let rhs_ty = self.check_expr(end);
185 // Check that both end-points are of numeric or char type.
186 let numeric_or_char = |ty: Ty| ty.is_numeric() || ty.is_char();
187 let lhs_compat = numeric_or_char(lhs_ty);
188 let rhs_compat = numeric_or_char(rhs_ty);
190 if !lhs_compat || !rhs_compat {
191 let span = if !lhs_compat && !rhs_compat {
193 } else if !lhs_compat {
199 let mut err = struct_span_err!(
203 "only char and numeric types are allowed in range patterns"
205 err.span_label(span, "ranges require char or numeric types");
206 err.note(&format!("start type: {}", self.ty_to_string(lhs_ty)));
207 err.note(&format!("end type: {}", self.ty_to_string(rhs_ty)));
208 if tcx.sess.teach(&err.get_code().unwrap()) {
210 "In a match expression, only numbers and characters can be matched \
211 against a range. This is because the compiler checks that the range \
212 is non-empty at compile-time, and is unable to evaluate arbitrary \
213 comparison functions. If you want to capture values of an orderable \
214 type between two end-points, you can use a guard."
221 // Now that we know the types can be unified we find the unified type and use
222 // it to type the entire expression.
223 let common_type = self.resolve_type_vars_if_possible(&lhs_ty);
225 // subtyping doesn't matter here, as the value is some kind of scalar
226 self.demand_eqtype_pat(pat.span, expected, lhs_ty, match_discrim_span);
227 self.demand_eqtype_pat(pat.span, expected, rhs_ty, match_discrim_span);
230 PatKind::Binding(ba, var_id, _, _, ref sub) => {
231 let bm = if ba == hir::BindingAnnotation::Unannotated {
234 ty::BindingMode::convert(ba)
239 .pat_binding_modes_mut()
240 .insert(pat.hir_id, bm);
241 debug!("check_pat_walk: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
242 let local_ty = self.local_ty(pat.span, pat.id).decl_ty;
244 ty::BindByReference(mutbl) => {
245 // if the binding is like
246 // ref x | ref const x | ref mut x
247 // then `x` is assigned a value of type `&M T` where M is the mutability
248 // and T is the expected type.
249 let region_var = self.next_region_var(infer::PatternRegion(pat.span));
250 let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
251 let region_ty = tcx.mk_ref(region_var, mt);
253 // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
254 // required. However, we use equality, which is stronger. See (*) for
256 self.demand_eqtype_pat(pat.span, region_ty, local_ty, match_discrim_span);
258 // otherwise the type of x is the expected type T
259 ty::BindByValue(_) => {
260 // As above, `T <: typeof(x)` is required but we
261 // use equality, see (*) below.
262 self.demand_eqtype_pat(pat.span, expected, local_ty, match_discrim_span);
266 // if there are multiple arms, make sure they all agree on
267 // what the type of the binding `x` ought to be
268 if var_id != pat.id {
269 let vt = self.local_ty(pat.span, var_id).decl_ty;
270 self.demand_eqtype_pat(pat.span, vt, local_ty, match_discrim_span);
273 if let Some(ref p) = *sub {
274 self.check_pat_walk(&p, expected, def_bm, match_discrim_span);
279 PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
280 self.check_pat_tuple_struct(
290 PatKind::Path(ref qpath) => {
291 self.check_pat_path(pat, qpath, expected)
293 PatKind::Struct(ref qpath, ref fields, etc) => {
294 self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, match_discrim_span)
296 PatKind::Tuple(ref elements, ddpos) => {
297 let mut expected_len = elements.len();
299 // Require known type only when `..` is present.
300 if let ty::Tuple(ref tys) =
301 self.structurally_resolved_type(pat.span, expected).sty {
302 expected_len = tys.len();
305 let max_len = cmp::max(expected_len, elements.len());
307 let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(
308 // FIXME: `MiscVariable` for now -- obtaining the span and name information
309 // from all tuple elements isn't trivial.
310 TypeVariableOrigin::TypeInference(pat.span)));
311 let element_tys = tcx.mk_type_list(element_tys_iter);
312 let pat_ty = tcx.mk_ty(ty::Tuple(element_tys));
313 if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) {
315 // Walk subpatterns with an expected type of `err` in this case to silence
316 // further errors being emitted when using the bindings. #50333
317 let element_tys_iter = (0..max_len).map(|_| tcx.types.err);
318 for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
319 self.check_pat_walk(elem, &tcx.types.err, def_bm, match_discrim_span);
321 tcx.mk_tup(element_tys_iter)
323 for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
324 self.check_pat_walk(elem, &element_tys[i], def_bm, match_discrim_span);
329 PatKind::Box(ref inner) => {
330 let inner_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(inner.span));
331 let uniq_ty = tcx.mk_box(inner_ty);
333 if self.check_dereferencable(pat.span, expected, &inner) {
334 // Here, `demand::subtype` is good enough, but I don't
335 // think any errors can be introduced by using
337 self.demand_eqtype_pat(pat.span, expected, uniq_ty, match_discrim_span);
338 self.check_pat_walk(&inner, inner_ty, def_bm, match_discrim_span);
341 self.check_pat_walk(&inner, tcx.types.err, def_bm, match_discrim_span);
345 PatKind::Ref(ref inner, mutbl) => {
346 let expected = self.shallow_resolve(expected);
347 if self.check_dereferencable(pat.span, expected, &inner) {
348 // `demand::subtype` would be good enough, but using
349 // `eqtype` turns out to be equally general. See (*)
350 // below for details.
352 // Take region, inner-type from expected type if we
353 // can, to avoid creating needless variables. This
354 // also helps with the bad interactions of the given
355 // hack detailed in (*) below.
356 debug!("check_pat_walk: expected={:?}", expected);
357 let (rptr_ty, inner_ty) = match expected.sty {
358 ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => {
362 let inner_ty = self.next_ty_var(
363 TypeVariableOrigin::TypeInference(inner.span));
364 let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
365 let region = self.next_region_var(infer::PatternRegion(pat.span));
366 let rptr_ty = tcx.mk_ref(region, mt);
367 debug!("check_pat_walk: demanding {:?} = {:?}", expected, rptr_ty);
368 let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
370 // Look for a case like `fn foo(&foo: u32)` and suggest
371 // `fn foo(foo: &u32)`
372 if let Some(mut err) = err {
373 if let PatKind::Binding(..) = inner.node {
374 if let Ok(snippet) = tcx.sess.source_map()
375 .span_to_snippet(pat.span)
377 err.help(&format!("did you mean `{}: &{}`?",
388 self.check_pat_walk(&inner, inner_ty, def_bm, match_discrim_span);
391 self.check_pat_walk(&inner, tcx.types.err, def_bm, match_discrim_span);
395 PatKind::Slice(ref before, ref slice, ref after) => {
396 let expected_ty = self.structurally_resolved_type(pat.span, expected);
397 let (inner_ty, slice_ty) = match expected_ty.sty {
398 ty::Array(inner_ty, size) => {
399 let size = size.unwrap_usize(tcx);
400 let min_len = before.len() as u64 + after.len() as u64;
404 tcx.sess, pat.span, E0527,
405 "pattern requires {} elements but array has {}",
407 .span_label(pat.span, format!("expected {} elements", size))
410 (inner_ty, tcx.types.err)
411 } else if let Some(rest) = size.checked_sub(min_len) {
412 (inner_ty, tcx.mk_array(inner_ty, rest))
414 struct_span_err!(tcx.sess, pat.span, E0528,
415 "pattern requires at least {} elements but array has {}",
417 .span_label(pat.span,
418 format!("pattern cannot match array of {} elements", size))
420 (inner_ty, tcx.types.err)
423 ty::Slice(inner_ty) => (inner_ty, expected_ty),
425 if !expected_ty.references_error() {
426 let mut err = struct_span_err!(
427 tcx.sess, pat.span, E0529,
428 "expected an array or slice, found `{}`",
430 if let ty::Ref(_, ty, _) = expected_ty.sty {
432 ty::Array(..) | ty::Slice(..) => {
433 err.help("the semantics of slice patterns changed \
434 recently; see issue #23121");
440 err.span_label( pat.span,
441 format!("pattern cannot match with input type `{}`", expected_ty)
444 (tcx.types.err, tcx.types.err)
449 self.check_pat_walk(&elt, inner_ty, def_bm, match_discrim_span);
451 if let Some(ref slice) = *slice {
452 self.check_pat_walk(&slice, slice_ty, def_bm, match_discrim_span);
455 self.check_pat_walk(&elt, inner_ty, def_bm, match_discrim_span);
461 self.write_ty(pat.hir_id, ty);
463 // (*) In most of the cases above (literals and constants being
464 // the exception), we relate types using strict equality, even
465 // though subtyping would be sufficient. There are a few reasons
466 // for this, some of which are fairly subtle and which cost me
467 // (nmatsakis) an hour or two debugging to remember, so I thought
468 // I'd write them down this time.
470 // 1. There is no loss of expressiveness here, though it does
471 // cause some inconvenience. What we are saying is that the type
472 // of `x` becomes *exactly* what is expected. This can cause unnecessary
473 // errors in some cases, such as this one:
476 // fn foo<'x>(x: &'x int) {
483 // The reason we might get an error is that `z` might be
484 // assigned a type like `&'x int`, and then we would have
485 // a problem when we try to assign `&a` to `z`, because
486 // the lifetime of `&a` (i.e., the enclosing block) is
487 // shorter than `'x`.
489 // HOWEVER, this code works fine. The reason is that the
490 // expected type here is whatever type the user wrote, not
491 // the initializer's type. In this case the user wrote
492 // nothing, so we are going to create a type variable `Z`.
493 // Then we will assign the type of the initializer (`&'x
494 // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
495 // will instantiate `Z` as a type `&'0 int` where `'0` is
496 // a fresh region variable, with the constraint that `'x :
497 // '0`. So basically we're all set.
499 // Note that there are two tests to check that this remains true
500 // (`regions-reassign-{match,let}-bound-pointer.rs`).
502 // 2. Things go horribly wrong if we use subtype. The reason for
503 // THIS is a fairly subtle case involving bound regions. See the
504 // `givens` field in `region_constraints`, as well as the test
505 // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
506 // for details. Short version is that we must sometimes detect
507 // relationships between specific region variables and regions
508 // bound in a closure signature, and that detection gets thrown
509 // off when we substitute fresh region variables here to enable
513 pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
514 if let PatKind::Binding(..) = inner.node {
515 if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) {
516 if let ty::Dynamic(..) = mt.ty.sty {
517 // This is "x = SomeTrait" being reduced from
518 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
519 let type_str = self.ty_to_string(expected);
520 let mut err = struct_span_err!(
524 "type `{}` cannot be dereferenced",
527 err.span_label(span, format!("type `{}` cannot be dereferenced", type_str));
528 if self.tcx.sess.teach(&err.get_code().unwrap()) {
530 This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \
531 pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \
532 this type has no compile-time size. Therefore, all accesses to trait types must be through \
533 pointers. If you encounter this error you should try to avoid dereferencing the pointer.
535 You can read more about trait objects in the Trait Objects section of the Reference: \
536 https://doc.rust-lang.org/reference/types.html#trait-objects");
548 expr: &'gcx hir::Expr,
549 discrim: &'gcx hir::Expr,
550 arms: &'gcx [hir::Arm],
551 expected: Expectation<'tcx>,
552 match_src: hir::MatchSource,
556 // Not entirely obvious: if matches may create ref bindings, we want to
557 // use the *precise* type of the discriminant, *not* some supertype, as
558 // the "discriminant type" (issue #23116).
560 // arielb1 [writes here in this comment thread][c] that there
561 // is certainly *some* potential danger, e.g., for an example
564 // [c]: https://github.com/rust-lang/rust/pull/43399#discussion_r130223956
567 // let Foo(x) = f()[0];
570 // Then if the pattern matches by reference, we want to match
571 // `f()[0]` as a lexpr, so we can't allow it to be
572 // coerced. But if the pattern matches by value, `f()[0]` is
573 // still syntactically a lexpr, but we *do* want to allow
576 // However, *likely* we are ok with allowing coercions to
577 // happen if there are no explicit ref mut patterns - all
578 // implicit ref mut patterns must occur behind a reference, so
579 // they will have the "correct" variance and lifetime.
581 // This does mean that the following pattern would be legal:
586 // impl Deref for Foo {
587 // type Target = Bar;
588 // fn deref(&self) -> &Bar { &self.0 }
590 // impl DerefMut for Foo {
591 // fn deref_mut(&mut self) -> &mut Bar { &mut self.0 }
593 // fn foo(x: &mut Foo) {
595 // let Bar(z): &mut Bar = x;
598 // assert_eq!(foo.0.0, 42);
602 // FIXME(tschottdorf): don't call contains_explicit_ref_binding, which
603 // is problematic as the HIR is being scraped, but ref bindings may be
604 // implicit after #42640. We need to make sure that pat_adjustments
605 // (once introduced) is populated by the time we get here.
608 let contains_ref_bindings = arms.iter()
609 .filter_map(|a| a.contains_explicit_ref_binding())
610 .max_by_key(|m| match *m {
611 hir::MutMutable => 1,
612 hir::MutImmutable => 0,
615 if let Some(m) = contains_ref_bindings {
616 discrim_ty = self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m));
618 // ...but otherwise we want to use any supertype of the
619 // discriminant. This is sort of a workaround, see note (*) in
620 // `check_pat` for some details.
621 discrim_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(discrim.span));
622 self.check_expr_has_type_or_error(discrim, discrim_ty);
625 // If there are no arms, that is a diverging match; a special case.
627 self.diverges.set(self.diverges.get() | Diverges::Always);
628 return tcx.types.never;
631 if self.diverges.get().always() {
633 self.warn_if_unreachable(arm.body.id, arm.body.span, "arm");
637 // Otherwise, we have to union together the types that the
638 // arms produce and so forth.
639 let discrim_diverges = self.diverges.get();
640 self.diverges.set(Diverges::Maybe);
642 // rust-lang/rust#55810: Typecheck patterns first (via eager
643 // collection into `Vec`), so we get types for all bindings.
644 let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| {
645 let mut all_pats_diverge = Diverges::WarnedAlways;
647 self.diverges.set(Diverges::Maybe);
651 ty::BindingMode::BindByValue(hir::Mutability::MutImmutable),
654 all_pats_diverge &= self.diverges.get();
657 // As discussed with @eddyb, this is for disabling unreachable_code
658 // warnings on patterns (they're now subsumed by unreachable_patterns
660 match all_pats_diverge {
661 Diverges::Maybe => Diverges::Maybe,
662 Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
666 // Now typecheck the blocks.
668 // The result of the match is the common supertype of all the
669 // arms. Start out the value as bottom, since it's the, well,
670 // bottom the type lattice, and we'll be moving up the lattice as
671 // we process each arm. (Note that any match with 0 arms is matching
672 // on any empty type and is therefore unreachable; should the flow
673 // of execution reach it, we will panic, so bottom is an appropriate
674 // type in that case)
675 let mut all_arms_diverge = Diverges::WarnedAlways;
677 let expected = expected.adjust_for_branches(self);
680 let coerce_first = match expected {
681 // We don't coerce to `()` so that if the match expression is a
682 // statement it's branches can have any consistent type. That allows
683 // us to give better error messages (pointing to a usually better
684 // arm for inconsistent arms or to the whole match when a `()` type
686 Expectation::ExpectHasType(ety) if ety != self.tcx.mk_unit() => ety,
687 _ => self.next_ty_var(TypeVariableOrigin::MiscVariable(expr.span)),
689 CoerceMany::with_coercion_sites(coerce_first, arms)
692 for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
693 if let Some(ref g) = arm.guard {
694 self.diverges.set(pats_diverge);
696 hir::Guard::If(e) => self.check_expr_has_type_or_error(e, tcx.types.bool),
700 self.diverges.set(pats_diverge);
701 let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
702 all_arms_diverge &= self.diverges.get();
704 // Handle the fallback arm of a desugared if-let like a missing else.
705 let is_if_let_fallback = match match_src {
706 hir::MatchSource::IfLetDesugar { contains_else_clause: false } => {
707 i == arms.len() - 1 && arm_ty.is_unit()
712 if is_if_let_fallback {
713 let cause = self.cause(expr.span, ObligationCauseCode::IfExpressionWithNoElse);
714 assert!(arm_ty.is_unit());
715 coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
717 let cause = self.cause(expr.span, ObligationCauseCode::MatchExpressionArm {
718 arm_span: arm.body.span,
721 coercion.coerce(self, &cause, &arm.body, arm_ty);
725 // We won't diverge unless the discriminant or all arms diverge.
726 self.diverges.set(discrim_diverges | all_arms_diverge);
728 coercion.complete(self)
735 fields: &'gcx [Spanned<hir::FieldPat>],
738 def_bm: ty::BindingMode,
739 match_discrim_span: Option<Span>,
742 // Resolve the path and check the definition for errors.
743 let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.id) {
746 for field in fields {
754 return self.tcx.types.err;
757 // Type-check the path.
758 self.demand_eqtype_pat(pat.span, expected, pat_ty, match_discrim_span);
760 // Type-check subpatterns.
761 if self.check_struct_pat_fields(pat_ty, pat.id, pat.span, variant, fields, etc, def_bm) {
776 // Resolve the path and check the definition for errors.
777 let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
780 self.set_tainted_by_errors();
781 return tcx.types.err;
784 report_unexpected_variant_def(tcx, &def, pat.span, qpath);
785 return tcx.types.err;
787 Def::VariantCtor(_, CtorKind::Fictive) |
788 Def::VariantCtor(_, CtorKind::Fn) => {
789 report_unexpected_variant_def(tcx, &def, pat.span, qpath);
790 return tcx.types.err;
792 Def::VariantCtor(_, CtorKind::Const) |
793 Def::StructCtor(_, CtorKind::Const) |
795 Def::Const(..) | Def::AssociatedConst(..) => {} // OK
796 _ => bug!("unexpected pattern definition: {:?}", def)
799 // Type-check the path.
800 let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id).0;
801 self.demand_suptype(pat.span, expected, pat_ty);
805 fn check_pat_tuple_struct(
809 subpats: &'gcx [P<hir::Pat>],
810 ddpos: Option<usize>,
812 def_bm: ty::BindingMode,
813 match_arm_pat_span: Option<Span>,
818 self.check_pat_walk(&pat, tcx.types.err, def_bm, match_arm_pat_span);
821 let report_unexpected_def = |def: Def| {
822 let msg = format!("expected tuple struct/variant, found {} `{}`",
824 hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false)));
825 struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg)
826 .span_label(pat.span, "not a tuple variant or struct").emit();
830 // Resolve the path and check the definition for errors.
831 let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
833 self.set_tainted_by_errors();
835 return self.tcx.types.err;
838 // Type-check the path.
839 let (pat_ty, def) = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
841 report_unexpected_def(def);
842 return self.tcx.types.err;
845 let variant = match def {
847 self.set_tainted_by_errors();
849 return tcx.types.err;
851 Def::AssociatedConst(..) | Def::Method(..) => {
852 report_unexpected_def(def);
853 return tcx.types.err;
855 Def::VariantCtor(_, CtorKind::Fn) |
856 Def::StructCtor(_, CtorKind::Fn) => {
857 tcx.expect_variant_def(def)
859 _ => bug!("unexpected pattern definition: {:?}", def)
862 // Replace constructor type with constructed type for tuple struct patterns.
863 let pat_ty = pat_ty.fn_sig(tcx).output();
864 let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
866 self.demand_eqtype_pat(pat.span, expected, pat_ty, match_arm_pat_span);
868 // Type-check subpatterns.
869 if subpats.len() == variant.fields.len() ||
870 subpats.len() < variant.fields.len() && ddpos.is_some() {
871 let substs = match pat_ty.sty {
872 ty::Adt(_, substs) => substs,
873 ref ty => bug!("unexpected pattern type {:?}", ty),
875 for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
876 let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
877 self.check_pat_walk(&subpat, field_ty, def_bm, match_arm_pat_span);
879 self.tcx.check_stability(variant.fields[i].did, Some(pat.id), subpat.span);
882 let subpats_ending = if subpats.len() == 1 { "" } else { "s" };
883 let fields_ending = if variant.fields.len() == 1 { "" } else { "s" };
884 struct_span_err!(tcx.sess, pat.span, E0023,
885 "this pattern has {} field{}, but the corresponding {} has {} field{}",
886 subpats.len(), subpats_ending, def.kind_name(),
887 variant.fields.len(), fields_ending)
888 .span_label(pat.span, format!("expected {} field{}, found {}",
889 variant.fields.len(), fields_ending, subpats.len()))
892 return tcx.types.err;
897 fn check_struct_pat_fields(&self,
901 variant: &'tcx ty::VariantDef,
902 fields: &'gcx [Spanned<hir::FieldPat>],
904 def_bm: ty::BindingMode) -> bool {
907 let (substs, adt) = match adt_ty.sty {
908 ty::Adt(adt, substs) => (substs, adt),
909 _ => span_bug!(span, "struct pattern is not an ADT")
911 let kind_name = adt.variant_descr();
913 // Index the struct fields' types.
914 let field_map = variant.fields
917 .map(|(i, field)| (field.ident.modern(), (i, field)))
918 .collect::<FxHashMap<_, _>>();
920 // Keep track of which fields have already appeared in the pattern.
921 let mut used_fields = FxHashMap::default();
922 let mut no_field_errors = true;
924 let mut inexistent_fields = vec![];
925 // Typecheck each field.
926 for &Spanned { node: ref field, span } in fields {
927 let ident = tcx.adjust_ident(field.ident, variant.did, self.body_id).0;
928 let field_ty = match used_fields.entry(ident) {
929 Occupied(occupied) => {
930 struct_span_err!(tcx.sess, span, E0025,
931 "field `{}` bound multiple times \
935 format!("multiple uses of `{}` in pattern", field.ident))
936 .span_label(*occupied.get(), format!("first use of `{}`", field.ident))
938 no_field_errors = false;
943 field_map.get(&ident)
945 self.write_field_index(field.id, *i);
946 self.tcx.check_stability(f.did, Some(pat_id), span);
947 self.field_ty(span, f, substs)
950 inexistent_fields.push((span, field.ident));
951 no_field_errors = false;
957 self.check_pat_walk(&field.pat, field_ty, def_bm, None);
959 let mut unmentioned_fields = variant.fields
961 .map(|field| field.ident.modern())
962 .filter(|ident| !used_fields.contains_key(&ident))
963 .collect::<Vec<_>>();
964 if inexistent_fields.len() > 0 {
965 let (field_names, t, plural) = if inexistent_fields.len() == 1 {
966 (format!("a field named `{}`", inexistent_fields[0].1), "this", "")
968 (format!("fields named {}",
969 inexistent_fields.iter()
970 .map(|(_, name)| format!("`{}`", name))
971 .collect::<Vec<String>>()
972 .join(", ")), "these", "s")
974 let spans = inexistent_fields.iter().map(|(span, _)| *span).collect::<Vec<_>>();
975 let mut err = struct_span_err!(tcx.sess,
978 "{} `{}` does not have {}",
980 tcx.item_path_str(variant.did),
982 if let Some((span, ident)) = inexistent_fields.last() {
983 err.span_label(*span,
984 format!("{} `{}` does not have {} field{}",
986 tcx.item_path_str(variant.did),
990 let input = unmentioned_fields.iter().map(|field| &field.name);
992 find_best_match_for_name(input, &ident.as_str(), None);
993 if let Some(suggested_name) = suggested_name {
997 suggested_name.to_string(),
998 Applicability::MaybeIncorrect,
1001 // we don't want to throw `E0027` in case we have thrown `E0026` for them
1002 unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str());
1006 if tcx.sess.teach(&err.get_code().unwrap()) {
1008 "This error indicates that a struct pattern attempted to \
1009 extract a non-existent field from a struct. Struct fields \
1010 are identified by the name used before the colon : so struct \
1011 patterns should resemble the declaration of the struct type \
1013 If you are using shorthand field patterns but want to refer \
1014 to the struct field by a different name, you should rename \
1021 // Require `..` if struct has non_exhaustive attribute.
1022 if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
1023 span_err!(tcx.sess, span, E0638,
1024 "`..` required with {} marked as non-exhaustive",
1028 // Report an error if incorrect number of the fields were specified.
1029 if kind_name == "union" {
1030 if fields.len() != 1 {
1031 tcx.sess.span_err(span, "union patterns should have exactly one field");
1034 tcx.sess.span_err(span, "`..` cannot be used in union patterns");
1037 if unmentioned_fields.len() > 0 {
1038 let field_names = if unmentioned_fields.len() == 1 {
1039 format!("field `{}`", unmentioned_fields[0])
1041 format!("fields {}",
1042 unmentioned_fields.iter()
1043 .map(|name| format!("`{}`", name))
1044 .collect::<Vec<String>>()
1047 let mut diag = struct_span_err!(tcx.sess, span, E0027,
1048 "pattern does not mention {}",
1050 diag.span_label(span, format!("missing {}", field_names));
1051 if variant.ctor_kind == CtorKind::Fn {
1052 diag.note("trying to match a tuple variant with a struct variant pattern");
1054 if tcx.sess.teach(&diag.get_code().unwrap()) {
1056 "This error indicates that a pattern for a struct fails to specify a \
1057 sub-pattern for every one of the struct's fields. Ensure that each field \
1058 from the struct's definition is mentioned in the pattern, or use `..` to \
1059 ignore unwanted fields."