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::AssociatedConst, _) => false,
75 PatKind::Binding(..) |
76 PatKind::Ref(..) => false,
79 debug!("pattern is non reference pattern");
80 let mut exp_ty = self.resolve_type_vars_with_obligations(&expected);
82 // Peel off as many `&` or `&mut` from the discriminant as possible. For example,
83 // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
84 // the `Some(5)` which is not of type Ref.
86 // For each ampersand peeled off, update the binding mode and push the original
87 // type into the adjustments vector.
89 // See the examples in `run-pass/match-defbm*.rs`.
90 let mut pat_adjustments = vec![];
91 while let ty::Ref(_, inner_ty, inner_mutability) = exp_ty.sty {
92 debug!("inspecting {:?}", exp_ty);
94 debug!("current discriminant is Ref, inserting implicit deref");
95 // Preserve the reference type. We'll need it later during HAIR lowering.
96 pat_adjustments.push(exp_ty);
99 def_bm = match def_bm {
100 // If default binding mode is by value, make it `ref` or `ref mut`
101 // (depending on whether we observe `&` or `&mut`).
102 ty::BindByValue(_) =>
103 ty::BindByReference(inner_mutability),
105 // Once a `ref`, always a `ref`. This is because a `& &mut` can't mutate
106 // the underlying value.
107 ty::BindByReference(hir::Mutability::MutImmutable) =>
108 ty::BindByReference(hir::Mutability::MutImmutable),
110 // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref`
112 ty::BindByReference(hir::Mutability::MutMutable) =>
113 ty::BindByReference(inner_mutability),
118 if pat_adjustments.len() > 0 {
119 debug!("default binding mode is now {:?}", def_bm);
120 self.inh.tables.borrow_mut()
121 .pat_adjustments_mut()
122 .insert(pat.hir_id, pat_adjustments);
124 } else if let PatKind::Ref(..) = pat.node {
125 // When you encounter a `&pat` pattern, reset to "by
126 // value". This is so that `x` and `y` here are by value,
127 // as they appear to be:
130 // match &(&22, &44) {
136 def_bm = ty::BindByValue(hir::MutImmutable);
139 // Lose mutability now that we know binding mode and discriminant type.
141 let expected = expected;
143 let ty = match pat.node {
147 PatKind::Lit(ref lt) => {
148 // We've already computed the type above (when checking for a non-ref pat), so
149 // avoid computing it again.
150 let ty = self.node_ty(lt.hir_id);
152 // Byte string patterns behave the same way as array patterns
153 // They can denote both statically and dynamically sized byte arrays
155 if let hir::ExprKind::Lit(ref lt) = lt.node {
156 if let ast::LitKind::ByteStr(_) = lt.node {
157 let expected_ty = self.structurally_resolved_type(pat.span, expected);
158 if let ty::Ref(_, r_ty, _) = expected_ty.sty {
159 if let ty::Slice(_) = r_ty.sty {
160 pat_ty = tcx.mk_imm_ref(tcx.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_type_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 let size = size.unwrap_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)
427 ty::Slice(inner_ty) => (inner_ty, expected_ty),
429 if !expected_ty.references_error() {
430 let mut err = struct_span_err!(
431 tcx.sess, pat.span, E0529,
432 "expected an array or slice, found `{}`",
434 if let ty::Ref(_, ty, _) = expected_ty.sty {
436 ty::Array(..) | ty::Slice(..) => {
437 err.help("the semantics of slice patterns changed \
438 recently; see issue #23121");
444 err.span_label( pat.span,
445 format!("pattern cannot match with input type `{}`", expected_ty)
448 (tcx.types.err, tcx.types.err)
453 self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span);
455 if let Some(ref slice) = *slice {
456 self.check_pat_walk(&slice, slice_ty, def_bm, discrim_span);
459 self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span);
465 self.write_ty(pat.hir_id, ty);
467 // (*) In most of the cases above (literals and constants being
468 // the exception), we relate types using strict equality, even
469 // though subtyping would be sufficient. There are a few reasons
470 // for this, some of which are fairly subtle and which cost me
471 // (nmatsakis) an hour or two debugging to remember, so I thought
472 // I'd write them down this time.
474 // 1. There is no loss of expressiveness here, though it does
475 // cause some inconvenience. What we are saying is that the type
476 // of `x` becomes *exactly* what is expected. This can cause unnecessary
477 // errors in some cases, such as this one:
480 // fn foo<'x>(x: &'x int) {
487 // The reason we might get an error is that `z` might be
488 // assigned a type like `&'x int`, and then we would have
489 // a problem when we try to assign `&a` to `z`, because
490 // the lifetime of `&a` (i.e., the enclosing block) is
491 // shorter than `'x`.
493 // HOWEVER, this code works fine. The reason is that the
494 // expected type here is whatever type the user wrote, not
495 // the initializer's type. In this case the user wrote
496 // nothing, so we are going to create a type variable `Z`.
497 // Then we will assign the type of the initializer (`&'x
498 // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
499 // will instantiate `Z` as a type `&'0 int` where `'0` is
500 // a fresh region variable, with the constraint that `'x :
501 // '0`. So basically we're all set.
503 // Note that there are two tests to check that this remains true
504 // (`regions-reassign-{match,let}-bound-pointer.rs`).
506 // 2. Things go horribly wrong if we use subtype. The reason for
507 // THIS is a fairly subtle case involving bound regions. See the
508 // `givens` field in `region_constraints`, as well as the test
509 // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
510 // for details. Short version is that we must sometimes detect
511 // relationships between specific region variables and regions
512 // bound in a closure signature, and that detection gets thrown
513 // off when we substitute fresh region variables here to enable
517 fn borrow_pat_suggestion(
519 err: &mut DiagnosticBuilder<'_>,
525 if let PatKind::Binding(..) = inner.node {
526 let parent_id = tcx.hir().get_parent_node_by_hir_id(pat.hir_id);
527 let parent = tcx.hir().get_by_hir_id(parent_id);
528 debug!("inner {:?} pat {:?} parent {:?}", inner, pat, parent);
530 hir::Node::Item(hir::Item { node: hir::ItemKind::Fn(..), .. }) |
531 hir::Node::ForeignItem(hir::ForeignItem {
532 node: hir::ForeignItemKind::Fn(..), ..
534 hir::Node::TraitItem(hir::TraitItem { node: hir::TraitItemKind::Method(..), .. }) |
535 hir::Node::ImplItem(hir::ImplItem { node: hir::ImplItemKind::Method(..), .. }) => {
536 // this pat is likely an argument
537 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
538 // FIXME: turn into structured suggestion, will need a span that also
539 // includes the the arg's type.
540 err.help(&format!("did you mean `{}: &{}`?", snippet, expected));
543 hir::Node::Expr(hir::Expr { node: hir::ExprKind::Match(..), .. }) |
544 hir::Node::Pat(_) => {
545 // rely on match ergonomics or it might be nested `&&pat`
546 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
549 "you can probably remove the explicit borrow",
551 Applicability::MaybeIncorrect,
555 _ => {} // don't provide suggestions in other cases #55175
560 pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
561 if let PatKind::Binding(..) = inner.node {
562 if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) {
563 if let ty::Dynamic(..) = mt.ty.sty {
564 // This is "x = SomeTrait" being reduced from
565 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
566 let type_str = self.ty_to_string(expected);
567 let mut err = struct_span_err!(
571 "type `{}` cannot be dereferenced",
574 err.span_label(span, format!("type `{}` cannot be dereferenced", type_str));
575 if self.tcx.sess.teach(&err.get_code().unwrap()) {
577 This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \
578 pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \
579 this type has no compile-time size. Therefore, all accesses to trait types must be through \
580 pointers. If you encounter this error you should try to avoid dereferencing the pointer.
582 You can read more about trait objects in the Trait Objects section of the Reference: \
583 https://doc.rust-lang.org/reference/types.html#trait-objects");
595 expr: &'gcx hir::Expr,
596 discrim: &'gcx hir::Expr,
597 arms: &'gcx [hir::Arm],
598 expected: Expectation<'tcx>,
599 match_src: hir::MatchSource,
603 use hir::MatchSource::*;
604 let (source_if, if_no_else, if_desugar) = match match_src {
605 IfDesugar { contains_else_clause } => (true, !contains_else_clause, true),
606 IfLetDesugar { contains_else_clause } => (true, !contains_else_clause, false),
607 _ => (false, false, false),
610 // Type check the descriminant and get its type.
611 let discrim_ty = if if_desugar {
612 // Here we want to ensure:
614 // 1. That default match bindings are *not* accepted in the condition of an
615 // `if` expression. E.g. given `fn foo() -> &bool;` we reject `if foo() { .. }`.
617 // 2. By expecting `bool` for `expr` we get nice diagnostics for e.g. `if x = y { .. }`.
619 // FIXME(60707): Consider removing hack with principled solution.
620 self.check_expr_has_type_or_error(discrim, self.tcx.types.bool)
622 self.demand_discriminant_type(arms, discrim)
625 // If there are no arms, that is a diverging match; a special case.
627 self.diverges.set(self.diverges.get() | Diverges::Always);
628 return tcx.types.never;
631 self.warn_arms_when_scrutinee_diverges(arms, source_if);
633 // Otherwise, we have to union together the types that the
634 // arms produce and so forth.
635 let discrim_diverges = self.diverges.get();
636 self.diverges.set(Diverges::Maybe);
638 // rust-lang/rust#55810: Typecheck patterns first (via eager
639 // collection into `Vec`), so we get types for all bindings.
640 let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| {
641 let mut all_pats_diverge = Diverges::WarnedAlways;
643 self.diverges.set(Diverges::Maybe);
644 let binding_mode = ty::BindingMode::BindByValue(hir::Mutability::MutImmutable);
645 self.check_pat_walk(&p, discrim_ty, binding_mode, Some(discrim.span));
646 all_pats_diverge &= self.diverges.get();
649 // As discussed with @eddyb, this is for disabling unreachable_code
650 // warnings on patterns (they're now subsumed by unreachable_patterns
652 match all_pats_diverge {
653 Diverges::Maybe => Diverges::Maybe,
654 Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
658 // Now typecheck the blocks.
660 // The result of the match is the common supertype of all the
661 // arms. Start out the value as bottom, since it's the, well,
662 // bottom the type lattice, and we'll be moving up the lattice as
663 // we process each arm. (Note that any match with 0 arms is matching
664 // on any empty type and is therefore unreachable; should the flow
665 // of execution reach it, we will panic, so bottom is an appropriate
666 // type in that case)
667 let mut all_arms_diverge = Diverges::WarnedAlways;
669 let expected = expected.adjust_for_branches(self);
672 let coerce_first = match expected {
673 // We don't coerce to `()` so that if the match expression is a
674 // statement it's branches can have any consistent type. That allows
675 // us to give better error messages (pointing to a usually better
676 // arm for inconsistent arms or to the whole match when a `()` type
678 Expectation::ExpectHasType(ety) if ety != self.tcx.mk_unit() => ety,
679 _ => self.next_ty_var(TypeVariableOrigin::MiscVariable(expr.span)),
681 CoerceMany::with_coercion_sites(coerce_first, arms)
684 let mut other_arms = vec![]; // used only for diagnostics
685 let mut prior_arm_ty = None;
686 for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
687 if let Some(g) = &arm.guard {
688 self.diverges.set(pats_diverge);
690 hir::Guard::If(e) => self.check_expr_has_type_or_error(e, tcx.types.bool),
694 self.diverges.set(pats_diverge);
695 let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
696 all_arms_diverge &= self.diverges.get();
698 let span = expr.span;
701 let then_expr = &arms[0].body;
702 match (i, if_no_else) {
703 (0, _) => coercion.coerce(self, &self.misc(span), then_expr, arm_ty),
704 (_, true) => self.if_fallback_coercion(span, then_expr, &mut coercion),
706 let then_ty = prior_arm_ty.unwrap();
707 let cause = self.if_cause(span, then_expr, &arm.body, then_ty, arm_ty);
708 coercion.coerce(self, &cause, &arm.body, arm_ty);
712 let arm_span = if let hir::ExprKind::Block(blk, _) = &arm.body.node {
713 // Point at the block expr instead of the entire block
714 blk.expr.as_ref().map(|e| e.span).unwrap_or(arm.body.span)
718 let (span, code) = match i {
719 // The reason for the first arm to fail is not that the match arms diverge,
720 // but rather that there's a prior obligation that doesn't hold.
721 0 => (arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id)),
722 _ => (span, ObligationCauseCode::MatchExpressionArm {
725 prior_arms: other_arms.clone(),
726 last_ty: prior_arm_ty.unwrap(),
727 discrim_hir_id: discrim.hir_id,
730 let cause = self.cause(span, code);
731 coercion.coerce(self, &cause, &arm.body, arm_ty);
732 other_arms.push(arm_span);
733 if other_arms.len() > 5 {
734 other_arms.remove(0);
737 prior_arm_ty = Some(arm_ty);
740 // We won't diverge unless the discriminant or all arms diverge.
741 self.diverges.set(discrim_diverges | all_arms_diverge);
743 coercion.complete(self)
746 /// When the previously checked expression (the scrutinee) diverges,
747 /// warn the user about the match arms being unreachable.
748 fn warn_arms_when_scrutinee_diverges(&self, arms: &'gcx [hir::Arm], source_if: bool) {
749 if self.diverges.get().always() {
750 let msg = if source_if { "block in `if` expression" } else { "arm" };
752 self.warn_if_unreachable(arm.body.hir_id, arm.body.span, msg);
757 /// Handle the fallback arm of a desugared if(-let) like a missing else.
758 fn if_fallback_coercion(
761 then_expr: &'gcx hir::Expr,
762 coercion: &mut CoerceMany<'gcx, 'tcx, '_, rustc::hir::Arm>,
764 // If this `if` expr is the parent's function return expr,
765 // the cause of the type coercion is the return type, point at it. (#25228)
766 let ret_reason = self.maybe_get_coercion_reason(then_expr.hir_id, span);
767 let cause = self.cause(span, ObligationCauseCode::IfExpressionWithNoElse);
768 coercion.coerce_forced_unit(self, &cause, &mut |err| {
769 if let Some((span, msg)) = &ret_reason {
770 err.span_label(*span, msg.as_str());
771 } else if let ExprKind::Block(block, _) = &then_expr.node {
772 if let Some(expr) = &block.expr {
773 err.span_label(expr.span, "found here".to_string());
776 err.note("`if` expressions without `else` evaluate to `()`");
777 err.help("consider adding an `else` block that evaluates to the expected type");
778 }, ret_reason.is_none());
781 fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, span: Span) -> Option<(Span, String)> {
782 use hir::Node::{Block, Item, Local};
784 let node = self.tcx.hir().get_by_hir_id(self.tcx.hir().get_parent_node_by_hir_id(
785 self.tcx.hir().get_parent_node_by_hir_id(hir_id),
787 if let Block(block) = node {
788 // check that the body's parent is an fn
789 let parent = self.tcx.hir().get_by_hir_id(
790 self.tcx.hir().get_parent_node_by_hir_id(
791 self.tcx.hir().get_parent_node_by_hir_id(block.hir_id),
794 if let (Some(expr), Item(hir::Item {
795 node: hir::ItemKind::Fn(..), ..
796 })) = (&block.expr, parent) {
797 // check that the `if` expr without `else` is the fn body's expr
798 if expr.span == span {
799 return self.get_fn_decl(hir_id).map(|(fn_decl, _)| (
800 fn_decl.output.span(),
801 format!("expected `{}` because of this return type", fn_decl.output),
806 if let Local(hir::Local { ty: Some(_), pat, .. }) = node {
807 return Some((pat.span, "expected because of this assignment".to_string()));
815 then_expr: &'gcx hir::Expr,
816 else_expr: &'gcx hir::Expr,
819 ) -> ObligationCause<'tcx> {
820 let mut outer_sp = if self.tcx.sess.source_map().is_multiline(span) {
821 // The `if`/`else` isn't in one line in the output, include some context to make it
822 // clear it is an if/else expression:
824 // LL | let x = if true {
827 // || ----- expected because of this
830 // || ^^^^^ expected i32, found u32
832 // ||_____- if and else have incompatible types
836 // The entire expression is in one line, only point at the arms
838 // LL | let x = if true { 10i32 } else { 10u32 };
839 // | ----- ^^^^^ expected i32, found u32
841 // | expected because of this
846 let mut remove_semicolon = None;
847 let error_sp = if let ExprKind::Block(block, _) = &else_expr.node {
848 if let Some(expr) = &block.expr {
850 } else if let Some(stmt) = block.stmts.last() {
851 // possibly incorrect trailing `;` in the else arm
852 remove_semicolon = self.could_remove_semicolon(block, then_ty);
854 } else { // empty block, point at its entirety
855 // Avoid overlapping spans that aren't as readable:
857 // 2 | let x = if true {
860 // | | - expected because of this
867 // | |______if and else have incompatible types
868 // | expected integer, found ()
870 // by not pointing at the entire expression:
872 // 2 | let x = if true {
873 // | ------- if and else have incompatible types
875 // | - expected because of this
880 // | |_____^ expected integer, found ()
882 if outer_sp.is_some() {
883 outer_sp = Some(self.tcx.sess.source_map().def_span(span));
887 } else { // shouldn't happen unless the parser has done something weird
891 // Compute `Span` of `then` part of `if`-expression:
892 let then_sp = if let ExprKind::Block(block, _) = &then_expr.node {
893 if let Some(expr) = &block.expr {
895 } else if let Some(stmt) = block.stmts.last() {
896 // possibly incorrect trailing `;` in the else arm
897 remove_semicolon = remove_semicolon.or(self.could_remove_semicolon(block, else_ty));
899 } else { // empty block, point at its entirety
900 outer_sp = None; // same as in `error_sp`, cleanup output
903 } else { // shouldn't happen unless the parser has done something weird
907 // Finally construct the cause:
908 self.cause(error_sp, ObligationCauseCode::IfExpression {
911 semicolon: remove_semicolon,
915 fn demand_discriminant_type(
917 arms: &'gcx [hir::Arm],
918 discrim: &'gcx hir::Expr,
920 // Not entirely obvious: if matches may create ref bindings, we want to
921 // use the *precise* type of the discriminant, *not* some supertype, as
922 // the "discriminant type" (issue #23116).
924 // arielb1 [writes here in this comment thread][c] that there
925 // is certainly *some* potential danger, e.g., for an example
928 // [c]: https://github.com/rust-lang/rust/pull/43399#discussion_r130223956
931 // let Foo(x) = f()[0];
934 // Then if the pattern matches by reference, we want to match
935 // `f()[0]` as a lexpr, so we can't allow it to be
936 // coerced. But if the pattern matches by value, `f()[0]` is
937 // still syntactically a lexpr, but we *do* want to allow
940 // However, *likely* we are ok with allowing coercions to
941 // happen if there are no explicit ref mut patterns - all
942 // implicit ref mut patterns must occur behind a reference, so
943 // they will have the "correct" variance and lifetime.
945 // This does mean that the following pattern would be legal:
950 // impl Deref for Foo {
951 // type Target = Bar;
952 // fn deref(&self) -> &Bar { &self.0 }
954 // impl DerefMut for Foo {
955 // fn deref_mut(&mut self) -> &mut Bar { &mut self.0 }
957 // fn foo(x: &mut Foo) {
959 // let Bar(z): &mut Bar = x;
962 // assert_eq!(foo.0.0, 42);
966 // FIXME(tschottdorf): don't call contains_explicit_ref_binding, which
967 // is problematic as the HIR is being scraped, but ref bindings may be
968 // implicit after #42640. We need to make sure that pat_adjustments
969 // (once introduced) is populated by the time we get here.
972 let contains_ref_bindings = arms.iter()
973 .filter_map(|a| a.contains_explicit_ref_binding())
974 .max_by_key(|m| match *m {
975 hir::MutMutable => 1,
976 hir::MutImmutable => 0,
979 if let Some(m) = contains_ref_bindings {
980 self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m))
982 // ...but otherwise we want to use any supertype of the
983 // discriminant. This is sort of a workaround, see note (*) in
984 // `check_pat` for some details.
985 let discrim_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(discrim.span));
986 self.check_expr_has_type_or_error(discrim, discrim_ty);
995 fields: &'gcx [Spanned<hir::FieldPat>],
998 def_bm: ty::BindingMode,
999 discrim_span: Option<Span>,
1002 // Resolve the path and check the definition for errors.
1003 let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.hir_id)
1007 for field in fields {
1008 self.check_pat_walk(&field.node.pat, self.tcx.types.err, def_bm, discrim_span);
1010 return self.tcx.types.err;
1013 // Type-check the path.
1014 self.demand_eqtype_pat(pat.span, expected, pat_ty, discrim_span);
1016 // Type-check subpatterns.
1017 if self.check_struct_pat_fields(pat_ty, pat.hir_id, pat.span, variant, fields, etc, def_bm)
1033 // Resolve the path and check the definition for errors.
1034 let (res, opt_ty, segments) = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span);
1037 self.set_tainted_by_errors();
1038 return tcx.types.err;
1040 Res::Def(DefKind::Method, _) => {
1041 report_unexpected_variant_res(tcx, res, pat.span, qpath);
1042 return tcx.types.err;
1044 Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _) |
1045 Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => {
1046 report_unexpected_variant_res(tcx, res, pat.span, qpath);
1047 return tcx.types.err;
1049 Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::SelfCtor(..) |
1050 Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssociatedConst, _) => {} // OK
1051 _ => bug!("unexpected pattern resolution: {:?}", res)
1054 // Type-check the path.
1055 let pat_ty = self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id).0;
1056 self.demand_suptype(pat.span, expected, pat_ty);
1060 fn check_pat_tuple_struct(
1064 subpats: &'gcx [P<hir::Pat>],
1065 ddpos: Option<usize>,
1067 def_bm: ty::BindingMode,
1068 match_arm_pat_span: Option<Span>,
1072 for pat in subpats {
1073 self.check_pat_walk(&pat, tcx.types.err, def_bm, match_arm_pat_span);
1076 let report_unexpected_res = |res: Res| {
1077 let msg = format!("expected tuple struct/variant, found {} `{}`",
1079 hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false)));
1080 struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg)
1081 .span_label(pat.span, "not a tuple variant or struct").emit();
1085 // Resolve the path and check the definition for errors.
1086 let (res, opt_ty, segments) = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span);
1087 if res == Res::Err {
1088 self.set_tainted_by_errors();
1090 return self.tcx.types.err;
1093 // Type-check the path.
1094 let (pat_ty, res) = self.instantiate_value_path(segments, opt_ty, res, pat.span,
1096 if !pat_ty.is_fn() {
1097 report_unexpected_res(res);
1098 return self.tcx.types.err;
1101 let variant = match res {
1103 self.set_tainted_by_errors();
1105 return tcx.types.err;
1107 Res::Def(DefKind::AssociatedConst, _) | Res::Def(DefKind::Method, _) => {
1108 report_unexpected_res(res);
1109 return tcx.types.err;
1111 Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => {
1112 tcx.expect_variant_res(res)
1114 _ => bug!("unexpected pattern resolution: {:?}", res)
1117 // Replace constructor type with constructed type for tuple struct patterns.
1118 let pat_ty = pat_ty.fn_sig(tcx).output();
1119 let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
1121 self.demand_eqtype_pat(pat.span, expected, pat_ty, match_arm_pat_span);
1123 // Type-check subpatterns.
1124 if subpats.len() == variant.fields.len() ||
1125 subpats.len() < variant.fields.len() && ddpos.is_some() {
1126 let substs = match pat_ty.sty {
1127 ty::Adt(_, substs) => substs,
1128 _ => bug!("unexpected pattern type {:?}", pat_ty),
1130 for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
1131 let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
1132 self.check_pat_walk(&subpat, field_ty, def_bm, match_arm_pat_span);
1134 self.tcx.check_stability(variant.fields[i].did, Some(pat.hir_id), subpat.span);
1137 let subpats_ending = if subpats.len() == 1 { "" } else { "s" };
1138 let fields_ending = if variant.fields.len() == 1 { "" } else { "s" };
1139 struct_span_err!(tcx.sess, pat.span, E0023,
1140 "this pattern has {} field{}, but the corresponding {} has {} field{}",
1141 subpats.len(), subpats_ending, res.descr(),
1142 variant.fields.len(), fields_ending)
1143 .span_label(pat.span, format!("expected {} field{}, found {}",
1144 variant.fields.len(), fields_ending, subpats.len()))
1147 return tcx.types.err;
1152 fn check_struct_pat_fields(
1157 variant: &'tcx ty::VariantDef,
1158 fields: &'gcx [Spanned<hir::FieldPat>],
1160 def_bm: ty::BindingMode,
1164 let (substs, adt) = match adt_ty.sty {
1165 ty::Adt(adt, substs) => (substs, adt),
1166 _ => span_bug!(span, "struct pattern is not an ADT")
1168 let kind_name = adt.variant_descr();
1170 // Index the struct fields' types.
1171 let field_map = variant.fields
1174 .map(|(i, field)| (field.ident.modern(), (i, field)))
1175 .collect::<FxHashMap<_, _>>();
1177 // Keep track of which fields have already appeared in the pattern.
1178 let mut used_fields = FxHashMap::default();
1179 let mut no_field_errors = true;
1181 let mut inexistent_fields = vec![];
1182 // Typecheck each field.
1183 for &Spanned { node: ref field, span } in fields {
1184 let ident = tcx.adjust_ident(field.ident, variant.def_id, self.body_id).0;
1185 let field_ty = match used_fields.entry(ident) {
1186 Occupied(occupied) => {
1187 struct_span_err!(tcx.sess, span, E0025,
1188 "field `{}` bound multiple times \
1192 format!("multiple uses of `{}` in pattern", field.ident))
1193 .span_label(*occupied.get(), format!("first use of `{}`", field.ident))
1195 no_field_errors = false;
1199 vacant.insert(span);
1200 field_map.get(&ident)
1202 self.write_field_index(field.hir_id, *i);
1203 self.tcx.check_stability(f.did, Some(pat_id), span);
1204 self.field_ty(span, f, substs)
1206 .unwrap_or_else(|| {
1207 inexistent_fields.push(field.ident);
1208 no_field_errors = false;
1214 self.check_pat_walk(&field.pat, field_ty, def_bm, None);
1216 let mut unmentioned_fields = variant.fields
1218 .map(|field| field.ident.modern())
1219 .filter(|ident| !used_fields.contains_key(&ident))
1220 .collect::<Vec<_>>();
1221 if inexistent_fields.len() > 0 && !variant.recovered {
1222 let (field_names, t, plural) = if inexistent_fields.len() == 1 {
1223 (format!("a field named `{}`", inexistent_fields[0]), "this", "")
1225 (format!("fields named {}",
1226 inexistent_fields.iter()
1227 .map(|ident| format!("`{}`", ident))
1228 .collect::<Vec<String>>()
1229 .join(", ")), "these", "s")
1231 let spans = inexistent_fields.iter().map(|ident| ident.span).collect::<Vec<_>>();
1232 let mut err = struct_span_err!(tcx.sess,
1235 "{} `{}` does not have {}",
1237 tcx.def_path_str(variant.def_id),
1239 if let Some(ident) = inexistent_fields.last() {
1240 err.span_label(ident.span,
1241 format!("{} `{}` does not have {} field{}",
1243 tcx.def_path_str(variant.def_id),
1247 let input = unmentioned_fields.iter().map(|field| &field.name);
1248 let suggested_name =
1249 find_best_match_for_name(input, &ident.as_str(), None);
1250 if let Some(suggested_name) = suggested_name {
1251 err.span_suggestion(
1253 "a field with a similar name exists",
1254 suggested_name.to_string(),
1255 Applicability::MaybeIncorrect,
1258 // we don't want to throw `E0027` in case we have thrown `E0026` for them
1259 unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str());
1263 if tcx.sess.teach(&err.get_code().unwrap()) {
1265 "This error indicates that a struct pattern attempted to \
1266 extract a non-existent field from a struct. Struct fields \
1267 are identified by the name used before the colon : so struct \
1268 patterns should resemble the declaration of the struct type \
1270 If you are using shorthand field patterns but want to refer \
1271 to the struct field by a different name, you should rename \
1278 // Require `..` if struct has non_exhaustive attribute.
1279 if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
1280 span_err!(tcx.sess, span, E0638,
1281 "`..` required with {} marked as non-exhaustive",
1285 // Report an error if incorrect number of the fields were specified.
1286 if kind_name == "union" {
1287 if fields.len() != 1 {
1288 tcx.sess.span_err(span, "union patterns should have exactly one field");
1291 tcx.sess.span_err(span, "`..` cannot be used in union patterns");
1294 if unmentioned_fields.len() > 0 {
1295 let field_names = if unmentioned_fields.len() == 1 {
1296 format!("field `{}`", unmentioned_fields[0])
1298 format!("fields {}",
1299 unmentioned_fields.iter()
1300 .map(|name| format!("`{}`", name))
1301 .collect::<Vec<String>>()
1304 let mut diag = struct_span_err!(tcx.sess, span, E0027,
1305 "pattern does not mention {}",
1307 diag.span_label(span, format!("missing {}", field_names));
1308 if variant.ctor_kind == CtorKind::Fn {
1309 diag.note("trying to match a tuple variant with a struct variant pattern");
1311 if tcx.sess.teach(&diag.get_code().unwrap()) {
1313 "This error indicates that a pattern for a struct fails to specify a \
1314 sub-pattern for every one of the struct's fields. Ensure that each field \
1315 from the struct's definition is mentioned in the pattern, or use `..` to \
1316 ignore unwanted fields."