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, 'tcx> FnCtxt<'a, '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 mut path_resolution = None;
54 let is_non_ref_pat = match pat.node {
56 PatKind::TupleStruct(..) |
60 PatKind::Slice(..) => true,
61 PatKind::Lit(ref lt) => {
62 let ty = self.check_expr(lt);
68 PatKind::Path(ref qpath) => {
69 let resolution = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span);
70 path_resolution = Some(resolution);
72 Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => false,
77 PatKind::Binding(..) |
78 PatKind::Ref(..) => false,
81 debug!("pattern is non reference pattern");
82 let mut exp_ty = self.resolve_type_vars_with_obligations(&expected);
84 // Peel off as many `&` or `&mut` from the discriminant as possible. For example,
85 // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
86 // the `Some(5)` which is not of type Ref.
88 // For each ampersand peeled off, update the binding mode and push the original
89 // type into the adjustments vector.
91 // See the examples in `run-pass/match-defbm*.rs`.
92 let mut pat_adjustments = vec![];
93 while let ty::Ref(_, inner_ty, inner_mutability) = exp_ty.sty {
94 debug!("inspecting {:?}", exp_ty);
96 debug!("current discriminant is Ref, inserting implicit deref");
97 // Preserve the reference type. We'll need it later during HAIR lowering.
98 pat_adjustments.push(exp_ty);
101 def_bm = match def_bm {
102 // If default binding mode is by value, make it `ref` or `ref mut`
103 // (depending on whether we observe `&` or `&mut`).
104 ty::BindByValue(_) =>
105 ty::BindByReference(inner_mutability),
107 // Once a `ref`, always a `ref`. This is because a `& &mut` can't mutate
108 // the underlying value.
109 ty::BindByReference(hir::Mutability::MutImmutable) =>
110 ty::BindByReference(hir::Mutability::MutImmutable),
112 // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref`
114 ty::BindByReference(hir::Mutability::MutMutable) =>
115 ty::BindByReference(inner_mutability),
120 if pat_adjustments.len() > 0 {
121 debug!("default binding mode is now {:?}", def_bm);
122 self.inh.tables.borrow_mut()
123 .pat_adjustments_mut()
124 .insert(pat.hir_id, pat_adjustments);
126 } else if let PatKind::Ref(..) = pat.node {
127 // When you encounter a `&pat` pattern, reset to "by
128 // value". This is so that `x` and `y` here are by value,
129 // as they appear to be:
132 // match &(&22, &44) {
138 def_bm = ty::BindByValue(hir::MutImmutable);
141 // Lose mutability now that we know binding mode and discriminant type.
143 let expected = expected;
145 let ty = match pat.node {
149 PatKind::Lit(ref lt) => {
150 // We've already computed the type above (when checking for a non-ref pat), so
151 // avoid computing it again.
152 let ty = self.node_ty(lt.hir_id);
154 // Byte string patterns behave the same way as array patterns
155 // They can denote both statically and dynamically-sized byte arrays.
157 if let hir::ExprKind::Lit(ref lt) = lt.node {
158 if let ast::LitKind::ByteStr(_) = lt.node {
159 let expected_ty = self.structurally_resolved_type(pat.span, expected);
160 if let ty::Ref(_, r_ty, _) = expected_ty.sty {
161 if let ty::Slice(_) = r_ty.sty {
162 pat_ty = tcx.mk_imm_ref(tcx.lifetimes.re_static,
163 tcx.mk_slice(tcx.types.u8))
169 // Somewhat surprising: in this case, the subtyping
170 // relation goes the opposite way as the other
171 // cases. Actually what we really want is not a subtyping
172 // relation at all but rather that there exists a LUB (so
173 // that they can be compared). However, in practice,
174 // constants are always scalars or strings. For scalars
175 // subtyping is irrelevant, and for strings `ty` is
176 // type is `&'static str`, so if we say that
178 // &'static str <: expected
180 // then that's equivalent to there existing a LUB.
181 if let Some(mut err) = self.demand_suptype_diag(pat.span, expected, pat_ty) {
182 err.emit_unless(discrim_span
183 .filter(|&s| s.is_compiler_desugaring(CompilerDesugaringKind::IfTemporary))
189 PatKind::Range(ref begin, ref end, _) => {
190 let lhs_ty = self.check_expr(begin);
191 let rhs_ty = self.check_expr(end);
193 // Check that both end-points are of numeric or char type.
194 let numeric_or_char = |ty: Ty<'_>| ty.is_numeric() || ty.is_char();
195 let lhs_compat = numeric_or_char(lhs_ty);
196 let rhs_compat = numeric_or_char(rhs_ty);
198 if !lhs_compat || !rhs_compat {
199 let span = if !lhs_compat && !rhs_compat {
201 } else if !lhs_compat {
207 let mut err = struct_span_err!(
211 "only char and numeric types are allowed in range patterns"
213 err.span_label(span, "ranges require char or numeric types");
214 err.note(&format!("start type: {}", self.ty_to_string(lhs_ty)));
215 err.note(&format!("end type: {}", self.ty_to_string(rhs_ty)));
216 if tcx.sess.teach(&err.get_code().unwrap()) {
218 "In a match expression, only numbers and characters can be matched \
219 against a range. This is because the compiler checks that the range \
220 is non-empty at compile-time, and is unable to evaluate arbitrary \
221 comparison functions. If you want to capture values of an orderable \
222 type between two end-points, you can use a guard."
229 // Now that we know the types can be unified we find the unified type and use
230 // it to type the entire expression.
231 let common_type = self.resolve_vars_if_possible(&lhs_ty);
233 // Subtyping doesn't matter here, as the value is some kind of scalar.
234 self.demand_eqtype_pat(pat.span, expected, lhs_ty, discrim_span);
235 self.demand_eqtype_pat(pat.span, expected, rhs_ty, discrim_span);
238 PatKind::Binding(ba, var_id, _, ref sub) => {
239 let bm = if ba == hir::BindingAnnotation::Unannotated {
242 ty::BindingMode::convert(ba)
247 .pat_binding_modes_mut()
248 .insert(pat.hir_id, bm);
249 debug!("check_pat_walk: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
250 let local_ty = self.local_ty(pat.span, pat.hir_id).decl_ty;
252 ty::BindByReference(mutbl) => {
253 // If the binding is like
254 // ref x | ref const x | ref mut x
255 // then `x` is assigned a value of type `&M T` where M is the mutability
256 // and T is the expected type.
257 let region_var = self.next_region_var(infer::PatternRegion(pat.span));
258 let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
259 let region_ty = tcx.mk_ref(region_var, mt);
261 // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
262 // required. However, we use equality, which is stronger. See (*) for
264 self.demand_eqtype_pat(pat.span, region_ty, local_ty, discrim_span);
266 // Otherwise, the type of x is the expected type `T`.
267 ty::BindByValue(_) => {
268 // As above, `T <: typeof(x)` is required, but we
269 // use equality, see (*) below.
270 self.demand_eqtype_pat(pat.span, expected, local_ty, discrim_span);
274 // If there are multiple arms, make sure they all agree on
275 // what the type of the binding `x` ought to be.
276 if var_id != pat.hir_id {
277 let vt = self.local_ty(pat.span, var_id).decl_ty;
278 self.demand_eqtype_pat(pat.span, vt, local_ty, discrim_span);
281 if let Some(ref p) = *sub {
282 self.check_pat_walk(&p, expected, def_bm, discrim_span);
287 PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
288 self.check_pat_tuple_struct(
298 PatKind::Path(ref qpath) => {
299 self.check_pat_path(pat, path_resolution.unwrap(), qpath, expected)
301 PatKind::Struct(ref qpath, ref fields, etc) => {
302 self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, discrim_span)
304 PatKind::Tuple(ref elements, ddpos) => {
305 let mut expected_len = elements.len();
307 // Require known type only when `..` is present.
308 if let ty::Tuple(ref tys) =
309 self.structurally_resolved_type(pat.span, expected).sty {
310 expected_len = tys.len();
313 let max_len = cmp::max(expected_len, elements.len());
315 let element_tys_iter = (0..max_len).map(|_| {
316 Kind::from(self.next_ty_var(
317 // FIXME: `MiscVariable` for now -- obtaining the span and name information
318 // from all tuple elements isn't trivial.
320 kind: TypeVariableOriginKind::TypeInference,
325 let element_tys = tcx.mk_substs(element_tys_iter);
326 let pat_ty = tcx.mk_ty(ty::Tuple(element_tys));
327 if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) {
329 // Walk subpatterns with an expected type of `err` in this case to silence
330 // further errors being emitted when using the bindings. #50333
331 let element_tys_iter = (0..max_len).map(|_| tcx.types.err);
332 for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
333 self.check_pat_walk(elem, &tcx.types.err, def_bm, discrim_span);
335 tcx.mk_tup(element_tys_iter)
337 for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
340 &element_tys[i].expect_ty(),
348 PatKind::Box(ref inner) => {
349 let inner_ty = self.next_ty_var(TypeVariableOrigin {
350 kind: TypeVariableOriginKind::TypeInference,
353 let uniq_ty = tcx.mk_box(inner_ty);
355 if self.check_dereferencable(pat.span, expected, &inner) {
356 // Here, `demand::subtype` is good enough, but I don't
357 // think any errors can be introduced by using
359 self.demand_eqtype_pat(pat.span, expected, uniq_ty, discrim_span);
360 self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span);
363 self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span);
367 PatKind::Ref(ref inner, mutbl) => {
368 let expected = self.shallow_resolve(expected);
369 if self.check_dereferencable(pat.span, expected, &inner) {
370 // `demand::subtype` would be good enough, but using
371 // `eqtype` turns out to be equally general. See (*)
372 // below for details.
374 // Take region, inner-type from expected type if we
375 // can, to avoid creating needless variables. This
376 // also helps with the bad interactions of the given
377 // hack detailed in (*) below.
378 debug!("check_pat_walk: expected={:?}", expected);
379 let (rptr_ty, inner_ty) = match expected.sty {
380 ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => {
384 let inner_ty = self.next_ty_var(
386 kind: TypeVariableOriginKind::TypeInference,
390 let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
391 let region = self.next_region_var(infer::PatternRegion(pat.span));
392 let rptr_ty = tcx.mk_ref(region, mt);
393 debug!("check_pat_walk: demanding {:?} = {:?}", expected, rptr_ty);
394 let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
396 // Look for a case like `fn foo(&foo: u32)` and suggest
397 // `fn foo(foo: &u32)`
398 if let Some(mut err) = err {
399 self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected);
406 self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span);
409 self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span);
413 PatKind::Slice(ref before, ref slice, ref after) => {
414 let expected_ty = self.structurally_resolved_type(pat.span, expected);
415 let (inner_ty, slice_ty) = match expected_ty.sty {
416 ty::Array(inner_ty, size) => {
417 if let Some(size) = size.assert_usize(tcx) {
418 let min_len = before.len() as u64 + after.len() as u64;
422 tcx.sess, pat.span, E0527,
423 "pattern requires {} elements but array has {}",
425 .span_label(pat.span, format!("expected {} elements", size))
428 (inner_ty, tcx.types.err)
429 } else if let Some(rest) = size.checked_sub(min_len) {
430 (inner_ty, tcx.mk_array(inner_ty, rest))
432 struct_span_err!(tcx.sess, pat.span, E0528,
433 "pattern requires at least {} elements but array has {}",
435 .span_label(pat.span,
436 format!("pattern cannot match array of {} elements", size))
438 (inner_ty, tcx.types.err)
445 "cannot pattern-match on an array without a fixed length",
447 (inner_ty, tcx.types.err)
450 ty::Slice(inner_ty) => (inner_ty, expected_ty),
452 if !expected_ty.references_error() {
453 let mut err = struct_span_err!(
454 tcx.sess, pat.span, E0529,
455 "expected an array or slice, found `{}`",
457 if let ty::Ref(_, ty, _) = expected_ty.sty {
459 ty::Array(..) | ty::Slice(..) => {
460 err.help("the semantics of slice patterns changed \
461 recently; see issue #23121");
467 err.span_label( pat.span,
468 format!("pattern cannot match with input type `{}`", expected_ty)
471 (tcx.types.err, tcx.types.err)
476 self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span);
478 if let Some(ref slice) = *slice {
479 self.check_pat_walk(&slice, slice_ty, def_bm, discrim_span);
482 self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span);
488 self.write_ty(pat.hir_id, ty);
490 // (*) In most of the cases above (literals and constants being
491 // the exception), we relate types using strict equality, even
492 // though subtyping would be sufficient. There are a few reasons
493 // for this, some of which are fairly subtle and which cost me
494 // (nmatsakis) an hour or two debugging to remember, so I thought
495 // I'd write them down this time.
497 // 1. There is no loss of expressiveness here, though it does
498 // cause some inconvenience. What we are saying is that the type
499 // of `x` becomes *exactly* what is expected. This can cause unnecessary
500 // errors in some cases, such as this one:
503 // fn foo<'x>(x: &'x int) {
510 // The reason we might get an error is that `z` might be
511 // assigned a type like `&'x int`, and then we would have
512 // a problem when we try to assign `&a` to `z`, because
513 // the lifetime of `&a` (i.e., the enclosing block) is
514 // shorter than `'x`.
516 // HOWEVER, this code works fine. The reason is that the
517 // expected type here is whatever type the user wrote, not
518 // the initializer's type. In this case the user wrote
519 // nothing, so we are going to create a type variable `Z`.
520 // Then we will assign the type of the initializer (`&'x
521 // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
522 // will instantiate `Z` as a type `&'0 int` where `'0` is
523 // a fresh region variable, with the constraint that `'x :
524 // '0`. So basically we're all set.
526 // Note that there are two tests to check that this remains true
527 // (`regions-reassign-{match,let}-bound-pointer.rs`).
529 // 2. Things go horribly wrong if we use subtype. The reason for
530 // THIS is a fairly subtle case involving bound regions. See the
531 // `givens` field in `region_constraints`, as well as the test
532 // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
533 // for details. Short version is that we must sometimes detect
534 // relationships between specific region variables and regions
535 // bound in a closure signature, and that detection gets thrown
536 // off when we substitute fresh region variables here to enable
540 fn borrow_pat_suggestion(
542 err: &mut DiagnosticBuilder<'_>,
548 if let PatKind::Binding(..) = inner.node {
549 let parent_id = tcx.hir().get_parent_node(pat.hir_id);
550 let parent = tcx.hir().get(parent_id);
551 debug!("inner {:?} pat {:?} parent {:?}", inner, pat, parent);
553 hir::Node::Item(hir::Item { node: hir::ItemKind::Fn(..), .. }) |
554 hir::Node::ForeignItem(hir::ForeignItem {
555 node: hir::ForeignItemKind::Fn(..), ..
557 hir::Node::TraitItem(hir::TraitItem { node: hir::TraitItemKind::Method(..), .. }) |
558 hir::Node::ImplItem(hir::ImplItem { node: hir::ImplItemKind::Method(..), .. }) => {
559 // this pat is likely an argument
560 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
561 // FIXME: turn into structured suggestion, will need a span that also
562 // includes the the arg's type.
563 err.help(&format!("did you mean `{}: &{}`?", snippet, expected));
567 hir::Node::Pat(_) => {
568 // rely on match ergonomics or it might be nested `&&pat`
569 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
572 "you can probably remove the explicit borrow",
574 Applicability::MaybeIncorrect,
578 _ => {} // don't provide suggestions in other cases #55175
583 pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
584 if let PatKind::Binding(..) = inner.node {
585 if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) {
586 if let ty::Dynamic(..) = mt.ty.sty {
587 // This is "x = SomeTrait" being reduced from
588 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
589 let type_str = self.ty_to_string(expected);
590 let mut err = struct_span_err!(
594 "type `{}` cannot be dereferenced",
597 err.span_label(span, format!("type `{}` cannot be dereferenced", type_str));
598 if self.tcx.sess.teach(&err.get_code().unwrap()) {
600 This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \
601 pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \
602 this type has no compile-time size. Therefore, all accesses to trait types must be through \
603 pointers. If you encounter this error you should try to avoid dereferencing the pointer.
605 You can read more about trait objects in the Trait Objects section of the Reference: \
606 https://doc.rust-lang.org/reference/types.html#trait-objects");
618 expr: &'tcx hir::Expr,
619 discrim: &'tcx hir::Expr,
620 arms: &'tcx [hir::Arm],
621 expected: Expectation<'tcx>,
622 match_src: hir::MatchSource,
626 use hir::MatchSource::*;
627 let (source_if, if_no_else, if_desugar) = match match_src {
628 IfDesugar { contains_else_clause } => (true, !contains_else_clause, true),
629 IfLetDesugar { contains_else_clause } => (true, !contains_else_clause, false),
630 _ => (false, false, false),
633 // Type check the descriminant and get its type.
634 let discrim_ty = if if_desugar {
635 // Here we want to ensure:
637 // 1. That default match bindings are *not* accepted in the condition of an
638 // `if` expression. E.g. given `fn foo() -> &bool;` we reject `if foo() { .. }`.
640 // 2. By expecting `bool` for `expr` we get nice diagnostics for e.g. `if x = y { .. }`.
642 // FIXME(60707): Consider removing hack with principled solution.
643 self.check_expr_has_type_or_error(discrim, self.tcx.types.bool)
645 self.demand_discriminant_type(arms, discrim)
648 // If there are no arms, that is a diverging match; a special case.
650 self.diverges.set(self.diverges.get() | Diverges::Always);
651 return tcx.types.never;
654 self.warn_arms_when_scrutinee_diverges(arms, source_if);
656 // Otherwise, we have to union together the types that the
657 // arms produce and so forth.
658 let discrim_diverges = self.diverges.get();
659 self.diverges.set(Diverges::Maybe);
661 // rust-lang/rust#55810: Typecheck patterns first (via eager
662 // collection into `Vec`), so we get types for all bindings.
663 let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| {
664 let mut all_pats_diverge = Diverges::WarnedAlways;
666 self.diverges.set(Diverges::Maybe);
667 let binding_mode = ty::BindingMode::BindByValue(hir::Mutability::MutImmutable);
668 self.check_pat_walk(&p, discrim_ty, binding_mode, Some(discrim.span));
669 all_pats_diverge &= self.diverges.get();
672 // As discussed with @eddyb, this is for disabling unreachable_code
673 // warnings on patterns (they're now subsumed by unreachable_patterns
675 match all_pats_diverge {
676 Diverges::Maybe => Diverges::Maybe,
677 Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
681 // Now typecheck the blocks.
683 // The result of the match is the common supertype of all the
684 // arms. Start out the value as bottom, since it's the, well,
685 // bottom the type lattice, and we'll be moving up the lattice as
686 // we process each arm. (Note that any match with 0 arms is matching
687 // on any empty type and is therefore unreachable; should the flow
688 // of execution reach it, we will panic, so bottom is an appropriate
689 // type in that case)
690 let mut all_arms_diverge = Diverges::WarnedAlways;
692 let expected = expected.adjust_for_branches(self);
695 let coerce_first = match expected {
696 // We don't coerce to `()` so that if the match expression is a
697 // statement it's branches can have any consistent type. That allows
698 // us to give better error messages (pointing to a usually better
699 // arm for inconsistent arms or to the whole match when a `()` type
701 Expectation::ExpectHasType(ety) if ety != self.tcx.mk_unit() => ety,
702 _ => self.next_ty_var(TypeVariableOrigin {
703 kind: TypeVariableOriginKind::MiscVariable,
707 CoerceMany::with_coercion_sites(coerce_first, arms)
710 let mut other_arms = vec![]; // used only for diagnostics
711 let mut prior_arm_ty = None;
712 for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
713 if let Some(g) = &arm.guard {
714 self.diverges.set(pats_diverge);
716 hir::Guard::If(e) => self.check_expr_has_type_or_error(e, tcx.types.bool),
720 self.diverges.set(pats_diverge);
721 let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
722 all_arms_diverge &= self.diverges.get();
724 let span = expr.span;
727 let then_expr = &arms[0].body;
728 match (i, if_no_else) {
729 (0, _) => coercion.coerce(self, &self.misc(span), then_expr, arm_ty),
730 (_, true) => self.if_fallback_coercion(span, then_expr, &mut coercion),
732 let then_ty = prior_arm_ty.unwrap();
733 let cause = self.if_cause(span, then_expr, &arm.body, then_ty, arm_ty);
734 coercion.coerce(self, &cause, &arm.body, arm_ty);
738 let arm_span = if let hir::ExprKind::Block(blk, _) = &arm.body.node {
739 // Point at the block expr instead of the entire block
740 blk.expr.as_ref().map(|e| e.span).unwrap_or(arm.body.span)
744 let (span, code) = match i {
745 // The reason for the first arm to fail is not that the match arms diverge,
746 // but rather that there's a prior obligation that doesn't hold.
747 0 => (arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id)),
748 _ => (span, ObligationCauseCode::MatchExpressionArm {
751 prior_arms: other_arms.clone(),
752 last_ty: prior_arm_ty.unwrap(),
753 discrim_hir_id: discrim.hir_id,
756 let cause = self.cause(span, code);
757 coercion.coerce(self, &cause, &arm.body, arm_ty);
758 other_arms.push(arm_span);
759 if other_arms.len() > 5 {
760 other_arms.remove(0);
763 prior_arm_ty = Some(arm_ty);
766 // We won't diverge unless the discriminant or all arms diverge.
767 self.diverges.set(discrim_diverges | all_arms_diverge);
769 coercion.complete(self)
772 /// When the previously checked expression (the scrutinee) diverges,
773 /// warn the user about the match arms being unreachable.
774 fn warn_arms_when_scrutinee_diverges(&self, arms: &'tcx [hir::Arm], source_if: bool) {
775 if self.diverges.get().always() {
776 let msg = if source_if { "block in `if` expression" } else { "arm" };
778 self.warn_if_unreachable(arm.body.hir_id, arm.body.span, msg);
783 /// Handle the fallback arm of a desugared if(-let) like a missing else.
784 fn if_fallback_coercion(
787 then_expr: &'tcx hir::Expr,
788 coercion: &mut CoerceMany<'tcx, '_, rustc::hir::Arm>,
790 // If this `if` expr is the parent's function return expr,
791 // the cause of the type coercion is the return type, point at it. (#25228)
792 let ret_reason = self.maybe_get_coercion_reason(then_expr.hir_id, span);
793 let cause = self.cause(span, ObligationCauseCode::IfExpressionWithNoElse);
794 coercion.coerce_forced_unit(self, &cause, &mut |err| {
795 if let Some((span, msg)) = &ret_reason {
796 err.span_label(*span, msg.as_str());
797 } else if let ExprKind::Block(block, _) = &then_expr.node {
798 if let Some(expr) = &block.expr {
799 err.span_label(expr.span, "found here".to_string());
802 err.note("`if` expressions without `else` evaluate to `()`");
803 err.help("consider adding an `else` block that evaluates to the expected type");
804 }, ret_reason.is_none());
807 fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, span: Span) -> Option<(Span, String)> {
808 use hir::Node::{Block, Item, Local};
810 let hir = self.tcx.hir();
811 let arm_id = hir.get_parent_node(hir_id);
812 let match_id = hir.get_parent_node(arm_id);
813 let containing_id = hir.get_parent_node(match_id);
815 let node = hir.get(containing_id);
816 if let Block(block) = node {
817 // check that the body's parent is an fn
818 let parent = hir.get(
820 hir.get_parent_node(block.hir_id),
823 if let (Some(expr), Item(hir::Item {
824 node: hir::ItemKind::Fn(..), ..
825 })) = (&block.expr, parent) {
826 // check that the `if` expr without `else` is the fn body's expr
827 if expr.span == span {
828 return self.get_fn_decl(hir_id).map(|(fn_decl, _)| (
829 fn_decl.output.span(),
830 format!("expected `{}` because of this return type", fn_decl.output),
835 if let Local(hir::Local { ty: Some(_), pat, .. }) = node {
836 return Some((pat.span, "expected because of this assignment".to_string()));
844 then_expr: &'tcx hir::Expr,
845 else_expr: &'tcx hir::Expr,
848 ) -> ObligationCause<'tcx> {
849 let mut outer_sp = if self.tcx.sess.source_map().is_multiline(span) {
850 // The `if`/`else` isn't in one line in the output, include some context to make it
851 // clear it is an if/else expression:
853 // LL | let x = if true {
856 // || ----- expected because of this
859 // || ^^^^^ expected i32, found u32
861 // ||_____- if and else have incompatible types
865 // The entire expression is in one line, only point at the arms
867 // LL | let x = if true { 10i32 } else { 10u32 };
868 // | ----- ^^^^^ expected i32, found u32
870 // | expected because of this
875 let mut remove_semicolon = None;
876 let error_sp = if let ExprKind::Block(block, _) = &else_expr.node {
877 if let Some(expr) = &block.expr {
879 } else if let Some(stmt) = block.stmts.last() {
880 // possibly incorrect trailing `;` in the else arm
881 remove_semicolon = self.could_remove_semicolon(block, then_ty);
883 } else { // empty block; point at its entirety
884 // Avoid overlapping spans that aren't as readable:
886 // 2 | let x = if true {
889 // | | - expected because of this
896 // | |______if and else have incompatible types
897 // | expected integer, found ()
899 // by not pointing at the entire expression:
901 // 2 | let x = if true {
902 // | ------- if and else have incompatible types
904 // | - expected because of this
909 // | |_____^ expected integer, found ()
911 if outer_sp.is_some() {
912 outer_sp = Some(self.tcx.sess.source_map().def_span(span));
916 } else { // shouldn't happen unless the parser has done something weird
920 // Compute `Span` of `then` part of `if`-expression.
921 let then_sp = if let ExprKind::Block(block, _) = &then_expr.node {
922 if let Some(expr) = &block.expr {
924 } else if let Some(stmt) = block.stmts.last() {
925 // possibly incorrect trailing `;` in the else arm
926 remove_semicolon = remove_semicolon.or(self.could_remove_semicolon(block, else_ty));
928 } else { // empty block; point at its entirety
929 outer_sp = None; // same as in `error_sp`; cleanup output
932 } else { // shouldn't happen unless the parser has done something weird
936 // Finally construct the cause:
937 self.cause(error_sp, ObligationCauseCode::IfExpression {
940 semicolon: remove_semicolon,
944 fn demand_discriminant_type(
946 arms: &'tcx [hir::Arm],
947 discrim: &'tcx hir::Expr,
949 // Not entirely obvious: if matches may create ref bindings, we want to
950 // use the *precise* type of the discriminant, *not* some supertype, as
951 // the "discriminant type" (issue #23116).
953 // arielb1 [writes here in this comment thread][c] that there
954 // is certainly *some* potential danger, e.g., for an example
957 // [c]: https://github.com/rust-lang/rust/pull/43399#discussion_r130223956
960 // let Foo(x) = f()[0];
963 // Then if the pattern matches by reference, we want to match
964 // `f()[0]` as a lexpr, so we can't allow it to be
965 // coerced. But if the pattern matches by value, `f()[0]` is
966 // still syntactically a lexpr, but we *do* want to allow
969 // However, *likely* we are ok with allowing coercions to
970 // happen if there are no explicit ref mut patterns - all
971 // implicit ref mut patterns must occur behind a reference, so
972 // they will have the "correct" variance and lifetime.
974 // This does mean that the following pattern would be legal:
979 // impl Deref for Foo {
980 // type Target = Bar;
981 // fn deref(&self) -> &Bar { &self.0 }
983 // impl DerefMut for Foo {
984 // fn deref_mut(&mut self) -> &mut Bar { &mut self.0 }
986 // fn foo(x: &mut Foo) {
988 // let Bar(z): &mut Bar = x;
991 // assert_eq!(foo.0.0, 42);
995 // FIXME(tschottdorf): don't call contains_explicit_ref_binding, which
996 // is problematic as the HIR is being scraped, but ref bindings may be
997 // implicit after #42640. We need to make sure that pat_adjustments
998 // (once introduced) is populated by the time we get here.
1001 let contains_ref_bindings = arms.iter()
1002 .filter_map(|a| a.contains_explicit_ref_binding())
1003 .max_by_key(|m| match *m {
1004 hir::MutMutable => 1,
1005 hir::MutImmutable => 0,
1008 if let Some(m) = contains_ref_bindings {
1009 self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m))
1011 // ...but otherwise we want to use any supertype of the
1012 // discriminant. This is sort of a workaround, see note (*) in
1013 // `check_pat` for some details.
1014 let discrim_ty = self.next_ty_var(TypeVariableOrigin {
1015 kind: TypeVariableOriginKind::TypeInference,
1018 self.check_expr_has_type_or_error(discrim, discrim_ty);
1023 fn check_pat_struct(
1025 pat: &'tcx hir::Pat,
1027 fields: &'tcx [Spanned<hir::FieldPat>],
1030 def_bm: ty::BindingMode,
1031 discrim_span: Option<Span>,
1033 // Resolve the path and check the definition for errors.
1034 let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.hir_id)
1038 for field in fields {
1039 self.check_pat_walk(&field.node.pat, self.tcx.types.err, def_bm, discrim_span);
1041 return self.tcx.types.err;
1044 // Type-check the path.
1045 self.demand_eqtype_pat(pat.span, expected, pat_ty, discrim_span);
1047 // Type-check subpatterns.
1048 if self.check_struct_pat_fields(pat_ty, pat.hir_id, pat.span, variant, fields, etc, def_bm)
1059 path_resolution: (Res, Option<Ty<'tcx>>, &'b [hir::PathSegment]),
1065 // We have already resolved the path.
1066 let (res, opt_ty, segments) = path_resolution;
1069 self.set_tainted_by_errors();
1070 return tcx.types.err;
1072 Res::Def(DefKind::Method, _) |
1073 Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _) |
1074 Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => {
1075 report_unexpected_variant_res(tcx, res, pat.span, qpath);
1076 return tcx.types.err;
1078 Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::SelfCtor(..) |
1079 Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => {} // OK
1080 _ => bug!("unexpected pattern resolution: {:?}", res)
1083 // Type-check the path.
1084 let pat_ty = self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id).0;
1085 self.demand_suptype(pat.span, expected, pat_ty);
1089 fn check_pat_tuple_struct(
1093 subpats: &'tcx [P<hir::Pat>],
1094 ddpos: Option<usize>,
1096 def_bm: ty::BindingMode,
1097 match_arm_pat_span: Option<Span>,
1101 for pat in subpats {
1102 self.check_pat_walk(&pat, tcx.types.err, def_bm, match_arm_pat_span);
1105 let report_unexpected_res = |res: Res| {
1106 let msg = format!("expected tuple struct/variant, found {} `{}`",
1108 hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false)));
1109 let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg);
1110 match (res, &pat.node) {
1111 (Res::Def(DefKind::Fn, _), _) | (Res::Def(DefKind::Method, _), _) => {
1112 err.span_label(pat.span, "`fn` calls are not allowed in patterns");
1113 err.help("for more information, visit \
1114 https://doc.rust-lang.org/book/ch18-00-patterns.html");
1117 err.span_label(pat.span, "not a tuple variant or struct");
1124 // Resolve the path and check the definition for errors.
1125 let (res, opt_ty, segments) = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span);
1126 if res == Res::Err {
1127 self.set_tainted_by_errors();
1129 return self.tcx.types.err;
1132 // Type-check the path.
1133 let (pat_ty, res) = self.instantiate_value_path(segments, opt_ty, res, pat.span,
1135 if !pat_ty.is_fn() {
1136 report_unexpected_res(res);
1137 return self.tcx.types.err;
1140 let variant = match res {
1142 self.set_tainted_by_errors();
1144 return tcx.types.err;
1146 Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::Method, _) => {
1147 report_unexpected_res(res);
1148 return tcx.types.err;
1150 Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => {
1151 tcx.expect_variant_res(res)
1153 _ => bug!("unexpected pattern resolution: {:?}", res)
1156 // Replace constructor type with constructed type for tuple struct patterns.
1157 let pat_ty = pat_ty.fn_sig(tcx).output();
1158 let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
1160 self.demand_eqtype_pat(pat.span, expected, pat_ty, match_arm_pat_span);
1162 // Type-check subpatterns.
1163 if subpats.len() == variant.fields.len() ||
1164 subpats.len() < variant.fields.len() && ddpos.is_some() {
1165 let substs = match pat_ty.sty {
1166 ty::Adt(_, substs) => substs,
1167 _ => bug!("unexpected pattern type {:?}", pat_ty),
1169 for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
1170 let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
1171 self.check_pat_walk(&subpat, field_ty, def_bm, match_arm_pat_span);
1173 self.tcx.check_stability(variant.fields[i].did, Some(pat.hir_id), subpat.span);
1176 let subpats_ending = if subpats.len() == 1 { "" } else { "s" };
1177 let fields_ending = if variant.fields.len() == 1 { "" } else { "s" };
1178 struct_span_err!(tcx.sess, pat.span, E0023,
1179 "this pattern has {} field{}, but the corresponding {} has {} field{}",
1180 subpats.len(), subpats_ending, res.descr(),
1181 variant.fields.len(), fields_ending)
1182 .span_label(pat.span, format!("expected {} field{}, found {}",
1183 variant.fields.len(), fields_ending, subpats.len()))
1186 return tcx.types.err;
1191 fn check_struct_pat_fields(
1196 variant: &'tcx ty::VariantDef,
1197 fields: &'tcx [Spanned<hir::FieldPat>],
1199 def_bm: ty::BindingMode,
1203 let (substs, adt) = match adt_ty.sty {
1204 ty::Adt(adt, substs) => (substs, adt),
1205 _ => span_bug!(span, "struct pattern is not an ADT")
1207 let kind_name = adt.variant_descr();
1209 // Index the struct fields' types.
1210 let field_map = variant.fields
1213 .map(|(i, field)| (field.ident.modern(), (i, field)))
1214 .collect::<FxHashMap<_, _>>();
1216 // Keep track of which fields have already appeared in the pattern.
1217 let mut used_fields = FxHashMap::default();
1218 let mut no_field_errors = true;
1220 let mut inexistent_fields = vec![];
1221 // Typecheck each field.
1222 for &Spanned { node: ref field, span } in fields {
1223 let ident = tcx.adjust_ident(field.ident, variant.def_id);
1224 let field_ty = match used_fields.entry(ident) {
1225 Occupied(occupied) => {
1226 struct_span_err!(tcx.sess, span, E0025,
1227 "field `{}` bound multiple times \
1231 format!("multiple uses of `{}` in pattern", field.ident))
1232 .span_label(*occupied.get(), format!("first use of `{}`", field.ident))
1234 no_field_errors = false;
1238 vacant.insert(span);
1239 field_map.get(&ident)
1241 self.write_field_index(field.hir_id, *i);
1242 self.tcx.check_stability(f.did, Some(pat_id), span);
1243 self.field_ty(span, f, substs)
1245 .unwrap_or_else(|| {
1246 inexistent_fields.push(field.ident);
1247 no_field_errors = false;
1253 self.check_pat_walk(&field.pat, field_ty, def_bm, None);
1255 let mut unmentioned_fields = variant.fields
1257 .map(|field| field.ident.modern())
1258 .filter(|ident| !used_fields.contains_key(&ident))
1259 .collect::<Vec<_>>();
1260 if inexistent_fields.len() > 0 && !variant.recovered {
1261 let (field_names, t, plural) = if inexistent_fields.len() == 1 {
1262 (format!("a field named `{}`", inexistent_fields[0]), "this", "")
1264 (format!("fields named {}",
1265 inexistent_fields.iter()
1266 .map(|ident| format!("`{}`", ident))
1267 .collect::<Vec<String>>()
1268 .join(", ")), "these", "s")
1270 let spans = inexistent_fields.iter().map(|ident| ident.span).collect::<Vec<_>>();
1271 let mut err = struct_span_err!(tcx.sess,
1274 "{} `{}` does not have {}",
1276 tcx.def_path_str(variant.def_id),
1278 if let Some(ident) = inexistent_fields.last() {
1279 err.span_label(ident.span,
1280 format!("{} `{}` does not have {} field{}",
1282 tcx.def_path_str(variant.def_id),
1286 let input = unmentioned_fields.iter().map(|field| &field.name);
1287 let suggested_name =
1288 find_best_match_for_name(input, &ident.as_str(), None);
1289 if let Some(suggested_name) = suggested_name {
1290 err.span_suggestion(
1292 "a field with a similar name exists",
1293 suggested_name.to_string(),
1294 Applicability::MaybeIncorrect,
1297 // we don't want to throw `E0027` in case we have thrown `E0026` for them
1298 unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str());
1302 if tcx.sess.teach(&err.get_code().unwrap()) {
1304 "This error indicates that a struct pattern attempted to \
1305 extract a non-existent field from a struct. Struct fields \
1306 are identified by the name used before the colon : so struct \
1307 patterns should resemble the declaration of the struct type \
1309 If you are using shorthand field patterns but want to refer \
1310 to the struct field by a different name, you should rename \
1317 // Require `..` if struct has non_exhaustive attribute.
1318 if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
1319 span_err!(tcx.sess, span, E0638,
1320 "`..` required with {} marked as non-exhaustive",
1324 // Report an error if incorrect number of the fields were specified.
1325 if kind_name == "union" {
1326 if fields.len() != 1 {
1327 tcx.sess.span_err(span, "union patterns should have exactly one field");
1330 tcx.sess.span_err(span, "`..` cannot be used in union patterns");
1333 if unmentioned_fields.len() > 0 {
1334 let field_names = if unmentioned_fields.len() == 1 {
1335 format!("field `{}`", unmentioned_fields[0])
1337 format!("fields {}",
1338 unmentioned_fields.iter()
1339 .map(|name| format!("`{}`", name))
1340 .collect::<Vec<String>>()
1343 let mut diag = struct_span_err!(tcx.sess, span, E0027,
1344 "pattern does not mention {}",
1346 diag.span_label(span, format!("missing {}", field_names));
1347 if variant.ctor_kind == CtorKind::Fn {
1348 diag.note("trying to match a tuple variant with a struct variant pattern");
1350 if tcx.sess.teach(&diag.get_code().unwrap()) {
1352 "This error indicates that a pattern for a struct fails to specify a \
1353 sub-pattern for every one of the struct's fields. Ensure that each field \
1354 from the struct's definition is mentioned in the pattern, or use `..` to \
1355 ignore unwanted fields."