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 `run-pass/match-defbm*.rs`.
92 let mut pat_adjustments = vec![];
93 while let ty::Ref(_, inner_ty, inner_mutability) = exp_ty.sty {
94 debug!("inspecting {:?}", exp_ty);
96 debug!("current discriminant is Ref, inserting implicit deref");
97 // Preserve the reference type. We'll need it later during HAIR lowering.
98 pat_adjustments.push(exp_ty);
101 def_bm = match def_bm {
102 // If default binding mode is by value, make it `ref` or `ref mut`
103 // (depending on whether we observe `&` or `&mut`).
104 ty::BindByValue(_) =>
105 ty::BindByReference(inner_mutability),
107 // Once a `ref`, always a `ref`. This is because a `& &mut` can't mutate
108 // the underlying value.
109 ty::BindByReference(hir::Mutability::MutImmutable) =>
110 ty::BindByReference(hir::Mutability::MutImmutable),
112 // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref`
114 ty::BindByReference(hir::Mutability::MutMutable) =>
115 ty::BindByReference(inner_mutability),
120 if pat_adjustments.len() > 0 {
121 debug!("default binding mode is now {:?}", def_bm);
122 self.inh.tables.borrow_mut()
123 .pat_adjustments_mut()
124 .insert(pat.hir_id, pat_adjustments);
126 } else if let PatKind::Ref(..) = pat.node {
127 // When you encounter a `&pat` pattern, reset to "by
128 // value". This is so that `x` and `y` here are by value,
129 // as they appear to be:
132 // match &(&22, &44) {
138 def_bm = ty::BindByValue(hir::MutImmutable);
141 // Lose mutability now that we know binding mode and discriminant type.
143 let expected = expected;
145 let ty = match pat.node {
149 PatKind::Lit(ref lt) => {
150 // We've already computed the type above (when checking for a non-ref pat), so
151 // avoid computing it again.
152 let ty = self.node_ty(lt.hir_id);
154 // Byte string patterns behave the same way as array patterns
155 // They can denote both statically and dynamically-sized byte arrays.
157 if let hir::ExprKind::Lit(ref lt) = lt.node {
158 if let ast::LitKind::ByteStr(_) = lt.node {
159 let expected_ty = self.structurally_resolved_type(pat.span, expected);
160 if let ty::Ref(_, r_ty, _) = expected_ty.sty {
161 if let ty::Slice(_) = r_ty.sty {
162 pat_ty = tcx.mk_imm_ref(tcx.lifetimes.re_static,
163 tcx.mk_slice(tcx.types.u8))
169 // Somewhat surprising: in this case, the subtyping
170 // relation goes the opposite way as the other
171 // cases. Actually what we really want is not a subtyping
172 // relation at all but rather that there exists a LUB (so
173 // that they can be compared). However, in practice,
174 // constants are always scalars or strings. For scalars
175 // subtyping is irrelevant, and for strings `ty` is
176 // type is `&'static str`, so if we say that
178 // &'static str <: expected
180 // then that's equivalent to there existing a LUB.
181 if let Some(mut err) = self.demand_suptype_diag(pat.span, expected, pat_ty) {
182 err.emit_unless(discrim_span
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<'_>| ty.is_numeric() || ty.is_char();
200 let lhs_compat = numeric_or_char(lhs_ty);
201 let rhs_compat = numeric_or_char(rhs_ty);
203 if !lhs_compat || !rhs_compat {
204 let span = if !lhs_compat && !rhs_compat {
206 } else if !lhs_compat {
212 let mut err = struct_span_err!(
216 "only char and numeric types are allowed in range patterns"
218 err.span_label(span, "ranges require char or numeric types");
219 err.note(&format!("start type: {}", self.ty_to_string(lhs_ty)));
220 err.note(&format!("end type: {}", self.ty_to_string(rhs_ty)));
221 if tcx.sess.teach(&err.get_code().unwrap()) {
223 "In a match expression, only numbers and characters can be matched \
224 against a range. This is because the compiler checks that the range \
225 is non-empty at compile-time, and is unable to evaluate arbitrary \
226 comparison functions. If you want to capture values of an orderable \
227 type between two end-points, you can use a guard."
234 // Now that we know the types can be unified we find the unified type and use
235 // it to type the entire expression.
236 let common_type = self.resolve_vars_if_possible(&lhs_ty);
238 // Subtyping doesn't matter here, as the value is some kind of scalar.
239 self.demand_eqtype_pat(pat.span, expected, lhs_ty, discrim_span);
240 self.demand_eqtype_pat(pat.span, expected, rhs_ty, discrim_span);
243 PatKind::Binding(ba, var_id, _, ref sub) => {
244 let bm = if ba == hir::BindingAnnotation::Unannotated {
247 ty::BindingMode::convert(ba)
252 .pat_binding_modes_mut()
253 .insert(pat.hir_id, bm);
254 debug!("check_pat_walk: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
255 let local_ty = self.local_ty(pat.span, pat.hir_id).decl_ty;
257 ty::BindByReference(mutbl) => {
258 // If the binding is like
259 // ref x | ref const x | ref mut x
260 // then `x` is assigned a value of type `&M T` where M is the mutability
261 // and T is the expected type.
262 let region_var = self.next_region_var(infer::PatternRegion(pat.span));
263 let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
264 let region_ty = tcx.mk_ref(region_var, mt);
266 // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
267 // required. However, we use equality, which is stronger. See (*) for
269 self.demand_eqtype_pat(pat.span, region_ty, local_ty, discrim_span);
271 // Otherwise, the type of x is the expected type `T`.
272 ty::BindByValue(_) => {
273 // As above, `T <: typeof(x)` is required, but we
274 // use equality, see (*) below.
275 self.demand_eqtype_pat(pat.span, expected, local_ty, discrim_span);
279 // If there are multiple arms, make sure they all agree on
280 // what the type of the binding `x` ought to be.
281 if var_id != pat.hir_id {
282 let vt = self.local_ty(pat.span, var_id).decl_ty;
283 self.demand_eqtype_pat(pat.span, vt, local_ty, discrim_span);
286 if let Some(ref p) = *sub {
287 self.check_pat_walk(&p, expected, def_bm, discrim_span);
292 PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
293 self.check_pat_tuple_struct(
303 PatKind::Path(ref qpath) => {
304 self.check_pat_path(pat, path_resolution.unwrap(), qpath, expected)
306 PatKind::Struct(ref qpath, ref fields, etc) => {
307 self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, discrim_span)
309 PatKind::Tuple(ref elements, ddpos) => {
310 let mut expected_len = elements.len();
312 // Require known type only when `..` is present.
313 if let ty::Tuple(ref tys) =
314 self.structurally_resolved_type(pat.span, expected).sty {
315 expected_len = tys.len();
318 let max_len = cmp::max(expected_len, elements.len());
320 let element_tys_iter = (0..max_len).map(|_| {
321 Kind::from(self.next_ty_var(
322 // FIXME: `MiscVariable` for now -- obtaining the span and name information
323 // from all tuple elements isn't trivial.
325 kind: TypeVariableOriginKind::TypeInference,
330 let element_tys = tcx.mk_substs(element_tys_iter);
331 let pat_ty = tcx.mk_ty(ty::Tuple(element_tys));
332 if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) {
334 // Walk subpatterns with an expected type of `err` in this case to silence
335 // further errors being emitted when using the bindings. #50333
336 let element_tys_iter = (0..max_len).map(|_| tcx.types.err);
337 for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
338 self.check_pat_walk(elem, &tcx.types.err, def_bm, discrim_span);
340 tcx.mk_tup(element_tys_iter)
342 for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
345 &element_tys[i].expect_ty(),
353 PatKind::Box(ref inner) => {
354 let inner_ty = self.next_ty_var(TypeVariableOrigin {
355 kind: TypeVariableOriginKind::TypeInference,
358 let uniq_ty = tcx.mk_box(inner_ty);
360 if self.check_dereferencable(pat.span, expected, &inner) {
361 // Here, `demand::subtype` is good enough, but I don't
362 // think any errors can be introduced by using
364 self.demand_eqtype_pat(pat.span, expected, uniq_ty, discrim_span);
365 self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span);
368 self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span);
372 PatKind::Ref(ref inner, mutbl) => {
373 let expected = self.shallow_resolve(expected);
374 if self.check_dereferencable(pat.span, expected, &inner) {
375 // `demand::subtype` would be good enough, but using
376 // `eqtype` turns out to be equally general. See (*)
377 // below for details.
379 // Take region, inner-type from expected type if we
380 // can, to avoid creating needless variables. This
381 // also helps with the bad interactions of the given
382 // hack detailed in (*) below.
383 debug!("check_pat_walk: expected={:?}", expected);
384 let (rptr_ty, inner_ty) = match expected.sty {
385 ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => {
389 let inner_ty = self.next_ty_var(
391 kind: TypeVariableOriginKind::TypeInference,
395 let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
396 let region = self.next_region_var(infer::PatternRegion(pat.span));
397 let rptr_ty = tcx.mk_ref(region, mt);
398 debug!("check_pat_walk: demanding {:?} = {:?}", expected, rptr_ty);
399 let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
401 // Look for a case like `fn foo(&foo: u32)` and suggest
402 // `fn foo(foo: &u32)`
403 if let Some(mut err) = err {
404 self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected);
411 self.check_pat_walk(&inner, inner_ty, def_bm, discrim_span);
414 self.check_pat_walk(&inner, tcx.types.err, def_bm, discrim_span);
418 PatKind::Slice(ref before, ref slice, ref after) => {
419 let expected_ty = self.structurally_resolved_type(pat.span, expected);
420 let (inner_ty, slice_ty) = match expected_ty.sty {
421 ty::Array(inner_ty, size) => {
422 if let Some(size) = size.assert_usize(tcx) {
423 let min_len = before.len() as u64 + after.len() as u64;
427 tcx.sess, pat.span, E0527,
428 "pattern requires {} elements but array has {}",
430 .span_label(pat.span, format!("expected {} elements", size))
433 (inner_ty, tcx.types.err)
434 } else if let Some(rest) = size.checked_sub(min_len) {
435 (inner_ty, tcx.mk_array(inner_ty, rest))
437 struct_span_err!(tcx.sess, pat.span, E0528,
438 "pattern requires at least {} elements but array has {}",
440 .span_label(pat.span,
441 format!("pattern cannot match array of {} elements", size))
443 (inner_ty, tcx.types.err)
450 "cannot pattern-match on an array without a fixed length",
452 (inner_ty, tcx.types.err)
455 ty::Slice(inner_ty) => (inner_ty, expected_ty),
457 if !expected_ty.references_error() {
458 let mut err = struct_span_err!(
459 tcx.sess, pat.span, E0529,
460 "expected an array or slice, found `{}`",
462 if let ty::Ref(_, ty, _) = expected_ty.sty {
464 ty::Array(..) | ty::Slice(..) => {
465 err.help("the semantics of slice patterns changed \
466 recently; see issue #62254");
472 err.span_label( pat.span,
473 format!("pattern cannot match with input type `{}`", expected_ty)
476 (tcx.types.err, tcx.types.err)
481 self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span);
483 if let Some(ref slice) = *slice {
484 self.check_pat_walk(&slice, slice_ty, def_bm, discrim_span);
487 self.check_pat_walk(&elt, inner_ty, def_bm, discrim_span);
493 self.write_ty(pat.hir_id, ty);
495 // (*) In most of the cases above (literals and constants being
496 // the exception), we relate types using strict equality, even
497 // though subtyping would be sufficient. There are a few reasons
498 // for this, some of which are fairly subtle and which cost me
499 // (nmatsakis) an hour or two debugging to remember, so I thought
500 // I'd write them down this time.
502 // 1. There is no loss of expressiveness here, though it does
503 // cause some inconvenience. What we are saying is that the type
504 // of `x` becomes *exactly* what is expected. This can cause unnecessary
505 // errors in some cases, such as this one:
508 // fn foo<'x>(x: &'x int) {
515 // The reason we might get an error is that `z` might be
516 // assigned a type like `&'x int`, and then we would have
517 // a problem when we try to assign `&a` to `z`, because
518 // the lifetime of `&a` (i.e., the enclosing block) is
519 // shorter than `'x`.
521 // HOWEVER, this code works fine. The reason is that the
522 // expected type here is whatever type the user wrote, not
523 // the initializer's type. In this case the user wrote
524 // nothing, so we are going to create a type variable `Z`.
525 // Then we will assign the type of the initializer (`&'x
526 // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
527 // will instantiate `Z` as a type `&'0 int` where `'0` is
528 // a fresh region variable, with the constraint that `'x :
529 // '0`. So basically we're all set.
531 // Note that there are two tests to check that this remains true
532 // (`regions-reassign-{match,let}-bound-pointer.rs`).
534 // 2. Things go horribly wrong if we use subtype. The reason for
535 // THIS is a fairly subtle case involving bound regions. See the
536 // `givens` field in `region_constraints`, as well as the test
537 // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
538 // for details. Short version is that we must sometimes detect
539 // relationships between specific region variables and regions
540 // bound in a closure signature, and that detection gets thrown
541 // off when we substitute fresh region variables here to enable
545 fn borrow_pat_suggestion(
547 err: &mut DiagnosticBuilder<'_>,
553 if let PatKind::Binding(..) = inner.node {
554 let parent_id = tcx.hir().get_parent_node(pat.hir_id);
555 let parent = tcx.hir().get(parent_id);
556 debug!("inner {:?} pat {:?} parent {:?}", inner, pat, parent);
558 hir::Node::Item(hir::Item { node: hir::ItemKind::Fn(..), .. }) |
559 hir::Node::ForeignItem(hir::ForeignItem {
560 node: hir::ForeignItemKind::Fn(..), ..
562 hir::Node::TraitItem(hir::TraitItem { node: hir::TraitItemKind::Method(..), .. }) |
563 hir::Node::ImplItem(hir::ImplItem { node: hir::ImplItemKind::Method(..), .. }) => {
564 // this pat is likely an argument
565 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
566 // FIXME: turn into structured suggestion, will need a span that also
567 // includes the the arg's type.
568 err.help(&format!("did you mean `{}: &{}`?", snippet, expected));
572 hir::Node::Pat(_) => {
573 // rely on match ergonomics or it might be nested `&&pat`
574 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
577 "you can probably remove the explicit borrow",
579 Applicability::MaybeIncorrect,
583 _ => {} // don't provide suggestions in other cases #55175
588 pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
589 if let PatKind::Binding(..) = inner.node {
590 if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) {
591 if let ty::Dynamic(..) = mt.ty.sty {
592 // This is "x = SomeTrait" being reduced from
593 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
594 let type_str = self.ty_to_string(expected);
595 let mut err = struct_span_err!(
599 "type `{}` cannot be dereferenced",
602 err.span_label(span, format!("type `{}` cannot be dereferenced", type_str));
603 if self.tcx.sess.teach(&err.get_code().unwrap()) {
605 This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \
606 pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \
607 this type has no compile-time size. Therefore, all accesses to trait types must be through \
608 pointers. If you encounter this error you should try to avoid dereferencing the pointer.
610 You can read more about trait objects in the Trait Objects section of the Reference: \
611 https://doc.rust-lang.org/reference/types.html#trait-objects");
623 expr: &'tcx hir::Expr,
624 discrim: &'tcx hir::Expr,
625 arms: &'tcx [hir::Arm],
626 expected: Expectation<'tcx>,
627 match_src: hir::MatchSource,
631 use hir::MatchSource::*;
632 let (source_if, if_no_else, force_scrutinee_bool) = match match_src {
633 IfDesugar { contains_else_clause } => (true, !contains_else_clause, true),
634 IfLetDesugar { contains_else_clause } => (true, !contains_else_clause, false),
635 WhileDesugar => (false, false, true),
636 _ => (false, false, false),
639 // Type check the descriminant and get its type.
640 let discrim_ty = if force_scrutinee_bool {
641 // Here we want to ensure:
643 // 1. That default match bindings are *not* accepted in the condition of an
644 // `if` expression. E.g. given `fn foo() -> &bool;` we reject `if foo() { .. }`.
646 // 2. By expecting `bool` for `expr` we get nice diagnostics for e.g. `if x = y { .. }`.
648 // FIXME(60707): Consider removing hack with principled solution.
649 self.check_expr_has_type_or_error(discrim, self.tcx.types.bool)
651 self.demand_discriminant_type(arms, discrim)
654 // If there are no arms, that is a diverging match; a special case.
656 self.diverges.set(self.diverges.get() | Diverges::Always);
657 return tcx.types.never;
660 self.warn_arms_when_scrutinee_diverges(arms, match_src);
662 // Otherwise, we have to union together the types that the
663 // arms produce and so forth.
664 let discrim_diverges = self.diverges.get();
665 self.diverges.set(Diverges::Maybe);
667 // rust-lang/rust#55810: Typecheck patterns first (via eager
668 // collection into `Vec`), so we get types for all bindings.
669 let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| {
670 let mut all_pats_diverge = Diverges::WarnedAlways;
672 self.diverges.set(Diverges::Maybe);
673 let binding_mode = ty::BindingMode::BindByValue(hir::Mutability::MutImmutable);
674 self.check_pat_walk(&p, discrim_ty, binding_mode, Some(discrim.span));
675 all_pats_diverge &= self.diverges.get();
678 // As discussed with @eddyb, this is for disabling unreachable_code
679 // warnings on patterns (they're now subsumed by unreachable_patterns
681 match all_pats_diverge {
682 Diverges::Maybe => Diverges::Maybe,
683 Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
687 // Now typecheck the blocks.
689 // The result of the match is the common supertype of all the
690 // arms. Start out the value as bottom, since it's the, well,
691 // bottom the type lattice, and we'll be moving up the lattice as
692 // we process each arm. (Note that any match with 0 arms is matching
693 // on any empty type and is therefore unreachable; should the flow
694 // of execution reach it, we will panic, so bottom is an appropriate
695 // type in that case)
696 let mut all_arms_diverge = Diverges::WarnedAlways;
698 let expected = expected.adjust_for_branches(self);
701 let coerce_first = match expected {
702 // We don't coerce to `()` so that if the match expression is a
703 // statement it's branches can have any consistent type. That allows
704 // us to give better error messages (pointing to a usually better
705 // arm for inconsistent arms or to the whole match when a `()` type
707 Expectation::ExpectHasType(ety) if ety != self.tcx.mk_unit() => ety,
708 _ => self.next_ty_var(TypeVariableOrigin {
709 kind: TypeVariableOriginKind::MiscVariable,
713 CoerceMany::with_coercion_sites(coerce_first, arms)
716 let mut other_arms = vec![]; // used only for diagnostics
717 let mut prior_arm_ty = None;
718 for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
719 if let Some(g) = &arm.guard {
720 self.diverges.set(pats_diverge);
722 hir::Guard::If(e) => self.check_expr_has_type_or_error(e, tcx.types.bool),
726 self.diverges.set(pats_diverge);
727 let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
728 all_arms_diverge &= self.diverges.get();
730 let span = expr.span;
733 let then_expr = &arms[0].body;
734 match (i, if_no_else) {
735 (0, _) => coercion.coerce(self, &self.misc(span), &arm.body, arm_ty),
736 (_, true) => self.if_fallback_coercion(span, then_expr, &mut coercion),
738 let then_ty = prior_arm_ty.unwrap();
739 let cause = self.if_cause(span, then_expr, &arm.body, then_ty, arm_ty);
740 coercion.coerce(self, &cause, &arm.body, arm_ty);
744 let arm_span = if let hir::ExprKind::Block(blk, _) = &arm.body.node {
745 // Point at the block expr instead of the entire block
746 blk.expr.as_ref().map(|e| e.span).unwrap_or(arm.body.span)
750 let (span, code) = match i {
751 // The reason for the first arm to fail is not that the match arms diverge,
752 // but rather that there's a prior obligation that doesn't hold.
753 0 => (arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id)),
754 _ => (span, ObligationCauseCode::MatchExpressionArm {
757 prior_arms: other_arms.clone(),
758 last_ty: prior_arm_ty.unwrap(),
759 discrim_hir_id: discrim.hir_id,
762 let cause = self.cause(span, code);
763 coercion.coerce(self, &cause, &arm.body, arm_ty);
764 other_arms.push(arm_span);
765 if other_arms.len() > 5 {
766 other_arms.remove(0);
769 prior_arm_ty = Some(arm_ty);
772 // We won't diverge unless the discriminant or all arms diverge.
773 self.diverges.set(discrim_diverges | all_arms_diverge);
775 coercion.complete(self)
778 /// When the previously checked expression (the scrutinee) diverges,
779 /// warn the user about the match arms being unreachable.
780 fn warn_arms_when_scrutinee_diverges(&self, arms: &'tcx [hir::Arm], source: hir::MatchSource) {
781 if self.diverges.get().always() {
782 use hir::MatchSource::*;
783 let msg = match source {
784 IfDesugar { .. } | IfLetDesugar { .. } => "block in `if` expression",
785 WhileDesugar { .. } | WhileLetDesugar { .. } => "block in `while` expression",
789 self.warn_if_unreachable(arm.body.hir_id, arm.body.span, msg);
794 /// Handle the fallback arm of a desugared if(-let) like a missing else.
795 fn if_fallback_coercion(
798 then_expr: &'tcx hir::Expr,
799 coercion: &mut CoerceMany<'tcx, '_, rustc::hir::Arm>,
801 // If this `if` expr is the parent's function return expr,
802 // the cause of the type coercion is the return type, point at it. (#25228)
803 let ret_reason = self.maybe_get_coercion_reason(then_expr.hir_id, span);
804 let cause = self.cause(span, ObligationCauseCode::IfExpressionWithNoElse);
805 coercion.coerce_forced_unit(self, &cause, &mut |err| {
806 if let Some((span, msg)) = &ret_reason {
807 err.span_label(*span, msg.as_str());
808 } else if let ExprKind::Block(block, _) = &then_expr.node {
809 if let Some(expr) = &block.expr {
810 err.span_label(expr.span, "found here".to_string());
813 err.note("`if` expressions without `else` evaluate to `()`");
814 err.help("consider adding an `else` block that evaluates to the expected type");
815 }, ret_reason.is_none());
818 fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, span: Span) -> Option<(Span, String)> {
819 use hir::Node::{Block, Item, Local};
821 let hir = self.tcx.hir();
822 let arm_id = hir.get_parent_node(hir_id);
823 let match_id = hir.get_parent_node(arm_id);
824 let containing_id = hir.get_parent_node(match_id);
826 let node = hir.get(containing_id);
827 if let Block(block) = node {
828 // check that the body's parent is an fn
829 let parent = hir.get(
831 hir.get_parent_node(block.hir_id),
834 if let (Some(expr), Item(hir::Item {
835 node: hir::ItemKind::Fn(..), ..
836 })) = (&block.expr, parent) {
837 // check that the `if` expr without `else` is the fn body's expr
838 if expr.span == span {
839 return self.get_fn_decl(hir_id).map(|(fn_decl, _)| (
840 fn_decl.output.span(),
841 format!("expected `{}` because of this return type", fn_decl.output),
846 if let Local(hir::Local { ty: Some(_), pat, .. }) = node {
847 return Some((pat.span, "expected because of this assignment".to_string()));
855 then_expr: &'tcx hir::Expr,
856 else_expr: &'tcx hir::Expr,
859 ) -> ObligationCause<'tcx> {
860 let mut outer_sp = if self.tcx.sess.source_map().is_multiline(span) {
861 // The `if`/`else` isn't in one line in the output, include some context to make it
862 // clear it is an if/else expression:
864 // LL | let x = if true {
867 // || ----- expected because of this
870 // || ^^^^^ expected i32, found u32
872 // ||_____- if and else have incompatible types
876 // The entire expression is in one line, only point at the arms
878 // LL | let x = if true { 10i32 } else { 10u32 };
879 // | ----- ^^^^^ expected i32, found u32
881 // | expected because of this
886 let mut remove_semicolon = None;
887 let error_sp = if let ExprKind::Block(block, _) = &else_expr.node {
888 if let Some(expr) = &block.expr {
890 } else if let Some(stmt) = block.stmts.last() {
891 // possibly incorrect trailing `;` in the else arm
892 remove_semicolon = self.could_remove_semicolon(block, then_ty);
894 } else { // empty block; point at its entirety
895 // Avoid overlapping spans that aren't as readable:
897 // 2 | let x = if true {
900 // | | - expected because of this
907 // | |______if and else have incompatible types
908 // | expected integer, found ()
910 // by not pointing at the entire expression:
912 // 2 | let x = if true {
913 // | ------- if and else have incompatible types
915 // | - expected because of this
920 // | |_____^ expected integer, found ()
922 if outer_sp.is_some() {
923 outer_sp = Some(self.tcx.sess.source_map().def_span(span));
927 } else { // shouldn't happen unless the parser has done something weird
931 // Compute `Span` of `then` part of `if`-expression.
932 let then_sp = if let ExprKind::Block(block, _) = &then_expr.node {
933 if let Some(expr) = &block.expr {
935 } else if let Some(stmt) = block.stmts.last() {
936 // possibly incorrect trailing `;` in the else arm
937 remove_semicolon = remove_semicolon.or(self.could_remove_semicolon(block, else_ty));
939 } else { // empty block; point at its entirety
940 outer_sp = None; // same as in `error_sp`; cleanup output
943 } else { // shouldn't happen unless the parser has done something weird
947 // Finally construct the cause:
948 self.cause(error_sp, ObligationCauseCode::IfExpression {
951 semicolon: remove_semicolon,
955 fn demand_discriminant_type(
957 arms: &'tcx [hir::Arm],
958 discrim: &'tcx hir::Expr,
960 // Not entirely obvious: if matches may create ref bindings, we want to
961 // use the *precise* type of the discriminant, *not* some supertype, as
962 // the "discriminant type" (issue #23116).
964 // arielb1 [writes here in this comment thread][c] that there
965 // is certainly *some* potential danger, e.g., for an example
968 // [c]: https://github.com/rust-lang/rust/pull/43399#discussion_r130223956
971 // let Foo(x) = f()[0];
974 // Then if the pattern matches by reference, we want to match
975 // `f()[0]` as a lexpr, so we can't allow it to be
976 // coerced. But if the pattern matches by value, `f()[0]` is
977 // still syntactically a lexpr, but we *do* want to allow
980 // However, *likely* we are ok with allowing coercions to
981 // happen if there are no explicit ref mut patterns - all
982 // implicit ref mut patterns must occur behind a reference, so
983 // they will have the "correct" variance and lifetime.
985 // This does mean that the following pattern would be legal:
990 // impl Deref for Foo {
991 // type Target = Bar;
992 // fn deref(&self) -> &Bar { &self.0 }
994 // impl DerefMut for Foo {
995 // fn deref_mut(&mut self) -> &mut Bar { &mut self.0 }
997 // fn foo(x: &mut Foo) {
999 // let Bar(z): &mut Bar = x;
1002 // assert_eq!(foo.0.0, 42);
1006 // FIXME(tschottdorf): don't call contains_explicit_ref_binding, which
1007 // is problematic as the HIR is being scraped, but ref bindings may be
1008 // implicit after #42640. We need to make sure that pat_adjustments
1009 // (once introduced) is populated by the time we get here.
1012 let contains_ref_bindings = arms.iter()
1013 .filter_map(|a| a.contains_explicit_ref_binding())
1014 .max_by_key(|m| match *m {
1015 hir::MutMutable => 1,
1016 hir::MutImmutable => 0,
1019 if let Some(m) = contains_ref_bindings {
1020 self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m))
1022 // ...but otherwise we want to use any supertype of the
1023 // discriminant. This is sort of a workaround, see note (*) in
1024 // `check_pat` for some details.
1025 let discrim_ty = self.next_ty_var(TypeVariableOrigin {
1026 kind: TypeVariableOriginKind::TypeInference,
1029 self.check_expr_has_type_or_error(discrim, discrim_ty);
1034 fn check_pat_struct(
1036 pat: &'tcx hir::Pat,
1038 fields: &'tcx [Spanned<hir::FieldPat>],
1041 def_bm: ty::BindingMode,
1042 discrim_span: Option<Span>,
1044 // Resolve the path and check the definition for errors.
1045 let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.hir_id)
1049 for field in fields {
1050 self.check_pat_walk(&field.node.pat, self.tcx.types.err, def_bm, discrim_span);
1052 return self.tcx.types.err;
1055 // Type-check the path.
1056 self.demand_eqtype_pat(pat.span, expected, pat_ty, discrim_span);
1058 // Type-check subpatterns.
1059 if self.check_struct_pat_fields(pat_ty, pat.hir_id, pat.span, variant, fields, etc, def_bm)
1070 path_resolution: (Res, Option<Ty<'tcx>>, &'b [hir::PathSegment]),
1076 // We have already resolved the path.
1077 let (res, opt_ty, segments) = path_resolution;
1080 self.set_tainted_by_errors();
1081 return tcx.types.err;
1083 Res::Def(DefKind::Method, _) |
1084 Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _) |
1085 Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => {
1086 report_unexpected_variant_res(tcx, res, pat.span, qpath);
1087 return tcx.types.err;
1089 Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::SelfCtor(..) |
1090 Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => {} // OK
1091 _ => bug!("unexpected pattern resolution: {:?}", res)
1094 // Type-check the path.
1095 let pat_ty = self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id).0;
1096 self.demand_suptype(pat.span, expected, pat_ty);
1100 fn check_pat_tuple_struct(
1104 subpats: &'tcx [P<hir::Pat>],
1105 ddpos: Option<usize>,
1107 def_bm: ty::BindingMode,
1108 match_arm_pat_span: Option<Span>,
1112 for pat in subpats {
1113 self.check_pat_walk(&pat, tcx.types.err, def_bm, match_arm_pat_span);
1116 let report_unexpected_res = |res: Res| {
1117 let msg = format!("expected tuple struct/variant, found {} `{}`",
1119 hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false)));
1120 let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg);
1121 match (res, &pat.node) {
1122 (Res::Def(DefKind::Fn, _), _) | (Res::Def(DefKind::Method, _), _) => {
1123 err.span_label(pat.span, "`fn` calls are not allowed in patterns");
1124 err.help("for more information, visit \
1125 https://doc.rust-lang.org/book/ch18-00-patterns.html");
1128 err.span_label(pat.span, "not a tuple variant or struct");
1135 // Resolve the path and check the definition for errors.
1136 let (res, opt_ty, segments) = self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span);
1137 if res == Res::Err {
1138 self.set_tainted_by_errors();
1140 return self.tcx.types.err;
1143 // Type-check the path.
1144 let (pat_ty, res) = self.instantiate_value_path(segments, opt_ty, res, pat.span,
1146 if !pat_ty.is_fn() {
1147 report_unexpected_res(res);
1148 return self.tcx.types.err;
1151 let variant = match res {
1153 self.set_tainted_by_errors();
1155 return tcx.types.err;
1157 Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::Method, _) => {
1158 report_unexpected_res(res);
1159 return tcx.types.err;
1161 Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => {
1162 tcx.expect_variant_res(res)
1164 _ => bug!("unexpected pattern resolution: {:?}", res)
1167 // Replace constructor type with constructed type for tuple struct patterns.
1168 let pat_ty = pat_ty.fn_sig(tcx).output();
1169 let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
1171 self.demand_eqtype_pat(pat.span, expected, pat_ty, match_arm_pat_span);
1173 // Type-check subpatterns.
1174 if subpats.len() == variant.fields.len() ||
1175 subpats.len() < variant.fields.len() && ddpos.is_some() {
1176 let substs = match pat_ty.sty {
1177 ty::Adt(_, substs) => substs,
1178 _ => bug!("unexpected pattern type {:?}", pat_ty),
1180 for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
1181 let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
1182 self.check_pat_walk(&subpat, field_ty, def_bm, match_arm_pat_span);
1184 self.tcx.check_stability(variant.fields[i].did, Some(pat.hir_id), subpat.span);
1187 let subpats_ending = if subpats.len() == 1 { "" } else { "s" };
1188 let fields_ending = if variant.fields.len() == 1 { "" } else { "s" };
1189 struct_span_err!(tcx.sess, pat.span, E0023,
1190 "this pattern has {} field{}, but the corresponding {} has {} field{}",
1191 subpats.len(), subpats_ending, res.descr(),
1192 variant.fields.len(), fields_ending)
1193 .span_label(pat.span, format!("expected {} field{}, found {}",
1194 variant.fields.len(), fields_ending, subpats.len()))
1197 return tcx.types.err;
1202 fn check_struct_pat_fields(
1207 variant: &'tcx ty::VariantDef,
1208 fields: &'tcx [Spanned<hir::FieldPat>],
1210 def_bm: ty::BindingMode,
1214 let (substs, adt) = match adt_ty.sty {
1215 ty::Adt(adt, substs) => (substs, adt),
1216 _ => span_bug!(span, "struct pattern is not an ADT")
1218 let kind_name = adt.variant_descr();
1220 // Index the struct fields' types.
1221 let field_map = variant.fields
1224 .map(|(i, field)| (field.ident.modern(), (i, field)))
1225 .collect::<FxHashMap<_, _>>();
1227 // Keep track of which fields have already appeared in the pattern.
1228 let mut used_fields = FxHashMap::default();
1229 let mut no_field_errors = true;
1231 let mut inexistent_fields = vec![];
1232 // Typecheck each field.
1233 for &Spanned { node: ref field, span } in fields {
1234 let ident = tcx.adjust_ident(field.ident, variant.def_id);
1235 let field_ty = match used_fields.entry(ident) {
1236 Occupied(occupied) => {
1237 struct_span_err!(tcx.sess, span, E0025,
1238 "field `{}` bound multiple times \
1242 format!("multiple uses of `{}` in pattern", field.ident))
1243 .span_label(*occupied.get(), format!("first use of `{}`", field.ident))
1245 no_field_errors = false;
1249 vacant.insert(span);
1250 field_map.get(&ident)
1252 self.write_field_index(field.hir_id, *i);
1253 self.tcx.check_stability(f.did, Some(pat_id), span);
1254 self.field_ty(span, f, substs)
1256 .unwrap_or_else(|| {
1257 inexistent_fields.push(field.ident);
1258 no_field_errors = false;
1264 self.check_pat_walk(&field.pat, field_ty, def_bm, None);
1266 let mut unmentioned_fields = variant.fields
1268 .map(|field| field.ident.modern())
1269 .filter(|ident| !used_fields.contains_key(&ident))
1270 .collect::<Vec<_>>();
1271 if inexistent_fields.len() > 0 && !variant.recovered {
1272 let (field_names, t, plural) = if inexistent_fields.len() == 1 {
1273 (format!("a field named `{}`", inexistent_fields[0]), "this", "")
1275 (format!("fields named {}",
1276 inexistent_fields.iter()
1277 .map(|ident| format!("`{}`", ident))
1278 .collect::<Vec<String>>()
1279 .join(", ")), "these", "s")
1281 let spans = inexistent_fields.iter().map(|ident| ident.span).collect::<Vec<_>>();
1282 let mut err = struct_span_err!(tcx.sess,
1285 "{} `{}` does not have {}",
1287 tcx.def_path_str(variant.def_id),
1289 if let Some(ident) = inexistent_fields.last() {
1290 err.span_label(ident.span,
1291 format!("{} `{}` does not have {} field{}",
1293 tcx.def_path_str(variant.def_id),
1297 let input = unmentioned_fields.iter().map(|field| &field.name);
1298 let suggested_name =
1299 find_best_match_for_name(input, &ident.as_str(), None);
1300 if let Some(suggested_name) = suggested_name {
1301 err.span_suggestion(
1303 "a field with a similar name exists",
1304 suggested_name.to_string(),
1305 Applicability::MaybeIncorrect,
1308 // we don't want to throw `E0027` in case we have thrown `E0026` for them
1309 unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str());
1313 if tcx.sess.teach(&err.get_code().unwrap()) {
1315 "This error indicates that a struct pattern attempted to \
1316 extract a non-existent field from a struct. Struct fields \
1317 are identified by the name used before the colon : so struct \
1318 patterns should resemble the declaration of the struct type \
1320 If you are using shorthand field patterns but want to refer \
1321 to the struct field by a different name, you should rename \
1328 // Require `..` if struct has non_exhaustive attribute.
1329 if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
1330 span_err!(tcx.sess, span, E0638,
1331 "`..` required with {} marked as non-exhaustive",
1335 // Report an error if incorrect number of the fields were specified.
1336 if kind_name == "union" {
1337 if fields.len() != 1 {
1338 tcx.sess.span_err(span, "union patterns should have exactly one field");
1341 tcx.sess.span_err(span, "`..` cannot be used in union patterns");
1344 if unmentioned_fields.len() > 0 {
1345 let field_names = if unmentioned_fields.len() == 1 {
1346 format!("field `{}`", unmentioned_fields[0])
1348 format!("fields {}",
1349 unmentioned_fields.iter()
1350 .map(|name| format!("`{}`", name))
1351 .collect::<Vec<String>>()
1354 let mut diag = struct_span_err!(tcx.sess, span, E0027,
1355 "pattern does not mention {}",
1357 diag.span_label(span, format!("missing {}", field_names));
1358 if variant.ctor_kind == CtorKind::Fn {
1359 diag.note("trying to match a tuple variant with a struct variant pattern");
1361 if tcx.sess.teach(&diag.get_code().unwrap()) {
1363 "This error indicates that a pattern for a struct fails to specify a \
1364 sub-pattern for every one of the struct's fields. Ensure that each field \
1365 from the struct's definition is mentioned in the pattern, or use `..` to \
1366 ignore unwanted fields."