1 use crate::check::{FnCtxt, Expectation, Diverges, Needs};
2 use crate::check::coercion::CoerceMany;
3 use crate::util::nodemap::FxHashMap;
4 use errors::{Applicability, DiagnosticBuilder};
5 use rustc::hir::{self, PatKind, Pat};
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};
12 use rustc::ty::subst::Kind;
14 use syntax::source_map::Spanned;
16 use syntax::util::lev_distance::find_best_match_for_name;
19 use std::collections::hash_map::Entry::{Occupied, Vacant};
22 use super::report_unexpected_variant_def;
24 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
25 /// `match_discrim_span` argument having a `Span` indicates that this pattern is part of
26 /// a match expression arm guard, and it points to the match discriminant to add context
27 /// in type errors. In the folloowing example, `match_discrim_span` corresponds to the
28 /// `a + b` expression:
31 /// error[E0308]: mismatched types
32 /// --> src/main.rs:5:9
34 /// 4 | let temp: usize = match a + b {
35 /// | ----- this expression has type `usize`
36 /// 5 | Ok(num) => num,
37 /// | ^^^^^^^ expected usize, found enum `std::result::Result`
39 /// = note: expected type `usize`
40 /// found type `std::result::Result<_, _>`
42 pub fn check_pat_walk(
45 mut expected: Ty<'tcx>,
46 mut def_bm: ty::BindingMode,
47 match_discrim_span: Option<Span>,
51 debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?})", pat, expected, def_bm);
53 let is_non_ref_pat = match pat.node {
55 PatKind::TupleStruct(..) |
59 PatKind::Slice(..) => true,
60 PatKind::Lit(ref lt) => {
61 let ty = self.check_expr(lt);
67 PatKind::Path(ref qpath) => {
68 let (def, _, _) = self.resolve_ty_and_def_ufcs(qpath, pat.hir_id, pat.span);
70 Def::Const(..) | Def::AssociatedConst(..) => false,
75 PatKind::Binding(..) |
76 PatKind::Ref(..) => false,
79 debug!("pattern is non reference pattern");
80 let mut exp_ty = self.resolve_type_vars_with_obligations(&expected);
82 // Peel off as many `&` or `&mut` from the discriminant as possible. For example,
83 // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
84 // the `Some(5)` which is not of type Ref.
86 // For each ampersand peeled off, update the binding mode and push the original
87 // type into the adjustments vector.
89 // See the examples in `run-pass/match-defbm*.rs`.
90 let mut pat_adjustments = vec![];
91 while let ty::Ref(_, inner_ty, inner_mutability) = exp_ty.sty {
92 debug!("inspecting {:?}", exp_ty);
94 debug!("current discriminant is Ref, inserting implicit deref");
95 // Preserve the reference type. We'll need it later during HAIR lowering.
96 pat_adjustments.push(exp_ty);
99 def_bm = match def_bm {
100 // If default binding mode is by value, make it `ref` or `ref mut`
101 // (depending on whether we observe `&` or `&mut`).
102 ty::BindByValue(_) =>
103 ty::BindByReference(inner_mutability),
105 // Once a `ref`, always a `ref`. This is because a `& &mut` can't mutate
106 // the underlying value.
107 ty::BindByReference(hir::Mutability::MutImmutable) =>
108 ty::BindByReference(hir::Mutability::MutImmutable),
110 // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref`
112 ty::BindByReference(hir::Mutability::MutMutable) =>
113 ty::BindByReference(inner_mutability),
118 if pat_adjustments.len() > 0 {
119 debug!("default binding mode is now {:?}", def_bm);
120 self.inh.tables.borrow_mut()
121 .pat_adjustments_mut()
122 .insert(pat.hir_id, pat_adjustments);
124 } else if let PatKind::Ref(..) = pat.node {
125 // When you encounter a `&pat` pattern, reset to "by
126 // value". This is so that `x` and `y` here are by value,
127 // as they appear to be:
130 // match &(&22, &44) {
136 def_bm = ty::BindByValue(hir::MutImmutable);
139 // Lose mutability now that we know binding mode and discriminant type.
141 let expected = expected;
143 let ty = match pat.node {
147 PatKind::Lit(ref lt) => {
148 // We've already computed the type above (when checking for a non-ref pat), so
149 // avoid computing it again.
150 let ty = self.node_ty(lt.hir_id);
152 // Byte string patterns behave the same way as array patterns
153 // They can denote both statically and dynamically sized byte arrays
155 if let hir::ExprKind::Lit(ref lt) = lt.node {
156 if let ast::LitKind::ByteStr(_) = lt.node {
157 let expected_ty = self.structurally_resolved_type(pat.span, expected);
158 if let ty::Ref(_, r_ty, _) = expected_ty.sty {
159 if let ty::Slice(_) = r_ty.sty {
160 pat_ty = tcx.mk_imm_ref(tcx.types.re_static,
161 tcx.mk_slice(tcx.types.u8))
167 // somewhat surprising: in this case, the subtyping
168 // relation goes the opposite way as the other
169 // cases. Actually what we really want is not a subtyping
170 // relation at all but rather that there exists a LUB (so
171 // that they can be compared). However, in practice,
172 // constants are always scalars or strings. For scalars
173 // subtyping is irrelevant, and for strings `ty` is
174 // type is `&'static str`, so if we say that
176 // &'static str <: expected
178 // that's equivalent to there existing a LUB.
179 self.demand_suptype(pat.span, expected, pat_ty);
182 PatKind::Range(ref begin, ref end, _) => {
183 let lhs_ty = self.check_expr(begin);
184 let rhs_ty = self.check_expr(end);
186 // Check that both end-points are of numeric or char type.
187 let numeric_or_char = |ty: Ty<'_>| ty.is_numeric() || ty.is_char();
188 let lhs_compat = numeric_or_char(lhs_ty);
189 let rhs_compat = numeric_or_char(rhs_ty);
191 if !lhs_compat || !rhs_compat {
192 let span = if !lhs_compat && !rhs_compat {
194 } else if !lhs_compat {
200 let mut err = struct_span_err!(
204 "only char and numeric types are allowed in range patterns"
206 err.span_label(span, "ranges require char or numeric types");
207 err.note(&format!("start type: {}", self.ty_to_string(lhs_ty)));
208 err.note(&format!("end type: {}", self.ty_to_string(rhs_ty)));
209 if tcx.sess.teach(&err.get_code().unwrap()) {
211 "In a match expression, only numbers and characters can be matched \
212 against a range. This is because the compiler checks that the range \
213 is non-empty at compile-time, and is unable to evaluate arbitrary \
214 comparison functions. If you want to capture values of an orderable \
215 type between two end-points, you can use a guard."
222 // Now that we know the types can be unified we find the unified type and use
223 // it to type the entire expression.
224 let common_type = self.resolve_type_vars_if_possible(&lhs_ty);
226 // subtyping doesn't matter here, as the value is some kind of scalar
227 self.demand_eqtype_pat(pat.span, expected, lhs_ty, match_discrim_span);
228 self.demand_eqtype_pat(pat.span, expected, rhs_ty, match_discrim_span);
231 PatKind::Binding(ba, var_id, _, ref sub) => {
232 let bm = if ba == hir::BindingAnnotation::Unannotated {
235 ty::BindingMode::convert(ba)
240 .pat_binding_modes_mut()
241 .insert(pat.hir_id, bm);
242 debug!("check_pat_walk: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
243 let local_ty = self.local_ty(pat.span, pat.hir_id).decl_ty;
245 ty::BindByReference(mutbl) => {
246 // if the binding is like
247 // ref x | ref const x | ref mut x
248 // then `x` is assigned a value of type `&M T` where M is the mutability
249 // and T is the expected type.
250 let region_var = self.next_region_var(infer::PatternRegion(pat.span));
251 let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
252 let region_ty = tcx.mk_ref(region_var, mt);
254 // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
255 // required. However, we use equality, which is stronger. See (*) for
257 self.demand_eqtype_pat(pat.span, region_ty, local_ty, match_discrim_span);
259 // otherwise the type of x is the expected type T
260 ty::BindByValue(_) => {
261 // As above, `T <: typeof(x)` is required but we
262 // use equality, see (*) below.
263 self.demand_eqtype_pat(pat.span, expected, local_ty, match_discrim_span);
267 // if there are multiple arms, make sure they all agree on
268 // what the type of the binding `x` ought to be
269 if var_id != pat.hir_id {
270 let vt = self.local_ty(pat.span, var_id).decl_ty;
271 self.demand_eqtype_pat(pat.span, vt, local_ty, match_discrim_span);
274 if let Some(ref p) = *sub {
275 self.check_pat_walk(&p, expected, def_bm, match_discrim_span);
280 PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
281 self.check_pat_tuple_struct(
291 PatKind::Path(ref qpath) => {
292 self.check_pat_path(pat, qpath, expected)
294 PatKind::Struct(ref qpath, ref fields, etc) => {
295 self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, match_discrim_span)
297 PatKind::Tuple(ref elements, ddpos) => {
298 let mut expected_len = elements.len();
300 // Require known type only when `..` is present.
301 if let ty::Tuple(ref tys) =
302 self.structurally_resolved_type(pat.span, expected).sty {
303 expected_len = tys.len();
306 let max_len = cmp::max(expected_len, elements.len());
308 let element_tys_iter = (0..max_len).map(|_| {
309 // FIXME: `MiscVariable` for now -- obtaining the span and name information
310 // from all tuple elements isn't trivial.
311 Kind::from(self.next_ty_var(TypeVariableOrigin::TypeInference(pat.span)))
313 let element_tys = tcx.mk_substs(element_tys_iter);
314 let pat_ty = tcx.mk_ty(ty::Tuple(element_tys));
315 if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) {
317 // Walk subpatterns with an expected type of `err` in this case to silence
318 // further errors being emitted when using the bindings. #50333
319 let element_tys_iter = (0..max_len).map(|_| tcx.types.err);
320 for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
321 self.check_pat_walk(elem, &tcx.types.err, def_bm, match_discrim_span);
323 tcx.mk_tup(element_tys_iter)
325 for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
328 &element_tys[i].expect_ty(),
336 PatKind::Box(ref inner) => {
337 let inner_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(inner.span));
338 let uniq_ty = tcx.mk_box(inner_ty);
340 if self.check_dereferencable(pat.span, expected, &inner) {
341 // Here, `demand::subtype` is good enough, but I don't
342 // think any errors can be introduced by using
344 self.demand_eqtype_pat(pat.span, expected, uniq_ty, match_discrim_span);
345 self.check_pat_walk(&inner, inner_ty, def_bm, match_discrim_span);
348 self.check_pat_walk(&inner, tcx.types.err, def_bm, match_discrim_span);
352 PatKind::Ref(ref inner, mutbl) => {
353 let expected = self.shallow_resolve(expected);
354 if self.check_dereferencable(pat.span, expected, &inner) {
355 // `demand::subtype` would be good enough, but using
356 // `eqtype` turns out to be equally general. See (*)
357 // below for details.
359 // Take region, inner-type from expected type if we
360 // can, to avoid creating needless variables. This
361 // also helps with the bad interactions of the given
362 // hack detailed in (*) below.
363 debug!("check_pat_walk: expected={:?}", expected);
364 let (rptr_ty, inner_ty) = match expected.sty {
365 ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => {
369 let inner_ty = self.next_ty_var(
370 TypeVariableOrigin::TypeInference(inner.span));
371 let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
372 let region = self.next_region_var(infer::PatternRegion(pat.span));
373 let rptr_ty = tcx.mk_ref(region, mt);
374 debug!("check_pat_walk: demanding {:?} = {:?}", expected, rptr_ty);
375 let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
377 // Look for a case like `fn foo(&foo: u32)` and suggest
378 // `fn foo(foo: &u32)`
379 if let Some(mut err) = err {
380 self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected);
387 self.check_pat_walk(&inner, inner_ty, def_bm, match_discrim_span);
390 self.check_pat_walk(&inner, tcx.types.err, def_bm, match_discrim_span);
394 PatKind::Slice(ref before, ref slice, ref after) => {
395 let expected_ty = self.structurally_resolved_type(pat.span, expected);
396 let (inner_ty, slice_ty) = match expected_ty.sty {
397 ty::Array(inner_ty, size) => {
398 let size = size.unwrap_usize(tcx);
399 let min_len = before.len() as u64 + after.len() as u64;
403 tcx.sess, pat.span, E0527,
404 "pattern requires {} elements but array has {}",
406 .span_label(pat.span, format!("expected {} elements", size))
409 (inner_ty, tcx.types.err)
410 } else if let Some(rest) = size.checked_sub(min_len) {
411 (inner_ty, tcx.mk_array(inner_ty, rest))
413 struct_span_err!(tcx.sess, pat.span, E0528,
414 "pattern requires at least {} elements but array has {}",
416 .span_label(pat.span,
417 format!("pattern cannot match array of {} elements", size))
419 (inner_ty, tcx.types.err)
422 ty::Slice(inner_ty) => (inner_ty, expected_ty),
424 if !expected_ty.references_error() {
425 let mut err = struct_span_err!(
426 tcx.sess, pat.span, E0529,
427 "expected an array or slice, found `{}`",
429 if let ty::Ref(_, ty, _) = expected_ty.sty {
431 ty::Array(..) | ty::Slice(..) => {
432 err.help("the semantics of slice patterns changed \
433 recently; see issue #23121");
439 err.span_label( pat.span,
440 format!("pattern cannot match with input type `{}`", expected_ty)
443 (tcx.types.err, tcx.types.err)
448 self.check_pat_walk(&elt, inner_ty, def_bm, match_discrim_span);
450 if let Some(ref slice) = *slice {
451 self.check_pat_walk(&slice, slice_ty, def_bm, match_discrim_span);
454 self.check_pat_walk(&elt, inner_ty, def_bm, match_discrim_span);
460 self.write_ty(pat.hir_id, ty);
462 // (*) In most of the cases above (literals and constants being
463 // the exception), we relate types using strict equality, even
464 // though subtyping would be sufficient. There are a few reasons
465 // for this, some of which are fairly subtle and which cost me
466 // (nmatsakis) an hour or two debugging to remember, so I thought
467 // I'd write them down this time.
469 // 1. There is no loss of expressiveness here, though it does
470 // cause some inconvenience. What we are saying is that the type
471 // of `x` becomes *exactly* what is expected. This can cause unnecessary
472 // errors in some cases, such as this one:
475 // fn foo<'x>(x: &'x int) {
482 // The reason we might get an error is that `z` might be
483 // assigned a type like `&'x int`, and then we would have
484 // a problem when we try to assign `&a` to `z`, because
485 // the lifetime of `&a` (i.e., the enclosing block) is
486 // shorter than `'x`.
488 // HOWEVER, this code works fine. The reason is that the
489 // expected type here is whatever type the user wrote, not
490 // the initializer's type. In this case the user wrote
491 // nothing, so we are going to create a type variable `Z`.
492 // Then we will assign the type of the initializer (`&'x
493 // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
494 // will instantiate `Z` as a type `&'0 int` where `'0` is
495 // a fresh region variable, with the constraint that `'x :
496 // '0`. So basically we're all set.
498 // Note that there are two tests to check that this remains true
499 // (`regions-reassign-{match,let}-bound-pointer.rs`).
501 // 2. Things go horribly wrong if we use subtype. The reason for
502 // THIS is a fairly subtle case involving bound regions. See the
503 // `givens` field in `region_constraints`, as well as the test
504 // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
505 // for details. Short version is that we must sometimes detect
506 // relationships between specific region variables and regions
507 // bound in a closure signature, and that detection gets thrown
508 // off when we substitute fresh region variables here to enable
512 fn borrow_pat_suggestion(
514 err: &mut DiagnosticBuilder<'_>,
520 if let PatKind::Binding(..) = inner.node {
521 let parent_id = tcx.hir().get_parent_node_by_hir_id(pat.hir_id);
522 let parent = tcx.hir().get_by_hir_id(parent_id);
523 debug!("inner {:?} pat {:?} parent {:?}", inner, pat, parent);
525 hir::Node::Item(hir::Item { node: hir::ItemKind::Fn(..), .. }) |
526 hir::Node::ForeignItem(hir::ForeignItem {
527 node: hir::ForeignItemKind::Fn(..), ..
529 hir::Node::TraitItem(hir::TraitItem { node: hir::TraitItemKind::Method(..), .. }) |
530 hir::Node::ImplItem(hir::ImplItem { node: hir::ImplItemKind::Method(..), .. }) => {
531 // this pat is likely an argument
532 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
533 // FIXME: turn into structured suggestion, will need a span that also
534 // includes the the arg's type.
535 err.help(&format!("did you mean `{}: &{}`?", snippet, expected));
538 hir::Node::Expr(hir::Expr { node: hir::ExprKind::Match(..), .. }) |
539 hir::Node::Pat(_) => {
540 // rely on match ergonomics or it might be nested `&&pat`
541 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
544 "you can probably remove the explicit borrow",
546 Applicability::MaybeIncorrect,
550 _ => {} // don't provide suggestions in other cases #55175
555 pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
556 if let PatKind::Binding(..) = inner.node {
557 if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) {
558 if let ty::Dynamic(..) = mt.ty.sty {
559 // This is "x = SomeTrait" being reduced from
560 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
561 let type_str = self.ty_to_string(expected);
562 let mut err = struct_span_err!(
566 "type `{}` cannot be dereferenced",
569 err.span_label(span, format!("type `{}` cannot be dereferenced", type_str));
570 if self.tcx.sess.teach(&err.get_code().unwrap()) {
572 This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \
573 pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \
574 this type has no compile-time size. Therefore, all accesses to trait types must be through \
575 pointers. If you encounter this error you should try to avoid dereferencing the pointer.
577 You can read more about trait objects in the Trait Objects section of the Reference: \
578 https://doc.rust-lang.org/reference/types.html#trait-objects");
590 expr: &'gcx hir::Expr,
591 discrim: &'gcx hir::Expr,
592 arms: &'gcx [hir::Arm],
593 expected: Expectation<'tcx>,
594 match_src: hir::MatchSource,
598 // Not entirely obvious: if matches may create ref bindings, we want to
599 // use the *precise* type of the discriminant, *not* some supertype, as
600 // the "discriminant type" (issue #23116).
602 // arielb1 [writes here in this comment thread][c] that there
603 // is certainly *some* potential danger, e.g., for an example
606 // [c]: https://github.com/rust-lang/rust/pull/43399#discussion_r130223956
609 // let Foo(x) = f()[0];
612 // Then if the pattern matches by reference, we want to match
613 // `f()[0]` as a lexpr, so we can't allow it to be
614 // coerced. But if the pattern matches by value, `f()[0]` is
615 // still syntactically a lexpr, but we *do* want to allow
618 // However, *likely* we are ok with allowing coercions to
619 // happen if there are no explicit ref mut patterns - all
620 // implicit ref mut patterns must occur behind a reference, so
621 // they will have the "correct" variance and lifetime.
623 // This does mean that the following pattern would be legal:
628 // impl Deref for Foo {
629 // type Target = Bar;
630 // fn deref(&self) -> &Bar { &self.0 }
632 // impl DerefMut for Foo {
633 // fn deref_mut(&mut self) -> &mut Bar { &mut self.0 }
635 // fn foo(x: &mut Foo) {
637 // let Bar(z): &mut Bar = x;
640 // assert_eq!(foo.0.0, 42);
644 // FIXME(tschottdorf): don't call contains_explicit_ref_binding, which
645 // is problematic as the HIR is being scraped, but ref bindings may be
646 // implicit after #42640. We need to make sure that pat_adjustments
647 // (once introduced) is populated by the time we get here.
650 let contains_ref_bindings = arms.iter()
651 .filter_map(|a| a.contains_explicit_ref_binding())
652 .max_by_key(|m| match *m {
653 hir::MutMutable => 1,
654 hir::MutImmutable => 0,
657 if let Some(m) = contains_ref_bindings {
658 discrim_ty = self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m));
660 // ...but otherwise we want to use any supertype of the
661 // discriminant. This is sort of a workaround, see note (*) in
662 // `check_pat` for some details.
663 discrim_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(discrim.span));
664 self.check_expr_has_type_or_error(discrim, discrim_ty);
667 // If there are no arms, that is a diverging match; a special case.
669 self.diverges.set(self.diverges.get() | Diverges::Always);
670 return tcx.types.never;
673 if self.diverges.get().always() {
675 self.warn_if_unreachable(arm.body.hir_id, arm.body.span, "arm");
679 // Otherwise, we have to union together the types that the
680 // arms produce and so forth.
681 let discrim_diverges = self.diverges.get();
682 self.diverges.set(Diverges::Maybe);
684 // rust-lang/rust#55810: Typecheck patterns first (via eager
685 // collection into `Vec`), so we get types for all bindings.
686 let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| {
687 let mut all_pats_diverge = Diverges::WarnedAlways;
689 self.diverges.set(Diverges::Maybe);
693 ty::BindingMode::BindByValue(hir::Mutability::MutImmutable),
696 all_pats_diverge &= self.diverges.get();
699 // As discussed with @eddyb, this is for disabling unreachable_code
700 // warnings on patterns (they're now subsumed by unreachable_patterns
702 match all_pats_diverge {
703 Diverges::Maybe => Diverges::Maybe,
704 Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
708 // Now typecheck the blocks.
710 // The result of the match is the common supertype of all the
711 // arms. Start out the value as bottom, since it's the, well,
712 // bottom the type lattice, and we'll be moving up the lattice as
713 // we process each arm. (Note that any match with 0 arms is matching
714 // on any empty type and is therefore unreachable; should the flow
715 // of execution reach it, we will panic, so bottom is an appropriate
716 // type in that case)
717 let mut all_arms_diverge = Diverges::WarnedAlways;
719 let expected = expected.adjust_for_branches(self);
722 let coerce_first = match expected {
723 // We don't coerce to `()` so that if the match expression is a
724 // statement it's branches can have any consistent type. That allows
725 // us to give better error messages (pointing to a usually better
726 // arm for inconsistent arms or to the whole match when a `()` type
728 Expectation::ExpectHasType(ety) if ety != self.tcx.mk_unit() => ety,
729 _ => self.next_ty_var(TypeVariableOrigin::MiscVariable(expr.span)),
731 CoerceMany::with_coercion_sites(coerce_first, arms)
734 let mut other_arms = vec![]; // used only for diagnostics
735 let mut prior_arm_ty = None;
736 for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
737 if let Some(ref g) = arm.guard {
738 self.diverges.set(pats_diverge);
740 hir::Guard::If(e) => self.check_expr_has_type_or_error(e, tcx.types.bool),
744 self.diverges.set(pats_diverge);
745 let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
746 all_arms_diverge &= self.diverges.get();
748 // Handle the fallback arm of a desugared if-let like a missing else.
749 let is_if_let_fallback = match match_src {
750 hir::MatchSource::IfLetDesugar { contains_else_clause: false } => {
751 i == arms.len() - 1 && arm_ty.is_unit()
756 let arm_span = if let hir::ExprKind::Block(ref blk, _) = arm.body.node {
757 // Point at the block expr instead of the entire block
758 blk.expr.as_ref().map(|e| e.span).unwrap_or(arm.body.span)
762 if is_if_let_fallback {
763 let cause = self.cause(expr.span, ObligationCauseCode::IfExpressionWithNoElse);
764 assert!(arm_ty.is_unit());
765 coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
767 let cause = if i == 0 {
768 // The reason for the first arm to fail is not that the match arms diverge,
769 // but rather that there's a prior obligation that doesn't hold.
770 self.cause(arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id))
772 self.cause(expr.span, ObligationCauseCode::MatchExpressionArm {
775 prior_arms: other_arms.clone(),
776 last_ty: prior_arm_ty.unwrap(),
777 discrim_hir_id: discrim.hir_id,
780 coercion.coerce(self, &cause, &arm.body, arm_ty);
782 other_arms.push(arm_span);
783 if other_arms.len() > 5 {
784 other_arms.remove(0);
786 prior_arm_ty = Some(arm_ty);
789 // We won't diverge unless the discriminant or all arms diverge.
790 self.diverges.set(discrim_diverges | all_arms_diverge);
792 coercion.complete(self)
799 fields: &'gcx [Spanned<hir::FieldPat>],
802 def_bm: ty::BindingMode,
803 match_discrim_span: Option<Span>,
806 // Resolve the path and check the definition for errors.
807 let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.hir_id)
811 for field in fields {
819 return self.tcx.types.err;
822 // Type-check the path.
823 self.demand_eqtype_pat(pat.span, expected, pat_ty, match_discrim_span);
825 // Type-check subpatterns.
826 if self.check_struct_pat_fields(pat_ty, pat.hir_id, pat.span, variant, fields, etc, def_bm)
842 // Resolve the path and check the definition for errors.
843 let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.hir_id, pat.span);
846 self.set_tainted_by_errors();
847 return tcx.types.err;
850 report_unexpected_variant_def(tcx, &def, pat.span, qpath);
851 return tcx.types.err;
853 Def::Ctor(_, _, CtorKind::Fictive) |
854 Def::Ctor(_, _, CtorKind::Fn) => {
855 report_unexpected_variant_def(tcx, &def, pat.span, qpath);
856 return tcx.types.err;
858 Def::Ctor(_, _, CtorKind::Const) | Def::SelfCtor(..) |
859 Def::Const(..) | Def::AssociatedConst(..) => {} // OK
860 _ => bug!("unexpected pattern definition: {:?}", def)
863 // Type-check the path.
864 let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.hir_id).0;
865 self.demand_suptype(pat.span, expected, pat_ty);
869 fn check_pat_tuple_struct(
873 subpats: &'gcx [P<hir::Pat>],
874 ddpos: Option<usize>,
876 def_bm: ty::BindingMode,
877 match_arm_pat_span: Option<Span>,
882 self.check_pat_walk(&pat, tcx.types.err, def_bm, match_arm_pat_span);
885 let report_unexpected_def = |def: Def| {
886 let msg = format!("expected tuple struct/variant, found {} `{}`",
888 hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false)));
889 struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg)
890 .span_label(pat.span, "not a tuple variant or struct").emit();
894 // Resolve the path and check the definition for errors.
895 let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.hir_id, pat.span);
897 self.set_tainted_by_errors();
899 return self.tcx.types.err;
902 // Type-check the path.
903 let (pat_ty, def) = self.instantiate_value_path(segments, opt_ty, def, pat.span,
906 report_unexpected_def(def);
907 return self.tcx.types.err;
910 let variant = match def {
912 self.set_tainted_by_errors();
914 return tcx.types.err;
916 Def::AssociatedConst(..) | Def::Method(..) => {
917 report_unexpected_def(def);
918 return tcx.types.err;
920 Def::Ctor(_, _, CtorKind::Fn) => {
921 tcx.expect_variant_def(def)
923 _ => bug!("unexpected pattern definition: {:?}", def)
926 // Replace constructor type with constructed type for tuple struct patterns.
927 let pat_ty = pat_ty.fn_sig(tcx).output();
928 let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
930 self.demand_eqtype_pat(pat.span, expected, pat_ty, match_arm_pat_span);
932 // Type-check subpatterns.
933 if subpats.len() == variant.fields.len() ||
934 subpats.len() < variant.fields.len() && ddpos.is_some() {
935 let substs = match pat_ty.sty {
936 ty::Adt(_, substs) => substs,
937 _ => bug!("unexpected pattern type {:?}", pat_ty),
939 for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
940 let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
941 self.check_pat_walk(&subpat, field_ty, def_bm, match_arm_pat_span);
943 self.tcx.check_stability(variant.fields[i].did, Some(pat.hir_id), subpat.span);
946 let subpats_ending = if subpats.len() == 1 { "" } else { "s" };
947 let fields_ending = if variant.fields.len() == 1 { "" } else { "s" };
948 struct_span_err!(tcx.sess, pat.span, E0023,
949 "this pattern has {} field{}, but the corresponding {} has {} field{}",
950 subpats.len(), subpats_ending, def.kind_name(),
951 variant.fields.len(), fields_ending)
952 .span_label(pat.span, format!("expected {} field{}, found {}",
953 variant.fields.len(), fields_ending, subpats.len()))
956 return tcx.types.err;
961 fn check_struct_pat_fields(
966 variant: &'tcx ty::VariantDef,
967 fields: &'gcx [Spanned<hir::FieldPat>],
969 def_bm: ty::BindingMode,
973 let (substs, adt) = match adt_ty.sty {
974 ty::Adt(adt, substs) => (substs, adt),
975 _ => span_bug!(span, "struct pattern is not an ADT")
977 let kind_name = adt.variant_descr();
979 // Index the struct fields' types.
980 let field_map = variant.fields
983 .map(|(i, field)| (field.ident.modern(), (i, field)))
984 .collect::<FxHashMap<_, _>>();
986 // Keep track of which fields have already appeared in the pattern.
987 let mut used_fields = FxHashMap::default();
988 let mut no_field_errors = true;
990 let mut inexistent_fields = vec![];
991 // Typecheck each field.
992 for &Spanned { node: ref field, span } in fields {
993 let ident = tcx.adjust_ident(field.ident, variant.def_id, self.body_id).0;
994 let field_ty = match used_fields.entry(ident) {
995 Occupied(occupied) => {
996 struct_span_err!(tcx.sess, span, E0025,
997 "field `{}` bound multiple times \
1001 format!("multiple uses of `{}` in pattern", field.ident))
1002 .span_label(*occupied.get(), format!("first use of `{}`", field.ident))
1004 no_field_errors = false;
1008 vacant.insert(span);
1009 field_map.get(&ident)
1011 self.write_field_index(field.hir_id, *i);
1012 self.tcx.check_stability(f.did, Some(pat_id), span);
1013 self.field_ty(span, f, substs)
1015 .unwrap_or_else(|| {
1016 inexistent_fields.push(field.ident);
1017 no_field_errors = false;
1023 self.check_pat_walk(&field.pat, field_ty, def_bm, None);
1025 let mut unmentioned_fields = variant.fields
1027 .map(|field| field.ident.modern())
1028 .filter(|ident| !used_fields.contains_key(&ident))
1029 .collect::<Vec<_>>();
1030 if inexistent_fields.len() > 0 && !variant.recovered {
1031 let (field_names, t, plural) = if inexistent_fields.len() == 1 {
1032 (format!("a field named `{}`", inexistent_fields[0]), "this", "")
1034 (format!("fields named {}",
1035 inexistent_fields.iter()
1036 .map(|ident| format!("`{}`", ident))
1037 .collect::<Vec<String>>()
1038 .join(", ")), "these", "s")
1040 let spans = inexistent_fields.iter().map(|ident| ident.span).collect::<Vec<_>>();
1041 let mut err = struct_span_err!(tcx.sess,
1044 "{} `{}` does not have {}",
1046 tcx.def_path_str(variant.def_id),
1048 if let Some(ident) = inexistent_fields.last() {
1049 err.span_label(ident.span,
1050 format!("{} `{}` does not have {} field{}",
1052 tcx.def_path_str(variant.def_id),
1056 let input = unmentioned_fields.iter().map(|field| &field.name);
1057 let suggested_name =
1058 find_best_match_for_name(input, &ident.as_str(), None);
1059 if let Some(suggested_name) = suggested_name {
1060 err.span_suggestion(
1062 "a field with a similar name exists",
1063 suggested_name.to_string(),
1064 Applicability::MaybeIncorrect,
1067 // we don't want to throw `E0027` in case we have thrown `E0026` for them
1068 unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str());
1072 if tcx.sess.teach(&err.get_code().unwrap()) {
1074 "This error indicates that a struct pattern attempted to \
1075 extract a non-existent field from a struct. Struct fields \
1076 are identified by the name used before the colon : so struct \
1077 patterns should resemble the declaration of the struct type \
1079 If you are using shorthand field patterns but want to refer \
1080 to the struct field by a different name, you should rename \
1087 // Require `..` if struct has non_exhaustive attribute.
1088 if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
1089 span_err!(tcx.sess, span, E0638,
1090 "`..` required with {} marked as non-exhaustive",
1094 // Report an error if incorrect number of the fields were specified.
1095 if kind_name == "union" {
1096 if fields.len() != 1 {
1097 tcx.sess.span_err(span, "union patterns should have exactly one field");
1100 tcx.sess.span_err(span, "`..` cannot be used in union patterns");
1103 if unmentioned_fields.len() > 0 {
1104 let field_names = if unmentioned_fields.len() == 1 {
1105 format!("field `{}`", unmentioned_fields[0])
1107 format!("fields {}",
1108 unmentioned_fields.iter()
1109 .map(|name| format!("`{}`", name))
1110 .collect::<Vec<String>>()
1113 let mut diag = struct_span_err!(tcx.sess, span, E0027,
1114 "pattern does not mention {}",
1116 diag.span_label(span, format!("missing {}", field_names));
1117 if variant.ctor_kind == CtorKind::Fn {
1118 diag.note("trying to match a tuple variant with a struct variant pattern");
1120 if tcx.sess.teach(&diag.get_code().unwrap()) {
1122 "This error indicates that a pattern for a struct fails to specify a \
1123 sub-pattern for every one of the struct's fields. Ensure that each field \
1124 from the struct's definition is mentioned in the pattern, or use `..` to \
1125 ignore unwanted fields."