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;
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 // FIXME: `MiscVariable` for now -- obtaining the span and name information
315 // from all tuple elements isn't trivial.
316 Kind::from(self.next_ty_var(TypeVariableOrigin::TypeInference(pat.span)))
318 let element_tys = tcx.mk_substs(element_tys_iter);
319 let pat_ty = tcx.mk_ty(ty::Tuple(element_tys));
320 if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) {
322 // Walk subpatterns with an expected type of `err` in this case to silence
323 // further errors being emitted when using the bindings. #50333
324 let element_tys_iter = (0..max_len).map(|_| tcx.types.err);
325 for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
326 self.check_pat_walk(elem, &tcx.types.err, def_bm, discrim_span);
328 tcx.mk_tup(element_tys_iter)
330 for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
333 &element_tys[i].expect_ty(),
341 PatKind::Box(ref inner) => {
342 let inner_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(inner.span));
343 let uniq_ty = tcx.mk_box(inner_ty);
345 if self.check_dereferencable(pat.span, expected, &inner) {
346 // Here, `demand::subtype` is good enough, but I don't
347 // think any errors can be introduced by using
349 self.demand_eqtype_pat(pat.span, expected, uniq_ty, discrim_span);
350 self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span);
353 self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span);
357 PatKind::Ref(ref inner, mutbl) => {
358 let expected = self.shallow_resolve(expected);
359 if self.check_dereferencable(pat.span, expected, &inner) {
360 // `demand::subtype` would be good enough, but using
361 // `eqtype` turns out to be equally general. See (*)
362 // below for details.
364 // Take region, inner-type from expected type if we
365 // can, to avoid creating needless variables. This
366 // also helps with the bad interactions of the given
367 // hack detailed in (*) below.
368 debug!("check_pat_walk: expected={:?}", expected);
369 let (rptr_ty, inner_ty) = match expected.sty {
370 ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => {
374 let inner_ty = self.next_ty_var(
375 TypeVariableOrigin::TypeInference(inner.span));
376 let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
377 let region = self.next_region_var(infer::PatternRegion(pat.span));
378 let rptr_ty = tcx.mk_ref(region, mt);
379 debug!("check_pat_walk: demanding {:?} = {:?}", expected, rptr_ty);
380 let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
382 // Look for a case like `fn foo(&foo: u32)` and suggest
383 // `fn foo(foo: &u32)`
384 if let Some(mut err) = err {
385 self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected);
392 self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span);
395 self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span);
399 PatKind::Slice(ref before, ref slice, ref after) => {
400 let expected_ty = self.structurally_resolved_type(pat.span, expected);
401 let (inner_ty, slice_ty) = match expected_ty.sty {
402 ty::Array(inner_ty, size) => {
403 if let Some(size) = size.assert_usize(tcx) {
404 let min_len = before.len() as u64 + after.len() as u64;
408 tcx.sess, pat.span, E0527,
409 "pattern requires {} elements but array has {}",
411 .span_label(pat.span, format!("expected {} elements", size))
414 (inner_ty, tcx.types.err)
415 } else if let Some(rest) = size.checked_sub(min_len) {
416 (inner_ty, tcx.mk_array(inner_ty, rest))
418 struct_span_err!(tcx.sess, pat.span, E0528,
419 "pattern requires at least {} elements but array has {}",
421 .span_label(pat.span,
422 format!("pattern cannot match array of {} elements", size))
424 (inner_ty, tcx.types.err)
431 "cannot pattern-match on an array without a fixed length",
433 (inner_ty, tcx.types.err)
436 ty::Slice(inner_ty) => (inner_ty, expected_ty),
438 if !expected_ty.references_error() {
439 let mut err = struct_span_err!(
440 tcx.sess, pat.span, E0529,
441 "expected an array or slice, found `{}`",
443 if let ty::Ref(_, ty, _) = expected_ty.sty {
445 ty::Array(..) | ty::Slice(..) => {
446 err.help("the semantics of slice patterns changed \
447 recently; see issue #23121");
453 err.span_label( pat.span,
454 format!("pattern cannot match with input type `{}`", expected_ty)
457 (tcx.types.err, tcx.types.err)
462 self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span);
464 if let Some(ref slice) = *slice {
465 self.check_pat_walk(&slice, slice_ty, def_bm, discrim_span);
468 self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span);
474 self.write_ty(pat.hir_id, ty);
476 // (*) In most of the cases above (literals and constants being
477 // the exception), we relate types using strict equality, even
478 // though subtyping would be sufficient. There are a few reasons
479 // for this, some of which are fairly subtle and which cost me
480 // (nmatsakis) an hour or two debugging to remember, so I thought
481 // I'd write them down this time.
483 // 1. There is no loss of expressiveness here, though it does
484 // cause some inconvenience. What we are saying is that the type
485 // of `x` becomes *exactly* what is expected. This can cause unnecessary
486 // errors in some cases, such as this one:
489 // fn foo<'x>(x: &'x int) {
496 // The reason we might get an error is that `z` might be
497 // assigned a type like `&'x int`, and then we would have
498 // a problem when we try to assign `&a` to `z`, because
499 // the lifetime of `&a` (i.e., the enclosing block) is
500 // shorter than `'x`.
502 // HOWEVER, this code works fine. The reason is that the
503 // expected type here is whatever type the user wrote, not
504 // the initializer's type. In this case the user wrote
505 // nothing, so we are going to create a type variable `Z`.
506 // Then we will assign the type of the initializer (`&'x
507 // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
508 // will instantiate `Z` as a type `&'0 int` where `'0` is
509 // a fresh region variable, with the constraint that `'x :
510 // '0`. So basically we're all set.
512 // Note that there are two tests to check that this remains true
513 // (`regions-reassign-{match,let}-bound-pointer.rs`).
515 // 2. Things go horribly wrong if we use subtype. The reason for
516 // THIS is a fairly subtle case involving bound regions. See the
517 // `givens` field in `region_constraints`, as well as the test
518 // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
519 // for details. Short version is that we must sometimes detect
520 // relationships between specific region variables and regions
521 // bound in a closure signature, and that detection gets thrown
522 // off when we substitute fresh region variables here to enable
526 fn borrow_pat_suggestion(
528 err: &mut DiagnosticBuilder<'_>,
534 if let PatKind::Binding(..) = inner.node {
535 let parent_id = tcx.hir().get_parent_node_by_hir_id(pat.hir_id);
536 let parent = tcx.hir().get_by_hir_id(parent_id);
537 debug!("inner {:?} pat {:?} parent {:?}", inner, pat, parent);
539 hir::Node::Item(hir::Item { node: hir::ItemKind::Fn(..), .. }) |
540 hir::Node::ForeignItem(hir::ForeignItem {
541 node: hir::ForeignItemKind::Fn(..), ..
543 hir::Node::TraitItem(hir::TraitItem { node: hir::TraitItemKind::Method(..), .. }) |
544 hir::Node::ImplItem(hir::ImplItem { node: hir::ImplItemKind::Method(..), .. }) => {
545 // this pat is likely an argument
546 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
547 // FIXME: turn into structured suggestion, will need a span that also
548 // includes the the arg's type.
549 err.help(&format!("did you mean `{}: &{}`?", snippet, expected));
553 hir::Node::Pat(_) => {
554 // rely on match ergonomics or it might be nested `&&pat`
555 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
558 "you can probably remove the explicit borrow",
560 Applicability::MaybeIncorrect,
564 _ => {} // don't provide suggestions in other cases #55175
569 pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
570 if let PatKind::Binding(..) = inner.node {
571 if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) {
572 if let ty::Dynamic(..) = mt.ty.sty {
573 // This is "x = SomeTrait" being reduced from
574 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
575 let type_str = self.ty_to_string(expected);
576 let mut err = struct_span_err!(
580 "type `{}` cannot be dereferenced",
583 err.span_label(span, format!("type `{}` cannot be dereferenced", type_str));
584 if self.tcx.sess.teach(&err.get_code().unwrap()) {
586 This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \
587 pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \
588 this type has no compile-time size. Therefore, all accesses to trait types must be through \
589 pointers. If you encounter this error you should try to avoid dereferencing the pointer.
591 You can read more about trait objects in the Trait Objects section of the Reference: \
592 https://doc.rust-lang.org/reference/types.html#trait-objects");
604 expr: &'gcx hir::Expr,
605 discrim: &'gcx hir::Expr,
606 arms: &'gcx [hir::Arm],
607 expected: Expectation<'tcx>,
608 match_src: hir::MatchSource,
612 use hir::MatchSource::*;
613 let (source_if, if_no_else, if_desugar) = match match_src {
614 IfDesugar { contains_else_clause } => (true, !contains_else_clause, true),
615 IfLetDesugar { contains_else_clause } => (true, !contains_else_clause, false),
616 _ => (false, false, false),
619 // Type check the descriminant and get its type.
620 let discrim_ty = if if_desugar {
621 // Here we want to ensure:
623 // 1. That default match bindings are *not* accepted in the condition of an
624 // `if` expression. E.g. given `fn foo() -> &bool;` we reject `if foo() { .. }`.
626 // 2. By expecting `bool` for `expr` we get nice diagnostics for e.g. `if x = y { .. }`.
628 // FIXME(60707): Consider removing hack with principled solution.
629 self.check_expr_has_type_or_error(discrim, self.tcx.types.bool)
631 self.demand_discriminant_type(arms, discrim)
634 // If there are no arms, that is a diverging match; a special case.
636 self.diverges.set(self.diverges.get() | Diverges::Always);
637 return tcx.types.never;
640 self.warn_arms_when_scrutinee_diverges(arms, source_if);
642 // Otherwise, we have to union together the types that the
643 // arms produce and so forth.
644 let discrim_diverges = self.diverges.get();
645 self.diverges.set(Diverges::Maybe);
647 // rust-lang/rust#55810: Typecheck patterns first (via eager
648 // collection into `Vec`), so we get types for all bindings.
649 let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| {
650 let mut all_pats_diverge = Diverges::WarnedAlways;
652 self.diverges.set(Diverges::Maybe);
653 let binding_mode = ty::BindingMode::BindByValue(hir::Mutability::MutImmutable);
654 self.check_pat_walk(&p, discrim_ty, binding_mode, Some(discrim.span));
655 all_pats_diverge &= self.diverges.get();
658 // As discussed with @eddyb, this is for disabling unreachable_code
659 // warnings on patterns (they're now subsumed by unreachable_patterns
661 match all_pats_diverge {
662 Diverges::Maybe => Diverges::Maybe,
663 Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
667 // Now typecheck the blocks.
669 // The result of the match is the common supertype of all the
670 // arms. Start out the value as bottom, since it's the, well,
671 // bottom the type lattice, and we'll be moving up the lattice as
672 // we process each arm. (Note that any match with 0 arms is matching
673 // on any empty type and is therefore unreachable; should the flow
674 // of execution reach it, we will panic, so bottom is an appropriate
675 // type in that case)
676 let mut all_arms_diverge = Diverges::WarnedAlways;
678 let expected = expected.adjust_for_branches(self);
681 let coerce_first = match expected {
682 // We don't coerce to `()` so that if the match expression is a
683 // statement it's branches can have any consistent type. That allows
684 // us to give better error messages (pointing to a usually better
685 // arm for inconsistent arms or to the whole match when a `()` type
687 Expectation::ExpectHasType(ety) if ety != self.tcx.mk_unit() => ety,
688 _ => self.next_ty_var(TypeVariableOrigin::MiscVariable(expr.span)),
690 CoerceMany::with_coercion_sites(coerce_first, arms)
693 let mut other_arms = vec![]; // used only for diagnostics
694 let mut prior_arm_ty = None;
695 for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
696 if let Some(g) = &arm.guard {
697 self.diverges.set(pats_diverge);
699 hir::Guard::If(e) => self.check_expr_has_type_or_error(e, tcx.types.bool),
703 self.diverges.set(pats_diverge);
704 let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
705 all_arms_diverge &= self.diverges.get();
707 let span = expr.span;
710 let then_expr = &arms[0].body;
711 match (i, if_no_else) {
712 (0, _) => coercion.coerce(self, &self.misc(span), then_expr, arm_ty),
713 (_, true) => self.if_fallback_coercion(span, then_expr, &mut coercion),
715 let then_ty = prior_arm_ty.unwrap();
716 let cause = self.if_cause(span, then_expr, &arm.body, then_ty, arm_ty);
717 coercion.coerce(self, &cause, &arm.body, arm_ty);
721 let arm_span = if let hir::ExprKind::Block(blk, _) = &arm.body.node {
722 // Point at the block expr instead of the entire block
723 blk.expr.as_ref().map(|e| e.span).unwrap_or(arm.body.span)
727 let (span, code) = match i {
728 // The reason for the first arm to fail is not that the match arms diverge,
729 // but rather that there's a prior obligation that doesn't hold.
730 0 => (arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id)),
731 _ => (span, ObligationCauseCode::MatchExpressionArm {
734 prior_arms: other_arms.clone(),
735 last_ty: prior_arm_ty.unwrap(),
736 discrim_hir_id: discrim.hir_id,
739 let cause = self.cause(span, code);
740 coercion.coerce(self, &cause, &arm.body, arm_ty);
741 other_arms.push(arm_span);
742 if other_arms.len() > 5 {
743 other_arms.remove(0);
746 prior_arm_ty = Some(arm_ty);
749 // We won't diverge unless the discriminant or all arms diverge.
750 self.diverges.set(discrim_diverges | all_arms_diverge);
752 coercion.complete(self)
755 /// When the previously checked expression (the scrutinee) diverges,
756 /// warn the user about the match arms being unreachable.
757 fn warn_arms_when_scrutinee_diverges(&self, arms: &'gcx [hir::Arm], source_if: bool) {
758 if self.diverges.get().always() {
759 let msg = if source_if { "block in `if` expression" } else { "arm" };
761 self.warn_if_unreachable(arm.body.hir_id, arm.body.span, msg);
766 /// Handle the fallback arm of a desugared if(-let) like a missing else.
767 fn if_fallback_coercion(
770 then_expr: &'gcx hir::Expr,
771 coercion: &mut CoerceMany<'gcx, 'tcx, '_, rustc::hir::Arm>,
773 // If this `if` expr is the parent's function return expr,
774 // the cause of the type coercion is the return type, point at it. (#25228)
775 let ret_reason = self.maybe_get_coercion_reason(then_expr.hir_id, span);
776 let cause = self.cause(span, ObligationCauseCode::IfExpressionWithNoElse);
777 coercion.coerce_forced_unit(self, &cause, &mut |err| {
778 if let Some((span, msg)) = &ret_reason {
779 err.span_label(*span, msg.as_str());
780 } else if let ExprKind::Block(block, _) = &then_expr.node {
781 if let Some(expr) = &block.expr {
782 err.span_label(expr.span, "found here".to_string());
785 err.note("`if` expressions without `else` evaluate to `()`");
786 err.help("consider adding an `else` block that evaluates to the expected type");
787 }, ret_reason.is_none());
790 fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, span: Span) -> Option<(Span, String)> {
791 use hir::Node::{Block, Item, Local};
793 let hir = self.tcx.hir();
794 let arm_id = hir.get_parent_node_by_hir_id(hir_id);
795 let match_id = hir.get_parent_node_by_hir_id(arm_id);
796 let containing_id = hir.get_parent_node_by_hir_id(match_id);
798 let node = hir.get_by_hir_id(containing_id);
799 if let Block(block) = node {
800 // check that the body's parent is an fn
801 let parent = hir.get_by_hir_id(
802 hir.get_parent_node_by_hir_id(
803 hir.get_parent_node_by_hir_id(block.hir_id),
806 if let (Some(expr), Item(hir::Item {
807 node: hir::ItemKind::Fn(..), ..
808 })) = (&block.expr, parent) {
809 // check that the `if` expr without `else` is the fn body's expr
810 if expr.span == span {
811 return self.get_fn_decl(hir_id).map(|(fn_decl, _)| (
812 fn_decl.output.span(),
813 format!("expected `{}` because of this return type", fn_decl.output),
818 if let Local(hir::Local { ty: Some(_), pat, .. }) = node {
819 return Some((pat.span, "expected because of this assignment".to_string()));
827 then_expr: &'gcx hir::Expr,
828 else_expr: &'gcx hir::Expr,
831 ) -> ObligationCause<'tcx> {
832 let mut outer_sp = if self.tcx.sess.source_map().is_multiline(span) {
833 // The `if`/`else` isn't in one line in the output, include some context to make it
834 // clear it is an if/else expression:
836 // LL | let x = if true {
839 // || ----- expected because of this
842 // || ^^^^^ expected i32, found u32
844 // ||_____- if and else have incompatible types
848 // The entire expression is in one line, only point at the arms
850 // LL | let x = if true { 10i32 } else { 10u32 };
851 // | ----- ^^^^^ expected i32, found u32
853 // | expected because of this
858 let mut remove_semicolon = None;
859 let error_sp = if let ExprKind::Block(block, _) = &else_expr.node {
860 if let Some(expr) = &block.expr {
862 } else if let Some(stmt) = block.stmts.last() {
863 // possibly incorrect trailing `;` in the else arm
864 remove_semicolon = self.could_remove_semicolon(block, then_ty);
866 } else { // empty block, point at its entirety
867 // Avoid overlapping spans that aren't as readable:
869 // 2 | let x = if true {
872 // | | - expected because of this
879 // | |______if and else have incompatible types
880 // | expected integer, found ()
882 // by not pointing at the entire expression:
884 // 2 | let x = if true {
885 // | ------- if and else have incompatible types
887 // | - expected because of this
892 // | |_____^ expected integer, found ()
894 if outer_sp.is_some() {
895 outer_sp = Some(self.tcx.sess.source_map().def_span(span));
899 } else { // shouldn't happen unless the parser has done something weird
903 // Compute `Span` of `then` part of `if`-expression:
904 let then_sp = if let ExprKind::Block(block, _) = &then_expr.node {
905 if let Some(expr) = &block.expr {
907 } else if let Some(stmt) = block.stmts.last() {
908 // possibly incorrect trailing `;` in the else arm
909 remove_semicolon = remove_semicolon.or(self.could_remove_semicolon(block, else_ty));
911 } else { // empty block, point at its entirety
912 outer_sp = None; // same as in `error_sp`, cleanup output
915 } else { // shouldn't happen unless the parser has done something weird
919 // Finally construct the cause:
920 self.cause(error_sp, ObligationCauseCode::IfExpression {
923 semicolon: remove_semicolon,
927 fn demand_discriminant_type(
929 arms: &'gcx [hir::Arm],
930 discrim: &'gcx hir::Expr,
932 // Not entirely obvious: if matches may create ref bindings, we want to
933 // use the *precise* type of the discriminant, *not* some supertype, as
934 // the "discriminant type" (issue #23116).
936 // arielb1 [writes here in this comment thread][c] that there
937 // is certainly *some* potential danger, e.g., for an example
940 // [c]: https://github.com/rust-lang/rust/pull/43399#discussion_r130223956
943 // let Foo(x) = f()[0];
946 // Then if the pattern matches by reference, we want to match
947 // `f()[0]` as a lexpr, so we can't allow it to be
948 // coerced. But if the pattern matches by value, `f()[0]` is
949 // still syntactically a lexpr, but we *do* want to allow
952 // However, *likely* we are ok with allowing coercions to
953 // happen if there are no explicit ref mut patterns - all
954 // implicit ref mut patterns must occur behind a reference, so
955 // they will have the "correct" variance and lifetime.
957 // This does mean that the following pattern would be legal:
962 // impl Deref for Foo {
963 // type Target = Bar;
964 // fn deref(&self) -> &Bar { &self.0 }
966 // impl DerefMut for Foo {
967 // fn deref_mut(&mut self) -> &mut Bar { &mut self.0 }
969 // fn foo(x: &mut Foo) {
971 // let Bar(z): &mut Bar = x;
974 // assert_eq!(foo.0.0, 42);
978 // FIXME(tschottdorf): don't call contains_explicit_ref_binding, which
979 // is problematic as the HIR is being scraped, but ref bindings may be
980 // implicit after #42640. We need to make sure that pat_adjustments
981 // (once introduced) is populated by the time we get here.
984 let contains_ref_bindings = arms.iter()
985 .filter_map(|a| a.contains_explicit_ref_binding())
986 .max_by_key(|m| match *m {
987 hir::MutMutable => 1,
988 hir::MutImmutable => 0,
991 if let Some(m) = contains_ref_bindings {
992 self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m))
994 // ...but otherwise we want to use any supertype of the
995 // discriminant. This is sort of a workaround, see note (*) in
996 // `check_pat` for some details.
997 let discrim_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(discrim.span));
998 self.check_expr_has_type_or_error(discrim, discrim_ty);
1003 fn check_pat_struct(
1005 pat: &'gcx hir::Pat,
1007 fields: &'gcx [Spanned<hir::FieldPat>],
1010 def_bm: ty::BindingMode,
1011 discrim_span: Option<Span>,
1014 // Resolve the path and check the definition for errors.
1015 let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.hir_id)
1019 for field in fields {
1020 self.check_pat_walk(&field.node.pat, self.tcx.types.err, def_bm, discrim_span);
1022 return self.tcx.types.err;
1025 // Type-check the path.
1026 self.demand_eqtype_pat(pat.span, expected, pat_ty, discrim_span);
1028 // Type-check subpatterns.
1029 if self.check_struct_pat_fields(pat_ty, pat.hir_id, pat.span, variant, fields, etc, def_bm)
1045 // Resolve the path and check the definition for errors.
1046 let (res, opt_ty, segments) = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span);
1049 self.set_tainted_by_errors();
1050 return tcx.types.err;
1052 Res::Def(DefKind::Method, _) => {
1053 report_unexpected_variant_res(tcx, res, pat.span, qpath);
1054 return tcx.types.err;
1056 Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _) |
1057 Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => {
1058 report_unexpected_variant_res(tcx, res, pat.span, qpath);
1059 return tcx.types.err;
1061 Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::SelfCtor(..) |
1062 Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => {} // OK
1063 _ => bug!("unexpected pattern resolution: {:?}", res)
1066 // Type-check the path.
1067 let pat_ty = self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id).0;
1068 self.demand_suptype(pat.span, expected, pat_ty);
1072 fn check_pat_tuple_struct(
1076 subpats: &'gcx [P<hir::Pat>],
1077 ddpos: Option<usize>,
1079 def_bm: ty::BindingMode,
1080 match_arm_pat_span: Option<Span>,
1084 for pat in subpats {
1085 self.check_pat_walk(&pat, tcx.types.err, def_bm, match_arm_pat_span);
1088 let report_unexpected_res = |res: Res| {
1089 let msg = format!("expected tuple struct/variant, found {} `{}`",
1091 hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false)));
1092 let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg);
1093 match (res, &pat.node) {
1094 (Res::Def(DefKind::Fn, _), _) | (Res::Def(DefKind::Method, _), _) => {
1095 err.span_label(pat.span, "`fn` calls are not allowed in patterns");
1096 err.help("for more information, visit \
1097 https://doc.rust-lang.org/book/ch18-00-patterns.html");
1100 err.span_label(pat.span, "not a tuple variant or struct");
1107 // Resolve the path and check the definition for errors.
1108 let (res, opt_ty, segments) = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span);
1109 if res == Res::Err {
1110 self.set_tainted_by_errors();
1112 return self.tcx.types.err;
1115 // Type-check the path.
1116 let (pat_ty, res) = self.instantiate_value_path(segments, opt_ty, res, pat.span,
1118 if !pat_ty.is_fn() {
1119 report_unexpected_res(res);
1120 return self.tcx.types.err;
1123 let variant = match res {
1125 self.set_tainted_by_errors();
1127 return tcx.types.err;
1129 Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::Method, _) => {
1130 report_unexpected_res(res);
1131 return tcx.types.err;
1133 Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => {
1134 tcx.expect_variant_res(res)
1136 _ => bug!("unexpected pattern resolution: {:?}", res)
1139 // Replace constructor type with constructed type for tuple struct patterns.
1140 let pat_ty = pat_ty.fn_sig(tcx).output();
1141 let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
1143 self.demand_eqtype_pat(pat.span, expected, pat_ty, match_arm_pat_span);
1145 // Type-check subpatterns.
1146 if subpats.len() == variant.fields.len() ||
1147 subpats.len() < variant.fields.len() && ddpos.is_some() {
1148 let substs = match pat_ty.sty {
1149 ty::Adt(_, substs) => substs,
1150 _ => bug!("unexpected pattern type {:?}", pat_ty),
1152 for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
1153 let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
1154 self.check_pat_walk(&subpat, field_ty, def_bm, match_arm_pat_span);
1156 self.tcx.check_stability(variant.fields[i].did, Some(pat.hir_id), subpat.span);
1159 let subpats_ending = if subpats.len() == 1 { "" } else { "s" };
1160 let fields_ending = if variant.fields.len() == 1 { "" } else { "s" };
1161 struct_span_err!(tcx.sess, pat.span, E0023,
1162 "this pattern has {} field{}, but the corresponding {} has {} field{}",
1163 subpats.len(), subpats_ending, res.descr(),
1164 variant.fields.len(), fields_ending)
1165 .span_label(pat.span, format!("expected {} field{}, found {}",
1166 variant.fields.len(), fields_ending, subpats.len()))
1169 return tcx.types.err;
1174 fn check_struct_pat_fields(
1179 variant: &'tcx ty::VariantDef,
1180 fields: &'gcx [Spanned<hir::FieldPat>],
1182 def_bm: ty::BindingMode,
1186 let (substs, adt) = match adt_ty.sty {
1187 ty::Adt(adt, substs) => (substs, adt),
1188 _ => span_bug!(span, "struct pattern is not an ADT")
1190 let kind_name = adt.variant_descr();
1192 // Index the struct fields' types.
1193 let field_map = variant.fields
1196 .map(|(i, field)| (field.ident.modern(), (i, field)))
1197 .collect::<FxHashMap<_, _>>();
1199 // Keep track of which fields have already appeared in the pattern.
1200 let mut used_fields = FxHashMap::default();
1201 let mut no_field_errors = true;
1203 let mut inexistent_fields = vec![];
1204 // Typecheck each field.
1205 for &Spanned { node: ref field, span } in fields {
1206 let ident = tcx.adjust_ident(field.ident, variant.def_id);
1207 let field_ty = match used_fields.entry(ident) {
1208 Occupied(occupied) => {
1209 struct_span_err!(tcx.sess, span, E0025,
1210 "field `{}` bound multiple times \
1214 format!("multiple uses of `{}` in pattern", field.ident))
1215 .span_label(*occupied.get(), format!("first use of `{}`", field.ident))
1217 no_field_errors = false;
1221 vacant.insert(span);
1222 field_map.get(&ident)
1224 self.write_field_index(field.hir_id, *i);
1225 self.tcx.check_stability(f.did, Some(pat_id), span);
1226 self.field_ty(span, f, substs)
1228 .unwrap_or_else(|| {
1229 inexistent_fields.push(field.ident);
1230 no_field_errors = false;
1236 self.check_pat_walk(&field.pat, field_ty, def_bm, None);
1238 let mut unmentioned_fields = variant.fields
1240 .map(|field| field.ident.modern())
1241 .filter(|ident| !used_fields.contains_key(&ident))
1242 .collect::<Vec<_>>();
1243 if inexistent_fields.len() > 0 && !variant.recovered {
1244 let (field_names, t, plural) = if inexistent_fields.len() == 1 {
1245 (format!("a field named `{}`", inexistent_fields[0]), "this", "")
1247 (format!("fields named {}",
1248 inexistent_fields.iter()
1249 .map(|ident| format!("`{}`", ident))
1250 .collect::<Vec<String>>()
1251 .join(", ")), "these", "s")
1253 let spans = inexistent_fields.iter().map(|ident| ident.span).collect::<Vec<_>>();
1254 let mut err = struct_span_err!(tcx.sess,
1257 "{} `{}` does not have {}",
1259 tcx.def_path_str(variant.def_id),
1261 if let Some(ident) = inexistent_fields.last() {
1262 err.span_label(ident.span,
1263 format!("{} `{}` does not have {} field{}",
1265 tcx.def_path_str(variant.def_id),
1269 let input = unmentioned_fields.iter().map(|field| &field.name);
1270 let suggested_name =
1271 find_best_match_for_name(input, &ident.as_str(), None);
1272 if let Some(suggested_name) = suggested_name {
1273 err.span_suggestion(
1275 "a field with a similar name exists",
1276 suggested_name.to_string(),
1277 Applicability::MaybeIncorrect,
1280 // we don't want to throw `E0027` in case we have thrown `E0026` for them
1281 unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str());
1285 if tcx.sess.teach(&err.get_code().unwrap()) {
1287 "This error indicates that a struct pattern attempted to \
1288 extract a non-existent field from a struct. Struct fields \
1289 are identified by the name used before the colon : so struct \
1290 patterns should resemble the declaration of the struct type \
1292 If you are using shorthand field patterns but want to refer \
1293 to the struct field by a different name, you should rename \
1300 // Require `..` if struct has non_exhaustive attribute.
1301 if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
1302 span_err!(tcx.sess, span, E0638,
1303 "`..` required with {} marked as non-exhaustive",
1307 // Report an error if incorrect number of the fields were specified.
1308 if kind_name == "union" {
1309 if fields.len() != 1 {
1310 tcx.sess.span_err(span, "union patterns should have exactly one field");
1313 tcx.sess.span_err(span, "`..` cannot be used in union patterns");
1316 if unmentioned_fields.len() > 0 {
1317 let field_names = if unmentioned_fields.len() == 1 {
1318 format!("field `{}`", unmentioned_fields[0])
1320 format!("fields {}",
1321 unmentioned_fields.iter()
1322 .map(|name| format!("`{}`", name))
1323 .collect::<Vec<String>>()
1326 let mut diag = struct_span_err!(tcx.sess, span, E0027,
1327 "pattern does not mention {}",
1329 diag.span_label(span, format!("missing {}", field_names));
1330 if variant.ctor_kind == CtorKind::Fn {
1331 diag.note("trying to match a tuple variant with a struct variant pattern");
1333 if tcx.sess.teach(&diag.get_code().unwrap()) {
1335 "This error indicates that a pattern for a struct fails to specify a \
1336 sub-pattern for every one of the struct's fields. Ensure that each field \
1337 from the struct's definition is mentioned in the pattern, or use `..` to \
1338 ignore unwanted fields."