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;
8 use rustc::hir::ptr::P;
10 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
11 use rustc::traits::{ObligationCause, ObligationCauseCode};
12 use rustc::ty::{self, Ty, TypeFoldable};
13 use rustc::ty::subst::Kind;
15 use syntax::source_map::Spanned;
16 use syntax::util::lev_distance::find_best_match_for_name;
18 use syntax_pos::hygiene::DesugaringKind;
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 `ui/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
184 // In the case of `if`- and `while`-expressions we've already checked
185 // that `scrutinee: bool`. We know that the pattern is `true`,
186 // so an error here would be a duplicate and from the wrong POV.
187 s.is_desugaring(DesugaringKind::CondTemporary)
194 PatKind::Range(ref begin, ref end, _) => {
195 let lhs_ty = self.check_expr(begin);
196 let rhs_ty = self.check_expr(end);
198 // Check that both end-points are of numeric or char type.
199 let numeric_or_char = |ty: Ty<'_>| {
202 || ty.references_error()
204 let lhs_compat = numeric_or_char(lhs_ty);
205 let rhs_compat = numeric_or_char(rhs_ty);
207 if !lhs_compat || !rhs_compat {
208 let span = if !lhs_compat && !rhs_compat {
210 } else if !lhs_compat {
216 let mut err = struct_span_err!(
220 "only char and numeric types are allowed in range patterns"
222 err.span_label(span, "ranges require char or numeric types");
223 err.note(&format!("start type: {}", self.ty_to_string(lhs_ty)));
224 err.note(&format!("end type: {}", self.ty_to_string(rhs_ty)));
225 if tcx.sess.teach(&err.get_code().unwrap()) {
227 "In a match expression, only numbers and characters can be matched \
228 against a range. This is because the compiler checks that the range \
229 is non-empty at compile-time, and is unable to evaluate arbitrary \
230 comparison functions. If you want to capture values of an orderable \
231 type between two end-points, you can use a guard."
238 // Now that we know the types can be unified we find the unified type and use
239 // it to type the entire expression.
240 let common_type = self.resolve_vars_if_possible(&lhs_ty);
242 // Subtyping doesn't matter here, as the value is some kind of scalar.
243 self.demand_eqtype_pat(pat.span, expected, lhs_ty, discrim_span);
244 self.demand_eqtype_pat(pat.span, expected, rhs_ty, discrim_span);
247 PatKind::Binding(ba, var_id, _, ref sub) => {
248 let bm = if ba == hir::BindingAnnotation::Unannotated {
251 ty::BindingMode::convert(ba)
256 .pat_binding_modes_mut()
257 .insert(pat.hir_id, bm);
258 debug!("check_pat_walk: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
259 let local_ty = self.local_ty(pat.span, pat.hir_id).decl_ty;
261 ty::BindByReference(mutbl) => {
262 // If the binding is like
263 // ref x | ref const x | ref mut x
264 // then `x` is assigned a value of type `&M T` where M is the mutability
265 // and T is the expected type.
266 let region_var = self.next_region_var(infer::PatternRegion(pat.span));
267 let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
268 let region_ty = tcx.mk_ref(region_var, mt);
270 // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
271 // required. However, we use equality, which is stronger. See (*) for
273 self.demand_eqtype_pat(pat.span, region_ty, local_ty, discrim_span);
275 // Otherwise, the type of x is the expected type `T`.
276 ty::BindByValue(_) => {
277 // As above, `T <: typeof(x)` is required, but we
278 // use equality, see (*) below.
279 self.demand_eqtype_pat(pat.span, expected, local_ty, discrim_span);
283 // If there are multiple arms, make sure they all agree on
284 // what the type of the binding `x` ought to be.
285 if var_id != pat.hir_id {
286 let vt = self.local_ty(pat.span, var_id).decl_ty;
287 self.demand_eqtype_pat(pat.span, vt, local_ty, discrim_span);
290 if let Some(ref p) = *sub {
291 self.check_pat_walk(&p, expected, def_bm, discrim_span);
296 PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
297 self.check_pat_tuple_struct(
307 PatKind::Path(ref qpath) => {
308 self.check_pat_path(pat, path_resolution.unwrap(), qpath, expected)
310 PatKind::Struct(ref qpath, ref fields, etc) => {
311 self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, discrim_span)
313 PatKind::Tuple(ref elements, ddpos) => {
314 let mut expected_len = elements.len();
316 // Require known type only when `..` is present.
317 if let ty::Tuple(ref tys) =
318 self.structurally_resolved_type(pat.span, expected).sty {
319 expected_len = tys.len();
322 let max_len = cmp::max(expected_len, elements.len());
324 let element_tys_iter = (0..max_len).map(|_| {
325 Kind::from(self.next_ty_var(
326 // FIXME: `MiscVariable` for now -- obtaining the span and name information
327 // from all tuple elements isn't trivial.
329 kind: TypeVariableOriginKind::TypeInference,
334 let element_tys = tcx.mk_substs(element_tys_iter);
335 let pat_ty = tcx.mk_ty(ty::Tuple(element_tys));
336 if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) {
338 // Walk subpatterns with an expected type of `err` in this case to silence
339 // further errors being emitted when using the bindings. #50333
340 let element_tys_iter = (0..max_len).map(|_| tcx.types.err);
341 for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
342 self.check_pat_walk(elem, &tcx.types.err, def_bm, discrim_span);
344 tcx.mk_tup(element_tys_iter)
346 for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
349 &element_tys[i].expect_ty(),
357 PatKind::Box(ref inner) => {
358 let inner_ty = self.next_ty_var(TypeVariableOrigin {
359 kind: TypeVariableOriginKind::TypeInference,
362 let uniq_ty = tcx.mk_box(inner_ty);
364 if self.check_dereferencable(pat.span, expected, &inner) {
365 // Here, `demand::subtype` is good enough, but I don't
366 // think any errors can be introduced by using
368 self.demand_eqtype_pat(pat.span, expected, uniq_ty, discrim_span);
369 self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span);
372 self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span);
376 PatKind::Ref(ref inner, mutbl) => {
377 let expected = self.shallow_resolve(expected);
378 if self.check_dereferencable(pat.span, expected, &inner) {
379 // `demand::subtype` would be good enough, but using
380 // `eqtype` turns out to be equally general. See (*)
381 // below for details.
383 // Take region, inner-type from expected type if we
384 // can, to avoid creating needless variables. This
385 // also helps with the bad interactions of the given
386 // hack detailed in (*) below.
387 debug!("check_pat_walk: expected={:?}", expected);
388 let (rptr_ty, inner_ty) = match expected.sty {
389 ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => {
393 let inner_ty = self.next_ty_var(
395 kind: TypeVariableOriginKind::TypeInference,
399 let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
400 let region = self.next_region_var(infer::PatternRegion(pat.span));
401 let rptr_ty = tcx.mk_ref(region, mt);
402 debug!("check_pat_walk: demanding {:?} = {:?}", expected, rptr_ty);
403 let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
405 // Look for a case like `fn foo(&foo: u32)` and suggest
406 // `fn foo(foo: &u32)`
407 if let Some(mut err) = err {
408 self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected);
415 self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span);
418 self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span);
422 PatKind::Slice(ref before, ref slice, ref after) => {
423 let expected_ty = self.structurally_resolved_type(pat.span, expected);
424 let (inner_ty, slice_ty) = match expected_ty.sty {
425 ty::Array(inner_ty, size) => {
426 if let Some(size) = size.assert_usize(tcx) {
427 let min_len = before.len() as u64 + after.len() as u64;
431 tcx.sess, pat.span, E0527,
432 "pattern requires {} elements but array has {}",
434 .span_label(pat.span, format!("expected {} elements", size))
437 (inner_ty, tcx.types.err)
438 } else if let Some(rest) = size.checked_sub(min_len) {
439 (inner_ty, tcx.mk_array(inner_ty, rest))
441 struct_span_err!(tcx.sess, pat.span, E0528,
442 "pattern requires at least {} elements but array has {}",
444 .span_label(pat.span,
445 format!("pattern cannot match array of {} elements", size))
447 (inner_ty, tcx.types.err)
454 "cannot pattern-match on an array without a fixed length",
456 (inner_ty, tcx.types.err)
459 ty::Slice(inner_ty) => (inner_ty, expected_ty),
461 if !expected_ty.references_error() {
462 let mut err = struct_span_err!(
463 tcx.sess, pat.span, E0529,
464 "expected an array or slice, found `{}`",
466 if let ty::Ref(_, ty, _) = expected_ty.sty {
468 ty::Array(..) | ty::Slice(..) => {
469 err.help("the semantics of slice patterns changed \
470 recently; see issue #62254");
476 err.span_label( pat.span,
477 format!("pattern cannot match with input type `{}`", expected_ty)
480 (tcx.types.err, tcx.types.err)
485 self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span);
487 if let Some(ref slice) = *slice {
488 self.check_pat_walk(&slice, slice_ty, def_bm, discrim_span);
491 self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span);
497 self.write_ty(pat.hir_id, ty);
499 // (*) In most of the cases above (literals and constants being
500 // the exception), we relate types using strict equality, even
501 // though subtyping would be sufficient. There are a few reasons
502 // for this, some of which are fairly subtle and which cost me
503 // (nmatsakis) an hour or two debugging to remember, so I thought
504 // I'd write them down this time.
506 // 1. There is no loss of expressiveness here, though it does
507 // cause some inconvenience. What we are saying is that the type
508 // of `x` becomes *exactly* what is expected. This can cause unnecessary
509 // errors in some cases, such as this one:
512 // fn foo<'x>(x: &'x int) {
519 // The reason we might get an error is that `z` might be
520 // assigned a type like `&'x int`, and then we would have
521 // a problem when we try to assign `&a` to `z`, because
522 // the lifetime of `&a` (i.e., the enclosing block) is
523 // shorter than `'x`.
525 // HOWEVER, this code works fine. The reason is that the
526 // expected type here is whatever type the user wrote, not
527 // the initializer's type. In this case the user wrote
528 // nothing, so we are going to create a type variable `Z`.
529 // Then we will assign the type of the initializer (`&'x
530 // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
531 // will instantiate `Z` as a type `&'0 int` where `'0` is
532 // a fresh region variable, with the constraint that `'x :
533 // '0`. So basically we're all set.
535 // Note that there are two tests to check that this remains true
536 // (`regions-reassign-{match,let}-bound-pointer.rs`).
538 // 2. Things go horribly wrong if we use subtype. The reason for
539 // THIS is a fairly subtle case involving bound regions. See the
540 // `givens` field in `region_constraints`, as well as the test
541 // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
542 // for details. Short version is that we must sometimes detect
543 // relationships between specific region variables and regions
544 // bound in a closure signature, and that detection gets thrown
545 // off when we substitute fresh region variables here to enable
549 fn borrow_pat_suggestion(
551 err: &mut DiagnosticBuilder<'_>,
557 if let PatKind::Binding(..) = inner.node {
558 let binding_parent_id = tcx.hir().get_parent_node(pat.hir_id);
559 let binding_parent = tcx.hir().get(binding_parent_id);
560 debug!("inner {:?} pat {:?} parent {:?}", inner, pat, binding_parent);
561 match binding_parent {
562 hir::Node::Arg(hir::Arg { span, .. }) => {
563 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
566 &format!("did you mean `{}`", snippet),
567 format!(" &{}", expected),
568 Applicability::MachineApplicable,
573 hir::Node::Pat(_) => {
574 // rely on match ergonomics or it might be nested `&&pat`
575 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
578 "you can probably remove the explicit borrow",
580 Applicability::MaybeIncorrect,
584 _ => {} // don't provide suggestions in other cases #55175
589 pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
590 if let PatKind::Binding(..) = inner.node {
591 if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) {
592 if let ty::Dynamic(..) = mt.ty.sty {
593 // This is "x = SomeTrait" being reduced from
594 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
595 let type_str = self.ty_to_string(expected);
596 let mut err = struct_span_err!(
600 "type `{}` cannot be dereferenced",
603 err.span_label(span, format!("type `{}` cannot be dereferenced", type_str));
604 if self.tcx.sess.teach(&err.get_code().unwrap()) {
606 This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \
607 pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \
608 this type has no compile-time size. Therefore, all accesses to trait types must be through \
609 pointers. If you encounter this error you should try to avoid dereferencing the pointer.
611 You can read more about trait objects in the Trait Objects section of the Reference: \
612 https://doc.rust-lang.org/reference/types.html#trait-objects");
624 expr: &'tcx hir::Expr,
625 discrim: &'tcx hir::Expr,
626 arms: &'tcx [hir::Arm],
627 expected: Expectation<'tcx>,
628 match_src: hir::MatchSource,
632 use hir::MatchSource::*;
633 let (source_if, if_no_else, force_scrutinee_bool) = match match_src {
634 IfDesugar { contains_else_clause } => (true, !contains_else_clause, true),
635 IfLetDesugar { contains_else_clause } => (true, !contains_else_clause, false),
636 WhileDesugar => (false, false, true),
637 _ => (false, false, false),
640 // Type check the descriminant and get its type.
641 let discrim_ty = if force_scrutinee_bool {
642 // Here we want to ensure:
644 // 1. That default match bindings are *not* accepted in the condition of an
645 // `if` expression. E.g. given `fn foo() -> &bool;` we reject `if foo() { .. }`.
647 // 2. By expecting `bool` for `expr` we get nice diagnostics for e.g. `if x = y { .. }`.
649 // FIXME(60707): Consider removing hack with principled solution.
650 self.check_expr_has_type_or_error(discrim, self.tcx.types.bool)
652 self.demand_discriminant_type(arms, discrim)
655 // If there are no arms, that is a diverging match; a special case.
657 self.diverges.set(self.diverges.get() | Diverges::Always);
658 return tcx.types.never;
661 self.warn_arms_when_scrutinee_diverges(arms, match_src);
663 // Otherwise, we have to union together the types that the
664 // arms produce and so forth.
665 let discrim_diverges = self.diverges.get();
666 self.diverges.set(Diverges::Maybe);
668 // rust-lang/rust#55810: Typecheck patterns first (via eager
669 // collection into `Vec`), so we get types for all bindings.
670 let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| {
671 let mut all_pats_diverge = Diverges::WarnedAlways;
673 self.diverges.set(Diverges::Maybe);
674 let binding_mode = ty::BindingMode::BindByValue(hir::Mutability::MutImmutable);
675 self.check_pat_walk(&p, discrim_ty, binding_mode, Some(discrim.span));
676 all_pats_diverge &= self.diverges.get();
679 // As discussed with @eddyb, this is for disabling unreachable_code
680 // warnings on patterns (they're now subsumed by unreachable_patterns
682 match all_pats_diverge {
683 Diverges::Maybe => Diverges::Maybe,
684 Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
688 // Now typecheck the blocks.
690 // The result of the match is the common supertype of all the
691 // arms. Start out the value as bottom, since it's the, well,
692 // bottom the type lattice, and we'll be moving up the lattice as
693 // we process each arm. (Note that any match with 0 arms is matching
694 // on any empty type and is therefore unreachable; should the flow
695 // of execution reach it, we will panic, so bottom is an appropriate
696 // type in that case)
697 let mut all_arms_diverge = Diverges::WarnedAlways;
699 let expected = expected.adjust_for_branches(self);
702 let coerce_first = match expected {
703 // We don't coerce to `()` so that if the match expression is a
704 // statement it's branches can have any consistent type. That allows
705 // us to give better error messages (pointing to a usually better
706 // arm for inconsistent arms or to the whole match when a `()` type
708 Expectation::ExpectHasType(ety) if ety != self.tcx.mk_unit() => ety,
709 _ => self.next_ty_var(TypeVariableOrigin {
710 kind: TypeVariableOriginKind::MiscVariable,
714 CoerceMany::with_coercion_sites(coerce_first, arms)
717 let mut other_arms = vec![]; // used only for diagnostics
718 let mut prior_arm_ty = None;
719 for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
720 if let Some(g) = &arm.guard {
721 self.diverges.set(pats_diverge);
723 hir::Guard::If(e) => self.check_expr_has_type_or_error(e, tcx.types.bool),
727 self.diverges.set(pats_diverge);
728 let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
729 all_arms_diverge &= self.diverges.get();
731 let span = expr.span;
734 let then_expr = &arms[0].body;
735 match (i, if_no_else) {
736 (0, _) => coercion.coerce(self, &self.misc(span), &arm.body, arm_ty),
737 (_, true) => self.if_fallback_coercion(span, then_expr, &mut coercion),
739 let then_ty = prior_arm_ty.unwrap();
740 let cause = self.if_cause(span, then_expr, &arm.body, then_ty, arm_ty);
741 coercion.coerce(self, &cause, &arm.body, arm_ty);
745 let arm_span = if let hir::ExprKind::Block(blk, _) = &arm.body.node {
746 // Point at the block expr instead of the entire block
747 blk.expr.as_ref().map(|e| e.span).unwrap_or(arm.body.span)
751 let (span, code) = match i {
752 // The reason for the first arm to fail is not that the match arms diverge,
753 // but rather that there's a prior obligation that doesn't hold.
754 0 => (arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id)),
755 _ => (span, ObligationCauseCode::MatchExpressionArm {
758 prior_arms: other_arms.clone(),
759 last_ty: prior_arm_ty.unwrap(),
760 discrim_hir_id: discrim.hir_id,
763 let cause = self.cause(span, code);
764 coercion.coerce(self, &cause, &arm.body, arm_ty);
765 other_arms.push(arm_span);
766 if other_arms.len() > 5 {
767 other_arms.remove(0);
770 prior_arm_ty = Some(arm_ty);
773 // We won't diverge unless the discriminant or all arms diverge.
774 self.diverges.set(discrim_diverges | all_arms_diverge);
776 coercion.complete(self)
779 /// When the previously checked expression (the scrutinee) diverges,
780 /// warn the user about the match arms being unreachable.
781 fn warn_arms_when_scrutinee_diverges(&self, arms: &'tcx [hir::Arm], source: hir::MatchSource) {
782 if self.diverges.get().always() {
783 use hir::MatchSource::*;
784 let msg = match source {
785 IfDesugar { .. } | IfLetDesugar { .. } => "block in `if` expression",
786 WhileDesugar { .. } | WhileLetDesugar { .. } => "block in `while` expression",
790 self.warn_if_unreachable(arm.body.hir_id, arm.body.span, msg);
795 /// Handle the fallback arm of a desugared if(-let) like a missing else.
796 fn if_fallback_coercion(
799 then_expr: &'tcx hir::Expr,
800 coercion: &mut CoerceMany<'tcx, '_, rustc::hir::Arm>,
802 // If this `if` expr is the parent's function return expr,
803 // the cause of the type coercion is the return type, point at it. (#25228)
804 let ret_reason = self.maybe_get_coercion_reason(then_expr.hir_id, span);
805 let cause = self.cause(span, ObligationCauseCode::IfExpressionWithNoElse);
806 coercion.coerce_forced_unit(self, &cause, &mut |err| {
807 if let Some((span, msg)) = &ret_reason {
808 err.span_label(*span, msg.as_str());
809 } else if let ExprKind::Block(block, _) = &then_expr.node {
810 if let Some(expr) = &block.expr {
811 err.span_label(expr.span, "found here".to_string());
814 err.note("`if` expressions without `else` evaluate to `()`");
815 err.help("consider adding an `else` block that evaluates to the expected type");
816 }, ret_reason.is_none());
819 fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, span: Span) -> Option<(Span, String)> {
820 use hir::Node::{Block, Item, Local};
822 let hir = self.tcx.hir();
823 let arm_id = hir.get_parent_node(hir_id);
824 let match_id = hir.get_parent_node(arm_id);
825 let containing_id = hir.get_parent_node(match_id);
827 let node = hir.get(containing_id);
828 if let Block(block) = node {
829 // check that the body's parent is an fn
830 let parent = hir.get(
832 hir.get_parent_node(block.hir_id),
835 if let (Some(expr), Item(hir::Item {
836 node: hir::ItemKind::Fn(..), ..
837 })) = (&block.expr, parent) {
838 // check that the `if` expr without `else` is the fn body's expr
839 if expr.span == span {
840 return self.get_fn_decl(hir_id).map(|(fn_decl, _)| (
841 fn_decl.output.span(),
842 format!("expected `{}` because of this return type", fn_decl.output),
847 if let Local(hir::Local { ty: Some(_), pat, .. }) = node {
848 return Some((pat.span, "expected because of this assignment".to_string()));
856 then_expr: &'tcx hir::Expr,
857 else_expr: &'tcx hir::Expr,
860 ) -> ObligationCause<'tcx> {
861 let mut outer_sp = if self.tcx.sess.source_map().is_multiline(span) {
862 // The `if`/`else` isn't in one line in the output, include some context to make it
863 // clear it is an if/else expression:
865 // LL | let x = if true {
868 // || ----- expected because of this
871 // || ^^^^^ expected i32, found u32
873 // ||_____- if and else have incompatible types
877 // The entire expression is in one line, only point at the arms
879 // LL | let x = if true { 10i32 } else { 10u32 };
880 // | ----- ^^^^^ expected i32, found u32
882 // | expected because of this
887 let mut remove_semicolon = None;
888 let error_sp = if let ExprKind::Block(block, _) = &else_expr.node {
889 if let Some(expr) = &block.expr {
891 } else if let Some(stmt) = block.stmts.last() {
892 // possibly incorrect trailing `;` in the else arm
893 remove_semicolon = self.could_remove_semicolon(block, then_ty);
895 } else { // empty block; point at its entirety
896 // Avoid overlapping spans that aren't as readable:
898 // 2 | let x = if true {
901 // | | - expected because of this
908 // | |______if and else have incompatible types
909 // | expected integer, found ()
911 // by not pointing at the entire expression:
913 // 2 | let x = if true {
914 // | ------- if and else have incompatible types
916 // | - expected because of this
921 // | |_____^ expected integer, found ()
923 if outer_sp.is_some() {
924 outer_sp = Some(self.tcx.sess.source_map().def_span(span));
928 } else { // shouldn't happen unless the parser has done something weird
932 // Compute `Span` of `then` part of `if`-expression.
933 let then_sp = if let ExprKind::Block(block, _) = &then_expr.node {
934 if let Some(expr) = &block.expr {
936 } else if let Some(stmt) = block.stmts.last() {
937 // possibly incorrect trailing `;` in the else arm
938 remove_semicolon = remove_semicolon.or(self.could_remove_semicolon(block, else_ty));
940 } else { // empty block; point at its entirety
941 outer_sp = None; // same as in `error_sp`; cleanup output
944 } else { // shouldn't happen unless the parser has done something weird
948 // Finally construct the cause:
949 self.cause(error_sp, ObligationCauseCode::IfExpression {
952 semicolon: remove_semicolon,
956 fn demand_discriminant_type(
958 arms: &'tcx [hir::Arm],
959 discrim: &'tcx hir::Expr,
961 // Not entirely obvious: if matches may create ref bindings, we want to
962 // use the *precise* type of the discriminant, *not* some supertype, as
963 // the "discriminant type" (issue #23116).
965 // arielb1 [writes here in this comment thread][c] that there
966 // is certainly *some* potential danger, e.g., for an example
969 // [c]: https://github.com/rust-lang/rust/pull/43399#discussion_r130223956
972 // let Foo(x) = f()[0];
975 // Then if the pattern matches by reference, we want to match
976 // `f()[0]` as a lexpr, so we can't allow it to be
977 // coerced. But if the pattern matches by value, `f()[0]` is
978 // still syntactically a lexpr, but we *do* want to allow
981 // However, *likely* we are ok with allowing coercions to
982 // happen if there are no explicit ref mut patterns - all
983 // implicit ref mut patterns must occur behind a reference, so
984 // they will have the "correct" variance and lifetime.
986 // This does mean that the following pattern would be legal:
991 // impl Deref for Foo {
992 // type Target = Bar;
993 // fn deref(&self) -> &Bar { &self.0 }
995 // impl DerefMut for Foo {
996 // fn deref_mut(&mut self) -> &mut Bar { &mut self.0 }
998 // fn foo(x: &mut Foo) {
1000 // let Bar(z): &mut Bar = x;
1003 // assert_eq!(foo.0.0, 42);
1007 // FIXME(tschottdorf): don't call contains_explicit_ref_binding, which
1008 // is problematic as the HIR is being scraped, but ref bindings may be
1009 // implicit after #42640. We need to make sure that pat_adjustments
1010 // (once introduced) is populated by the time we get here.
1013 let contains_ref_bindings = arms.iter()
1014 .filter_map(|a| a.contains_explicit_ref_binding())
1015 .max_by_key(|m| match *m {
1016 hir::MutMutable => 1,
1017 hir::MutImmutable => 0,
1020 if let Some(m) = contains_ref_bindings {
1021 self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m))
1023 // ...but otherwise we want to use any supertype of the
1024 // discriminant. This is sort of a workaround, see note (*) in
1025 // `check_pat` for some details.
1026 let discrim_ty = self.next_ty_var(TypeVariableOrigin {
1027 kind: TypeVariableOriginKind::TypeInference,
1030 self.check_expr_has_type_or_error(discrim, discrim_ty);
1035 fn check_pat_struct(
1037 pat: &'tcx hir::Pat,
1039 fields: &'tcx [Spanned<hir::FieldPat>],
1042 def_bm: ty::BindingMode,
1043 discrim_span: Option<Span>,
1045 // Resolve the path and check the definition for errors.
1046 let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.hir_id)
1050 for field in fields {
1051 self.check_pat_walk(&field.node.pat, self.tcx.types.err, def_bm, discrim_span);
1053 return self.tcx.types.err;
1056 // Type-check the path.
1057 self.demand_eqtype_pat(pat.span, expected, pat_ty, discrim_span);
1059 // Type-check subpatterns.
1060 if self.check_struct_pat_fields(pat_ty, pat.hir_id, pat.span, variant, fields, etc, def_bm)
1071 path_resolution: (Res, Option<Ty<'tcx>>, &'b [hir::PathSegment]),
1077 // We have already resolved the path.
1078 let (res, opt_ty, segments) = path_resolution;
1081 self.set_tainted_by_errors();
1082 return tcx.types.err;
1084 Res::Def(DefKind::Method, _) |
1085 Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _) |
1086 Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => {
1087 report_unexpected_variant_res(tcx, res, pat.span, qpath);
1088 return tcx.types.err;
1090 Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::SelfCtor(..) |
1091 Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => {} // OK
1092 _ => bug!("unexpected pattern resolution: {:?}", res)
1095 // Type-check the path.
1096 let pat_ty = self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id).0;
1097 self.demand_suptype(pat.span, expected, pat_ty);
1101 fn check_pat_tuple_struct(
1105 subpats: &'tcx [P<hir::Pat>],
1106 ddpos: Option<usize>,
1108 def_bm: ty::BindingMode,
1109 match_arm_pat_span: Option<Span>,
1113 for pat in subpats {
1114 self.check_pat_walk(&pat, tcx.types.err, def_bm, match_arm_pat_span);
1117 let report_unexpected_res = |res: Res| {
1118 let msg = format!("expected tuple struct/variant, found {} `{}`",
1120 hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false)));
1121 let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg);
1122 match (res, &pat.node) {
1123 (Res::Def(DefKind::Fn, _), _) | (Res::Def(DefKind::Method, _), _) => {
1124 err.span_label(pat.span, "`fn` calls are not allowed in patterns");
1125 err.help("for more information, visit \
1126 https://doc.rust-lang.org/book/ch18-00-patterns.html");
1129 err.span_label(pat.span, "not a tuple variant or struct");
1136 // Resolve the path and check the definition for errors.
1137 let (res, opt_ty, segments) = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span);
1138 if res == Res::Err {
1139 self.set_tainted_by_errors();
1141 return self.tcx.types.err;
1144 // Type-check the path.
1145 let (pat_ty, res) = self.instantiate_value_path(segments, opt_ty, res, pat.span,
1147 if !pat_ty.is_fn() {
1148 report_unexpected_res(res);
1149 return self.tcx.types.err;
1152 let variant = match res {
1154 self.set_tainted_by_errors();
1156 return tcx.types.err;
1158 Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::Method, _) => {
1159 report_unexpected_res(res);
1160 return tcx.types.err;
1162 Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => {
1163 tcx.expect_variant_res(res)
1165 _ => bug!("unexpected pattern resolution: {:?}", res)
1168 // Replace constructor type with constructed type for tuple struct patterns.
1169 let pat_ty = pat_ty.fn_sig(tcx).output();
1170 let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
1172 self.demand_eqtype_pat(pat.span, expected, pat_ty, match_arm_pat_span);
1174 // Type-check subpatterns.
1175 if subpats.len() == variant.fields.len() ||
1176 subpats.len() < variant.fields.len() && ddpos.is_some() {
1177 let substs = match pat_ty.sty {
1178 ty::Adt(_, substs) => substs,
1179 _ => bug!("unexpected pattern type {:?}", pat_ty),
1181 for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
1182 let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
1183 self.check_pat_walk(&subpat, field_ty, def_bm, match_arm_pat_span);
1185 self.tcx.check_stability(variant.fields[i].did, Some(pat.hir_id), subpat.span);
1188 let subpats_ending = if subpats.len() == 1 { "" } else { "s" };
1189 let fields_ending = if variant.fields.len() == 1 { "" } else { "s" };
1190 struct_span_err!(tcx.sess, pat.span, E0023,
1191 "this pattern has {} field{}, but the corresponding {} has {} field{}",
1192 subpats.len(), subpats_ending, res.descr(),
1193 variant.fields.len(), fields_ending)
1194 .span_label(pat.span, format!("expected {} field{}, found {}",
1195 variant.fields.len(), fields_ending, subpats.len()))
1198 return tcx.types.err;
1203 fn check_struct_pat_fields(
1208 variant: &'tcx ty::VariantDef,
1209 fields: &'tcx [Spanned<hir::FieldPat>],
1211 def_bm: ty::BindingMode,
1215 let (substs, adt) = match adt_ty.sty {
1216 ty::Adt(adt, substs) => (substs, adt),
1217 _ => span_bug!(span, "struct pattern is not an ADT")
1219 let kind_name = adt.variant_descr();
1221 // Index the struct fields' types.
1222 let field_map = variant.fields
1225 .map(|(i, field)| (field.ident.modern(), (i, field)))
1226 .collect::<FxHashMap<_, _>>();
1228 // Keep track of which fields have already appeared in the pattern.
1229 let mut used_fields = FxHashMap::default();
1230 let mut no_field_errors = true;
1232 let mut inexistent_fields = vec![];
1233 // Typecheck each field.
1234 for &Spanned { node: ref field, span } in fields {
1235 let ident = tcx.adjust_ident(field.ident, variant.def_id);
1236 let field_ty = match used_fields.entry(ident) {
1237 Occupied(occupied) => {
1238 struct_span_err!(tcx.sess, span, E0025,
1239 "field `{}` bound multiple times \
1243 format!("multiple uses of `{}` in pattern", field.ident))
1244 .span_label(*occupied.get(), format!("first use of `{}`", field.ident))
1246 no_field_errors = false;
1250 vacant.insert(span);
1251 field_map.get(&ident)
1253 self.write_field_index(field.hir_id, *i);
1254 self.tcx.check_stability(f.did, Some(pat_id), span);
1255 self.field_ty(span, f, substs)
1257 .unwrap_or_else(|| {
1258 inexistent_fields.push(field.ident);
1259 no_field_errors = false;
1265 self.check_pat_walk(&field.pat, field_ty, def_bm, None);
1267 let mut unmentioned_fields = variant.fields
1269 .map(|field| field.ident.modern())
1270 .filter(|ident| !used_fields.contains_key(&ident))
1271 .collect::<Vec<_>>();
1272 if inexistent_fields.len() > 0 && !variant.recovered {
1273 let (field_names, t, plural) = if inexistent_fields.len() == 1 {
1274 (format!("a field named `{}`", inexistent_fields[0]), "this", "")
1276 (format!("fields named {}",
1277 inexistent_fields.iter()
1278 .map(|ident| format!("`{}`", ident))
1279 .collect::<Vec<String>>()
1280 .join(", ")), "these", "s")
1282 let spans = inexistent_fields.iter().map(|ident| ident.span).collect::<Vec<_>>();
1283 let mut err = struct_span_err!(tcx.sess,
1286 "{} `{}` does not have {}",
1288 tcx.def_path_str(variant.def_id),
1290 if let Some(ident) = inexistent_fields.last() {
1291 err.span_label(ident.span,
1292 format!("{} `{}` does not have {} field{}",
1294 tcx.def_path_str(variant.def_id),
1298 let input = unmentioned_fields.iter().map(|field| &field.name);
1299 let suggested_name =
1300 find_best_match_for_name(input, &ident.as_str(), None);
1301 if let Some(suggested_name) = suggested_name {
1302 err.span_suggestion(
1304 "a field with a similar name exists",
1305 suggested_name.to_string(),
1306 Applicability::MaybeIncorrect,
1309 // we don't want to throw `E0027` in case we have thrown `E0026` for them
1310 unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str());
1314 if tcx.sess.teach(&err.get_code().unwrap()) {
1316 "This error indicates that a struct pattern attempted to \
1317 extract a non-existent field from a struct. Struct fields \
1318 are identified by the name used before the colon : so struct \
1319 patterns should resemble the declaration of the struct type \
1321 If you are using shorthand field patterns but want to refer \
1322 to the struct field by a different name, you should rename \
1329 // Require `..` if struct has non_exhaustive attribute.
1330 if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
1331 span_err!(tcx.sess, span, E0638,
1332 "`..` required with {} marked as non-exhaustive",
1336 // Report an error if incorrect number of the fields were specified.
1337 if kind_name == "union" {
1338 if fields.len() != 1 {
1339 tcx.sess.span_err(span, "union patterns should have exactly one field");
1342 tcx.sess.span_err(span, "`..` cannot be used in union patterns");
1345 if unmentioned_fields.len() > 0 {
1346 let field_names = if unmentioned_fields.len() == 1 {
1347 format!("field `{}`", unmentioned_fields[0])
1349 format!("fields {}",
1350 unmentioned_fields.iter()
1351 .map(|name| format!("`{}`", name))
1352 .collect::<Vec<String>>()
1355 let mut diag = struct_span_err!(tcx.sess, span, E0027,
1356 "pattern does not mention {}",
1358 diag.span_label(span, format!("missing {}", field_names));
1359 if variant.ctor_kind == CtorKind::Fn {
1360 diag.note("trying to match a tuple variant with a struct variant pattern");
1362 if tcx.sess.teach(&diag.get_code().unwrap()) {
1364 "This error indicates that a pattern for a struct fails to specify a \
1365 sub-pattern for every one of the struct's fields. Ensure that each field \
1366 from the struct's definition is mentioned in the pattern, or use `..` to \
1367 ignore unwanted fields."