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, ExprKind};
6 use rustc::hir::def::{Res, DefKind, CtorKind};
7 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
9 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
10 use rustc::traits::{ObligationCause, 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;
18 use syntax_pos::hygiene::CompilerDesugaringKind;
20 use std::collections::hash_map::Entry::{Occupied, Vacant};
23 use super::report_unexpected_variant_res;
25 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
26 /// `discrim_span` argument having a `Span` indicates that this pattern is part of a match
27 /// expression arm guard, and it points to the match discriminant to add context in type errors.
28 /// In the following example, `discrim_span` corresponds to the `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 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_res_ufcs(qpath, pat.hir_id, pat.span);
70 Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => 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.lifetimes.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 if let Some(mut err) = self.demand_suptype_diag(pat.span, expected, pat_ty) {
180 err.emit_unless(discrim_span
181 .filter(|&s| s.is_compiler_desugaring(CompilerDesugaringKind::IfTemporary))
187 PatKind::Range(ref begin, ref end, _) => {
188 let lhs_ty = self.check_expr(begin);
189 let rhs_ty = self.check_expr(end);
191 // Check that both end-points are of numeric or char type.
192 let numeric_or_char = |ty: Ty<'_>| ty.is_numeric() || ty.is_char();
193 let lhs_compat = numeric_or_char(lhs_ty);
194 let rhs_compat = numeric_or_char(rhs_ty);
196 if !lhs_compat || !rhs_compat {
197 let span = if !lhs_compat && !rhs_compat {
199 } else if !lhs_compat {
205 let mut err = struct_span_err!(
209 "only char and numeric types are allowed in range patterns"
211 err.span_label(span, "ranges require char or numeric types");
212 err.note(&format!("start type: {}", self.ty_to_string(lhs_ty)));
213 err.note(&format!("end type: {}", self.ty_to_string(rhs_ty)));
214 if tcx.sess.teach(&err.get_code().unwrap()) {
216 "In a match expression, only numbers and characters can be matched \
217 against a range. This is because the compiler checks that the range \
218 is non-empty at compile-time, and is unable to evaluate arbitrary \
219 comparison functions. If you want to capture values of an orderable \
220 type between two end-points, you can use a guard."
227 // Now that we know the types can be unified we find the unified type and use
228 // it to type the entire expression.
229 let common_type = self.resolve_vars_if_possible(&lhs_ty);
231 // subtyping doesn't matter here, as the value is some kind of scalar
232 self.demand_eqtype_pat(pat.span, expected, lhs_ty, discrim_span);
233 self.demand_eqtype_pat(pat.span, expected, rhs_ty, discrim_span);
236 PatKind::Binding(ba, var_id, _, ref sub) => {
237 let bm = if ba == hir::BindingAnnotation::Unannotated {
240 ty::BindingMode::convert(ba)
245 .pat_binding_modes_mut()
246 .insert(pat.hir_id, bm);
247 debug!("check_pat_walk: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
248 let local_ty = self.local_ty(pat.span, pat.hir_id).decl_ty;
250 ty::BindByReference(mutbl) => {
251 // if the binding is like
252 // ref x | ref const x | ref mut x
253 // then `x` is assigned a value of type `&M T` where M is the mutability
254 // and T is the expected type.
255 let region_var = self.next_region_var(infer::PatternRegion(pat.span));
256 let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
257 let region_ty = tcx.mk_ref(region_var, mt);
259 // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
260 // required. However, we use equality, which is stronger. See (*) for
262 self.demand_eqtype_pat(pat.span, region_ty, local_ty, discrim_span);
264 // otherwise the type of x is the expected type T
265 ty::BindByValue(_) => {
266 // As above, `T <: typeof(x)` is required but we
267 // use equality, see (*) below.
268 self.demand_eqtype_pat(pat.span, expected, local_ty, discrim_span);
272 // if there are multiple arms, make sure they all agree on
273 // what the type of the binding `x` ought to be
274 if var_id != pat.hir_id {
275 let vt = self.local_ty(pat.span, var_id).decl_ty;
276 self.demand_eqtype_pat(pat.span, vt, local_ty, discrim_span);
279 if let Some(ref p) = *sub {
280 self.check_pat_walk(&p, expected, def_bm, discrim_span);
285 PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
286 self.check_pat_tuple_struct(
296 PatKind::Path(ref qpath) => {
297 self.check_pat_path(pat, qpath, expected)
299 PatKind::Struct(ref qpath, ref fields, etc) => {
300 self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, discrim_span)
302 PatKind::Tuple(ref elements, ddpos) => {
303 let mut expected_len = elements.len();
305 // Require known type only when `..` is present.
306 if let ty::Tuple(ref tys) =
307 self.structurally_resolved_type(pat.span, expected).sty {
308 expected_len = tys.len();
311 let max_len = cmp::max(expected_len, elements.len());
313 let element_tys_iter = (0..max_len).map(|_| {
314 Kind::from(self.next_ty_var(
315 // FIXME: `MiscVariable` for now -- obtaining the span and name information
316 // from all tuple elements isn't trivial.
318 kind: TypeVariableOriginKind::TypeInference,
323 let element_tys = tcx.mk_substs(element_tys_iter);
324 let pat_ty = tcx.mk_ty(ty::Tuple(element_tys));
325 if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) {
327 // Walk subpatterns with an expected type of `err` in this case to silence
328 // further errors being emitted when using the bindings. #50333
329 let element_tys_iter = (0..max_len).map(|_| tcx.types.err);
330 for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
331 self.check_pat_walk(elem, &tcx.types.err, def_bm, discrim_span);
333 tcx.mk_tup(element_tys_iter)
335 for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
338 &element_tys[i].expect_ty(),
346 PatKind::Box(ref inner) => {
347 let inner_ty = self.next_ty_var(TypeVariableOrigin {
348 kind: TypeVariableOriginKind::TypeInference,
351 let uniq_ty = tcx.mk_box(inner_ty);
353 if self.check_dereferencable(pat.span, expected, &inner) {
354 // Here, `demand::subtype` is good enough, but I don't
355 // think any errors can be introduced by using
357 self.demand_eqtype_pat(pat.span, expected, uniq_ty, discrim_span);
358 self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span);
361 self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span);
365 PatKind::Ref(ref inner, mutbl) => {
366 let expected = self.shallow_resolve(expected);
367 if self.check_dereferencable(pat.span, expected, &inner) {
368 // `demand::subtype` would be good enough, but using
369 // `eqtype` turns out to be equally general. See (*)
370 // below for details.
372 // Take region, inner-type from expected type if we
373 // can, to avoid creating needless variables. This
374 // also helps with the bad interactions of the given
375 // hack detailed in (*) below.
376 debug!("check_pat_walk: expected={:?}", expected);
377 let (rptr_ty, inner_ty) = match expected.sty {
378 ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => {
382 let inner_ty = self.next_ty_var(
384 kind: TypeVariableOriginKind::TypeInference,
388 let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
389 let region = self.next_region_var(infer::PatternRegion(pat.span));
390 let rptr_ty = tcx.mk_ref(region, mt);
391 debug!("check_pat_walk: demanding {:?} = {:?}", expected, rptr_ty);
392 let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
394 // Look for a case like `fn foo(&foo: u32)` and suggest
395 // `fn foo(foo: &u32)`
396 if let Some(mut err) = err {
397 self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected);
404 self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span);
407 self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span);
411 PatKind::Slice(ref before, ref slice, ref after) => {
412 let expected_ty = self.structurally_resolved_type(pat.span, expected);
413 let (inner_ty, slice_ty) = match expected_ty.sty {
414 ty::Array(inner_ty, size) => {
415 if let Some(size) = size.assert_usize(tcx) {
416 let min_len = before.len() as u64 + after.len() as u64;
420 tcx.sess, pat.span, E0527,
421 "pattern requires {} elements but array has {}",
423 .span_label(pat.span, format!("expected {} elements", size))
426 (inner_ty, tcx.types.err)
427 } else if let Some(rest) = size.checked_sub(min_len) {
428 (inner_ty, tcx.mk_array(inner_ty, rest))
430 struct_span_err!(tcx.sess, pat.span, E0528,
431 "pattern requires at least {} elements but array has {}",
433 .span_label(pat.span,
434 format!("pattern cannot match array of {} elements", size))
436 (inner_ty, tcx.types.err)
443 "cannot pattern-match on an array without a fixed length",
445 (inner_ty, tcx.types.err)
448 ty::Slice(inner_ty) => (inner_ty, expected_ty),
450 if !expected_ty.references_error() {
451 let mut err = struct_span_err!(
452 tcx.sess, pat.span, E0529,
453 "expected an array or slice, found `{}`",
455 if let ty::Ref(_, ty, _) = expected_ty.sty {
457 ty::Array(..) | ty::Slice(..) => {
458 err.help("the semantics of slice patterns changed \
459 recently; see issue #23121");
465 err.span_label( pat.span,
466 format!("pattern cannot match with input type `{}`", expected_ty)
469 (tcx.types.err, tcx.types.err)
474 self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span);
476 if let Some(ref slice) = *slice {
477 self.check_pat_walk(&slice, slice_ty, def_bm, discrim_span);
480 self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span);
486 self.write_ty(pat.hir_id, ty);
488 // (*) In most of the cases above (literals and constants being
489 // the exception), we relate types using strict equality, even
490 // though subtyping would be sufficient. There are a few reasons
491 // for this, some of which are fairly subtle and which cost me
492 // (nmatsakis) an hour or two debugging to remember, so I thought
493 // I'd write them down this time.
495 // 1. There is no loss of expressiveness here, though it does
496 // cause some inconvenience. What we are saying is that the type
497 // of `x` becomes *exactly* what is expected. This can cause unnecessary
498 // errors in some cases, such as this one:
501 // fn foo<'x>(x: &'x int) {
508 // The reason we might get an error is that `z` might be
509 // assigned a type like `&'x int`, and then we would have
510 // a problem when we try to assign `&a` to `z`, because
511 // the lifetime of `&a` (i.e., the enclosing block) is
512 // shorter than `'x`.
514 // HOWEVER, this code works fine. The reason is that the
515 // expected type here is whatever type the user wrote, not
516 // the initializer's type. In this case the user wrote
517 // nothing, so we are going to create a type variable `Z`.
518 // Then we will assign the type of the initializer (`&'x
519 // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
520 // will instantiate `Z` as a type `&'0 int` where `'0` is
521 // a fresh region variable, with the constraint that `'x :
522 // '0`. So basically we're all set.
524 // Note that there are two tests to check that this remains true
525 // (`regions-reassign-{match,let}-bound-pointer.rs`).
527 // 2. Things go horribly wrong if we use subtype. The reason for
528 // THIS is a fairly subtle case involving bound regions. See the
529 // `givens` field in `region_constraints`, as well as the test
530 // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
531 // for details. Short version is that we must sometimes detect
532 // relationships between specific region variables and regions
533 // bound in a closure signature, and that detection gets thrown
534 // off when we substitute fresh region variables here to enable
538 fn borrow_pat_suggestion(
540 err: &mut DiagnosticBuilder<'_>,
546 if let PatKind::Binding(..) = inner.node {
547 let parent_id = tcx.hir().get_parent_node_by_hir_id(pat.hir_id);
548 let parent = tcx.hir().get_by_hir_id(parent_id);
549 debug!("inner {:?} pat {:?} parent {:?}", inner, pat, parent);
551 hir::Node::Item(hir::Item { node: hir::ItemKind::Fn(..), .. }) |
552 hir::Node::ForeignItem(hir::ForeignItem {
553 node: hir::ForeignItemKind::Fn(..), ..
555 hir::Node::TraitItem(hir::TraitItem { node: hir::TraitItemKind::Method(..), .. }) |
556 hir::Node::ImplItem(hir::ImplItem { node: hir::ImplItemKind::Method(..), .. }) => {
557 // this pat is likely an argument
558 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
559 // FIXME: turn into structured suggestion, will need a span that also
560 // includes the the arg's type.
561 err.help(&format!("did you mean `{}: &{}`?", snippet, expected));
565 hir::Node::Pat(_) => {
566 // rely on match ergonomics or it might be nested `&&pat`
567 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
570 "you can probably remove the explicit borrow",
572 Applicability::MaybeIncorrect,
576 _ => {} // don't provide suggestions in other cases #55175
581 pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
582 if let PatKind::Binding(..) = inner.node {
583 if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) {
584 if let ty::Dynamic(..) = mt.ty.sty {
585 // This is "x = SomeTrait" being reduced from
586 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
587 let type_str = self.ty_to_string(expected);
588 let mut err = struct_span_err!(
592 "type `{}` cannot be dereferenced",
595 err.span_label(span, format!("type `{}` cannot be dereferenced", type_str));
596 if self.tcx.sess.teach(&err.get_code().unwrap()) {
598 This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \
599 pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \
600 this type has no compile-time size. Therefore, all accesses to trait types must be through \
601 pointers. If you encounter this error you should try to avoid dereferencing the pointer.
603 You can read more about trait objects in the Trait Objects section of the Reference: \
604 https://doc.rust-lang.org/reference/types.html#trait-objects");
616 expr: &'gcx hir::Expr,
617 discrim: &'gcx hir::Expr,
618 arms: &'gcx [hir::Arm],
619 expected: Expectation<'tcx>,
620 match_src: hir::MatchSource,
624 use hir::MatchSource::*;
625 let (source_if, if_no_else, if_desugar) = match match_src {
626 IfDesugar { contains_else_clause } => (true, !contains_else_clause, true),
627 IfLetDesugar { contains_else_clause } => (true, !contains_else_clause, false),
628 _ => (false, false, false),
631 // Type check the descriminant and get its type.
632 let discrim_ty = if if_desugar {
633 // Here we want to ensure:
635 // 1. That default match bindings are *not* accepted in the condition of an
636 // `if` expression. E.g. given `fn foo() -> &bool;` we reject `if foo() { .. }`.
638 // 2. By expecting `bool` for `expr` we get nice diagnostics for e.g. `if x = y { .. }`.
640 // FIXME(60707): Consider removing hack with principled solution.
641 self.check_expr_has_type_or_error(discrim, self.tcx.types.bool)
643 self.demand_discriminant_type(arms, discrim)
646 // If there are no arms, that is a diverging match; a special case.
648 self.diverges.set(self.diverges.get() | Diverges::Always);
649 return tcx.types.never;
652 self.warn_arms_when_scrutinee_diverges(arms, source_if);
654 // Otherwise, we have to union together the types that the
655 // arms produce and so forth.
656 let discrim_diverges = self.diverges.get();
657 self.diverges.set(Diverges::Maybe);
659 // rust-lang/rust#55810: Typecheck patterns first (via eager
660 // collection into `Vec`), so we get types for all bindings.
661 let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| {
662 let mut all_pats_diverge = Diverges::WarnedAlways;
664 self.diverges.set(Diverges::Maybe);
665 let binding_mode = ty::BindingMode::BindByValue(hir::Mutability::MutImmutable);
666 self.check_pat_walk(&p, discrim_ty, binding_mode, Some(discrim.span));
667 all_pats_diverge &= self.diverges.get();
670 // As discussed with @eddyb, this is for disabling unreachable_code
671 // warnings on patterns (they're now subsumed by unreachable_patterns
673 match all_pats_diverge {
674 Diverges::Maybe => Diverges::Maybe,
675 Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
679 // Now typecheck the blocks.
681 // The result of the match is the common supertype of all the
682 // arms. Start out the value as bottom, since it's the, well,
683 // bottom the type lattice, and we'll be moving up the lattice as
684 // we process each arm. (Note that any match with 0 arms is matching
685 // on any empty type and is therefore unreachable; should the flow
686 // of execution reach it, we will panic, so bottom is an appropriate
687 // type in that case)
688 let mut all_arms_diverge = Diverges::WarnedAlways;
690 let expected = expected.adjust_for_branches(self);
693 let coerce_first = match expected {
694 // We don't coerce to `()` so that if the match expression is a
695 // statement it's branches can have any consistent type. That allows
696 // us to give better error messages (pointing to a usually better
697 // arm for inconsistent arms or to the whole match when a `()` type
699 Expectation::ExpectHasType(ety) if ety != self.tcx.mk_unit() => ety,
700 _ => self.next_ty_var(TypeVariableOrigin {
701 kind: TypeVariableOriginKind::MiscVariable,
705 CoerceMany::with_coercion_sites(coerce_first, arms)
708 let mut other_arms = vec![]; // used only for diagnostics
709 let mut prior_arm_ty = None;
710 for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
711 if let Some(g) = &arm.guard {
712 self.diverges.set(pats_diverge);
714 hir::Guard::If(e) => self.check_expr_has_type_or_error(e, tcx.types.bool),
718 self.diverges.set(pats_diverge);
719 let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
720 all_arms_diverge &= self.diverges.get();
722 let span = expr.span;
725 let then_expr = &arms[0].body;
726 match (i, if_no_else) {
727 (0, _) => coercion.coerce(self, &self.misc(span), then_expr, arm_ty),
728 (_, true) => self.if_fallback_coercion(span, then_expr, &mut coercion),
730 let then_ty = prior_arm_ty.unwrap();
731 let cause = self.if_cause(span, then_expr, &arm.body, then_ty, arm_ty);
732 coercion.coerce(self, &cause, &arm.body, arm_ty);
736 let arm_span = if let hir::ExprKind::Block(blk, _) = &arm.body.node {
737 // Point at the block expr instead of the entire block
738 blk.expr.as_ref().map(|e| e.span).unwrap_or(arm.body.span)
742 let (span, code) = match i {
743 // The reason for the first arm to fail is not that the match arms diverge,
744 // but rather that there's a prior obligation that doesn't hold.
745 0 => (arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id)),
746 _ => (span, ObligationCauseCode::MatchExpressionArm {
749 prior_arms: other_arms.clone(),
750 last_ty: prior_arm_ty.unwrap(),
751 discrim_hir_id: discrim.hir_id,
754 let cause = self.cause(span, code);
755 coercion.coerce(self, &cause, &arm.body, arm_ty);
756 other_arms.push(arm_span);
757 if other_arms.len() > 5 {
758 other_arms.remove(0);
761 prior_arm_ty = Some(arm_ty);
764 // We won't diverge unless the discriminant or all arms diverge.
765 self.diverges.set(discrim_diverges | all_arms_diverge);
767 coercion.complete(self)
770 /// When the previously checked expression (the scrutinee) diverges,
771 /// warn the user about the match arms being unreachable.
772 fn warn_arms_when_scrutinee_diverges(&self, arms: &'gcx [hir::Arm], source_if: bool) {
773 if self.diverges.get().always() {
774 let msg = if source_if { "block in `if` expression" } else { "arm" };
776 self.warn_if_unreachable(arm.body.hir_id, arm.body.span, msg);
781 /// Handle the fallback arm of a desugared if(-let) like a missing else.
782 fn if_fallback_coercion(
785 then_expr: &'gcx hir::Expr,
786 coercion: &mut CoerceMany<'gcx, 'tcx, '_, rustc::hir::Arm>,
788 // If this `if` expr is the parent's function return expr,
789 // the cause of the type coercion is the return type, point at it. (#25228)
790 let ret_reason = self.maybe_get_coercion_reason(then_expr.hir_id, span);
791 let cause = self.cause(span, ObligationCauseCode::IfExpressionWithNoElse);
792 coercion.coerce_forced_unit(self, &cause, &mut |err| {
793 if let Some((span, msg)) = &ret_reason {
794 err.span_label(*span, msg.as_str());
795 } else if let ExprKind::Block(block, _) = &then_expr.node {
796 if let Some(expr) = &block.expr {
797 err.span_label(expr.span, "found here".to_string());
800 err.note("`if` expressions without `else` evaluate to `()`");
801 err.help("consider adding an `else` block that evaluates to the expected type");
802 }, ret_reason.is_none());
805 fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, span: Span) -> Option<(Span, String)> {
806 use hir::Node::{Block, Item, Local};
808 let hir = self.tcx.hir();
809 let arm_id = hir.get_parent_node_by_hir_id(hir_id);
810 let match_id = hir.get_parent_node_by_hir_id(arm_id);
811 let containing_id = hir.get_parent_node_by_hir_id(match_id);
813 let node = hir.get_by_hir_id(containing_id);
814 if let Block(block) = node {
815 // check that the body's parent is an fn
816 let parent = hir.get_by_hir_id(
817 hir.get_parent_node_by_hir_id(
818 hir.get_parent_node_by_hir_id(block.hir_id),
821 if let (Some(expr), Item(hir::Item {
822 node: hir::ItemKind::Fn(..), ..
823 })) = (&block.expr, parent) {
824 // check that the `if` expr without `else` is the fn body's expr
825 if expr.span == span {
826 return self.get_fn_decl(hir_id).map(|(fn_decl, _)| (
827 fn_decl.output.span(),
828 format!("expected `{}` because of this return type", fn_decl.output),
833 if let Local(hir::Local { ty: Some(_), pat, .. }) = node {
834 return Some((pat.span, "expected because of this assignment".to_string()));
842 then_expr: &'gcx hir::Expr,
843 else_expr: &'gcx hir::Expr,
846 ) -> ObligationCause<'tcx> {
847 let mut outer_sp = if self.tcx.sess.source_map().is_multiline(span) {
848 // The `if`/`else` isn't in one line in the output, include some context to make it
849 // clear it is an if/else expression:
851 // LL | let x = if true {
854 // || ----- expected because of this
857 // || ^^^^^ expected i32, found u32
859 // ||_____- if and else have incompatible types
863 // The entire expression is in one line, only point at the arms
865 // LL | let x = if true { 10i32 } else { 10u32 };
866 // | ----- ^^^^^ expected i32, found u32
868 // | expected because of this
873 let mut remove_semicolon = None;
874 let error_sp = if let ExprKind::Block(block, _) = &else_expr.node {
875 if let Some(expr) = &block.expr {
877 } else if let Some(stmt) = block.stmts.last() {
878 // possibly incorrect trailing `;` in the else arm
879 remove_semicolon = self.could_remove_semicolon(block, then_ty);
881 } else { // empty block, point at its entirety
882 // Avoid overlapping spans that aren't as readable:
884 // 2 | let x = if true {
887 // | | - expected because of this
894 // | |______if and else have incompatible types
895 // | expected integer, found ()
897 // by not pointing at the entire expression:
899 // 2 | let x = if true {
900 // | ------- if and else have incompatible types
902 // | - expected because of this
907 // | |_____^ expected integer, found ()
909 if outer_sp.is_some() {
910 outer_sp = Some(self.tcx.sess.source_map().def_span(span));
914 } else { // shouldn't happen unless the parser has done something weird
918 // Compute `Span` of `then` part of `if`-expression:
919 let then_sp = if let ExprKind::Block(block, _) = &then_expr.node {
920 if let Some(expr) = &block.expr {
922 } else if let Some(stmt) = block.stmts.last() {
923 // possibly incorrect trailing `;` in the else arm
924 remove_semicolon = remove_semicolon.or(self.could_remove_semicolon(block, else_ty));
926 } else { // empty block, point at its entirety
927 outer_sp = None; // same as in `error_sp`, cleanup output
930 } else { // shouldn't happen unless the parser has done something weird
934 // Finally construct the cause:
935 self.cause(error_sp, ObligationCauseCode::IfExpression {
938 semicolon: remove_semicolon,
942 fn demand_discriminant_type(
944 arms: &'gcx [hir::Arm],
945 discrim: &'gcx hir::Expr,
947 // Not entirely obvious: if matches may create ref bindings, we want to
948 // use the *precise* type of the discriminant, *not* some supertype, as
949 // the "discriminant type" (issue #23116).
951 // arielb1 [writes here in this comment thread][c] that there
952 // is certainly *some* potential danger, e.g., for an example
955 // [c]: https://github.com/rust-lang/rust/pull/43399#discussion_r130223956
958 // let Foo(x) = f()[0];
961 // Then if the pattern matches by reference, we want to match
962 // `f()[0]` as a lexpr, so we can't allow it to be
963 // coerced. But if the pattern matches by value, `f()[0]` is
964 // still syntactically a lexpr, but we *do* want to allow
967 // However, *likely* we are ok with allowing coercions to
968 // happen if there are no explicit ref mut patterns - all
969 // implicit ref mut patterns must occur behind a reference, so
970 // they will have the "correct" variance and lifetime.
972 // This does mean that the following pattern would be legal:
977 // impl Deref for Foo {
978 // type Target = Bar;
979 // fn deref(&self) -> &Bar { &self.0 }
981 // impl DerefMut for Foo {
982 // fn deref_mut(&mut self) -> &mut Bar { &mut self.0 }
984 // fn foo(x: &mut Foo) {
986 // let Bar(z): &mut Bar = x;
989 // assert_eq!(foo.0.0, 42);
993 // FIXME(tschottdorf): don't call contains_explicit_ref_binding, which
994 // is problematic as the HIR is being scraped, but ref bindings may be
995 // implicit after #42640. We need to make sure that pat_adjustments
996 // (once introduced) is populated by the time we get here.
999 let contains_ref_bindings = arms.iter()
1000 .filter_map(|a| a.contains_explicit_ref_binding())
1001 .max_by_key(|m| match *m {
1002 hir::MutMutable => 1,
1003 hir::MutImmutable => 0,
1006 if let Some(m) = contains_ref_bindings {
1007 self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m))
1009 // ...but otherwise we want to use any supertype of the
1010 // discriminant. This is sort of a workaround, see note (*) in
1011 // `check_pat` for some details.
1012 let discrim_ty = self.next_ty_var(TypeVariableOrigin {
1013 kind: TypeVariableOriginKind::TypeInference,
1016 self.check_expr_has_type_or_error(discrim, discrim_ty);
1021 fn check_pat_struct(
1023 pat: &'gcx hir::Pat,
1025 fields: &'gcx [Spanned<hir::FieldPat>],
1028 def_bm: ty::BindingMode,
1029 discrim_span: Option<Span>,
1032 // Resolve the path and check the definition for errors.
1033 let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.hir_id)
1037 for field in fields {
1038 self.check_pat_walk(&field.node.pat, self.tcx.types.err, def_bm, discrim_span);
1040 return self.tcx.types.err;
1043 // Type-check the path.
1044 self.demand_eqtype_pat(pat.span, expected, pat_ty, discrim_span);
1046 // Type-check subpatterns.
1047 if self.check_struct_pat_fields(pat_ty, pat.hir_id, pat.span, variant, fields, etc, def_bm)
1063 // Resolve the path and check the definition for errors.
1064 let (res, opt_ty, segments) = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span);
1067 self.set_tainted_by_errors();
1068 return tcx.types.err;
1070 Res::Def(DefKind::Method, _) => {
1071 report_unexpected_variant_res(tcx, res, pat.span, qpath);
1072 return tcx.types.err;
1074 Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _) |
1075 Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => {
1076 report_unexpected_variant_res(tcx, res, pat.span, qpath);
1077 return tcx.types.err;
1079 Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::SelfCtor(..) |
1080 Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => {} // OK
1081 _ => bug!("unexpected pattern resolution: {:?}", res)
1084 // Type-check the path.
1085 let pat_ty = self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id).0;
1086 self.demand_suptype(pat.span, expected, pat_ty);
1090 fn check_pat_tuple_struct(
1094 subpats: &'gcx [P<hir::Pat>],
1095 ddpos: Option<usize>,
1097 def_bm: ty::BindingMode,
1098 match_arm_pat_span: Option<Span>,
1102 for pat in subpats {
1103 self.check_pat_walk(&pat, tcx.types.err, def_bm, match_arm_pat_span);
1106 let report_unexpected_res = |res: Res| {
1107 let msg = format!("expected tuple struct/variant, found {} `{}`",
1109 hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false)));
1110 let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg);
1111 match (res, &pat.node) {
1112 (Res::Def(DefKind::Fn, _), _) | (Res::Def(DefKind::Method, _), _) => {
1113 err.span_label(pat.span, "`fn` calls are not allowed in patterns");
1114 err.help("for more information, visit \
1115 https://doc.rust-lang.org/book/ch18-00-patterns.html");
1118 err.span_label(pat.span, "not a tuple variant or struct");
1125 // Resolve the path and check the definition for errors.
1126 let (res, opt_ty, segments) = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span);
1127 if res == Res::Err {
1128 self.set_tainted_by_errors();
1130 return self.tcx.types.err;
1133 // Type-check the path.
1134 let (pat_ty, res) = self.instantiate_value_path(segments, opt_ty, res, pat.span,
1136 if !pat_ty.is_fn() {
1137 report_unexpected_res(res);
1138 return self.tcx.types.err;
1141 let variant = match res {
1143 self.set_tainted_by_errors();
1145 return tcx.types.err;
1147 Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::Method, _) => {
1148 report_unexpected_res(res);
1149 return tcx.types.err;
1151 Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => {
1152 tcx.expect_variant_res(res)
1154 _ => bug!("unexpected pattern resolution: {:?}", res)
1157 // Replace constructor type with constructed type for tuple struct patterns.
1158 let pat_ty = pat_ty.fn_sig(tcx).output();
1159 let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
1161 self.demand_eqtype_pat(pat.span, expected, pat_ty, match_arm_pat_span);
1163 // Type-check subpatterns.
1164 if subpats.len() == variant.fields.len() ||
1165 subpats.len() < variant.fields.len() && ddpos.is_some() {
1166 let substs = match pat_ty.sty {
1167 ty::Adt(_, substs) => substs,
1168 _ => bug!("unexpected pattern type {:?}", pat_ty),
1170 for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
1171 let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
1172 self.check_pat_walk(&subpat, field_ty, def_bm, match_arm_pat_span);
1174 self.tcx.check_stability(variant.fields[i].did, Some(pat.hir_id), subpat.span);
1177 let subpats_ending = if subpats.len() == 1 { "" } else { "s" };
1178 let fields_ending = if variant.fields.len() == 1 { "" } else { "s" };
1179 struct_span_err!(tcx.sess, pat.span, E0023,
1180 "this pattern has {} field{}, but the corresponding {} has {} field{}",
1181 subpats.len(), subpats_ending, res.descr(),
1182 variant.fields.len(), fields_ending)
1183 .span_label(pat.span, format!("expected {} field{}, found {}",
1184 variant.fields.len(), fields_ending, subpats.len()))
1187 return tcx.types.err;
1192 fn check_struct_pat_fields(
1197 variant: &'tcx ty::VariantDef,
1198 fields: &'gcx [Spanned<hir::FieldPat>],
1200 def_bm: ty::BindingMode,
1204 let (substs, adt) = match adt_ty.sty {
1205 ty::Adt(adt, substs) => (substs, adt),
1206 _ => span_bug!(span, "struct pattern is not an ADT")
1208 let kind_name = adt.variant_descr();
1210 // Index the struct fields' types.
1211 let field_map = variant.fields
1214 .map(|(i, field)| (field.ident.modern(), (i, field)))
1215 .collect::<FxHashMap<_, _>>();
1217 // Keep track of which fields have already appeared in the pattern.
1218 let mut used_fields = FxHashMap::default();
1219 let mut no_field_errors = true;
1221 let mut inexistent_fields = vec![];
1222 // Typecheck each field.
1223 for &Spanned { node: ref field, span } in fields {
1224 let ident = tcx.adjust_ident(field.ident, variant.def_id);
1225 let field_ty = match used_fields.entry(ident) {
1226 Occupied(occupied) => {
1227 struct_span_err!(tcx.sess, span, E0025,
1228 "field `{}` bound multiple times \
1232 format!("multiple uses of `{}` in pattern", field.ident))
1233 .span_label(*occupied.get(), format!("first use of `{}`", field.ident))
1235 no_field_errors = false;
1239 vacant.insert(span);
1240 field_map.get(&ident)
1242 self.write_field_index(field.hir_id, *i);
1243 self.tcx.check_stability(f.did, Some(pat_id), span);
1244 self.field_ty(span, f, substs)
1246 .unwrap_or_else(|| {
1247 inexistent_fields.push(field.ident);
1248 no_field_errors = false;
1254 self.check_pat_walk(&field.pat, field_ty, def_bm, None);
1256 let mut unmentioned_fields = variant.fields
1258 .map(|field| field.ident.modern())
1259 .filter(|ident| !used_fields.contains_key(&ident))
1260 .collect::<Vec<_>>();
1261 if inexistent_fields.len() > 0 && !variant.recovered {
1262 let (field_names, t, plural) = if inexistent_fields.len() == 1 {
1263 (format!("a field named `{}`", inexistent_fields[0]), "this", "")
1265 (format!("fields named {}",
1266 inexistent_fields.iter()
1267 .map(|ident| format!("`{}`", ident))
1268 .collect::<Vec<String>>()
1269 .join(", ")), "these", "s")
1271 let spans = inexistent_fields.iter().map(|ident| ident.span).collect::<Vec<_>>();
1272 let mut err = struct_span_err!(tcx.sess,
1275 "{} `{}` does not have {}",
1277 tcx.def_path_str(variant.def_id),
1279 if let Some(ident) = inexistent_fields.last() {
1280 err.span_label(ident.span,
1281 format!("{} `{}` does not have {} field{}",
1283 tcx.def_path_str(variant.def_id),
1287 let input = unmentioned_fields.iter().map(|field| &field.name);
1288 let suggested_name =
1289 find_best_match_for_name(input, &ident.as_str(), None);
1290 if let Some(suggested_name) = suggested_name {
1291 err.span_suggestion(
1293 "a field with a similar name exists",
1294 suggested_name.to_string(),
1295 Applicability::MaybeIncorrect,
1298 // we don't want to throw `E0027` in case we have thrown `E0026` for them
1299 unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str());
1303 if tcx.sess.teach(&err.get_code().unwrap()) {
1305 "This error indicates that a struct pattern attempted to \
1306 extract a non-existent field from a struct. Struct fields \
1307 are identified by the name used before the colon : so struct \
1308 patterns should resemble the declaration of the struct type \
1310 If you are using shorthand field patterns but want to refer \
1311 to the struct field by a different name, you should rename \
1318 // Require `..` if struct has non_exhaustive attribute.
1319 if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
1320 span_err!(tcx.sess, span, E0638,
1321 "`..` required with {} marked as non-exhaustive",
1325 // Report an error if incorrect number of the fields were specified.
1326 if kind_name == "union" {
1327 if fields.len() != 1 {
1328 tcx.sess.span_err(span, "union patterns should have exactly one field");
1331 tcx.sess.span_err(span, "`..` cannot be used in union patterns");
1334 if unmentioned_fields.len() > 0 {
1335 let field_names = if unmentioned_fields.len() == 1 {
1336 format!("field `{}`", unmentioned_fields[0])
1338 format!("fields {}",
1339 unmentioned_fields.iter()
1340 .map(|name| format!("`{}`", name))
1341 .collect::<Vec<String>>()
1344 let mut diag = struct_span_err!(tcx.sess, span, E0027,
1345 "pattern does not mention {}",
1347 diag.span_label(span, format!("missing {}", field_names));
1348 if variant.ctor_kind == CtorKind::Fn {
1349 diag.note("trying to match a tuple variant with a struct variant pattern");
1351 if tcx.sess.teach(&diag.get_code().unwrap()) {
1353 "This error indicates that a pattern for a struct fails to specify a \
1354 sub-pattern for every one of the struct's fields. Ensure that each field \
1355 from the struct's definition is mentioned in the pattern, or use `..` to \
1356 ignore unwanted fields."