1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use rustc::hir::{self, PatKind};
12 use rustc::hir::def::{Def, CtorKind};
13 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
15 use rustc::infer::type_variable::TypeVariableOrigin;
16 use rustc::traits::ObligationCauseCode;
17 use rustc::ty::{self, Ty, TypeFoldable};
18 use check::{FnCtxt, Expectation, Diverges, Needs};
19 use check::coercion::CoerceMany;
20 use util::nodemap::FxHashMap;
22 use std::collections::hash_map::Entry::{Occupied, Vacant};
25 use syntax::source_map::Spanned;
27 use syntax::util::lev_distance::find_best_match_for_name;
30 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
31 /// The `is_arg` argument indicates whether this pattern is the
32 /// *outermost* pattern in an argument (e.g., in `fn foo(&x:
33 /// &u32)`, it is true for the `&x` pattern but not `x`). This is
34 /// used to tailor error reporting.
35 pub fn check_pat_walk(
38 mut expected: Ty<'tcx>,
39 mut def_bm: ty::BindingMode,
44 debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?},is_arg={})",
45 pat, expected, def_bm, is_arg);
47 let is_non_ref_pat = match pat.node {
49 PatKind::TupleStruct(..) |
53 PatKind::Slice(..) => true,
54 PatKind::Lit(ref lt) => {
55 let ty = self.check_expr(lt);
61 PatKind::Path(ref qpath) => {
62 let (def, _, _) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
64 Def::Const(..) | Def::AssociatedConst(..) => false,
69 PatKind::Binding(..) |
70 PatKind::Ref(..) => false,
73 debug!("pattern is non reference pattern");
74 let mut exp_ty = self.resolve_type_vars_with_obligations(&expected);
76 // Peel off as many `&` or `&mut` from the discriminant as possible. For example,
77 // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
78 // the `Some(5)` which is not of type Ref.
80 // For each ampersand peeled off, update the binding mode and push the original
81 // type into the adjustments vector.
83 // See the examples in `run-pass/match-defbm*.rs`.
84 let mut pat_adjustments = vec![];
85 while let ty::Ref(_, inner_ty, inner_mutability) = exp_ty.sty {
86 debug!("inspecting {:?} with type {:?}", exp_ty, exp_ty.sty);
88 debug!("current discriminant is Ref, inserting implicit deref");
89 // Preserve the reference type. We'll need it later during HAIR lowering.
90 pat_adjustments.push(exp_ty);
93 def_bm = match def_bm {
94 // If default binding mode is by value, make it `ref` or `ref mut`
95 // (depending on whether we observe `&` or `&mut`).
97 ty::BindByReference(inner_mutability),
99 // Once a `ref`, always a `ref`. This is because a `& &mut` can't mutate
100 // the underlying value.
101 ty::BindByReference(hir::Mutability::MutImmutable) =>
102 ty::BindByReference(hir::Mutability::MutImmutable),
104 // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref`
106 ty::BindByReference(hir::Mutability::MutMutable) =>
107 ty::BindByReference(inner_mutability),
112 if pat_adjustments.len() > 0 {
113 debug!("default binding mode is now {:?}", def_bm);
114 self.inh.tables.borrow_mut()
115 .pat_adjustments_mut()
116 .insert(pat.hir_id, pat_adjustments);
118 } else if let PatKind::Ref(..) = pat.node {
119 // When you encounter a `&pat` pattern, reset to "by
120 // value". This is so that `x` and `y` here are by value,
121 // as they appear to be:
124 // match &(&22, &44) {
130 def_bm = ty::BindByValue(hir::MutImmutable);
133 // Lose mutability now that we know binding mode and discriminant type.
135 let expected = expected;
137 let ty = match pat.node {
141 PatKind::Lit(ref lt) => {
142 // We've already computed the type above (when checking for a non-ref pat), so
143 // avoid computing it again.
144 let ty = self.node_ty(lt.hir_id);
146 // Byte string patterns behave the same way as array patterns
147 // They can denote both statically and dynamically sized byte arrays
149 if let hir::ExprKind::Lit(ref lt) = lt.node {
150 if let ast::LitKind::ByteStr(_) = lt.node {
151 let expected_ty = self.structurally_resolved_type(pat.span, expected);
152 if let ty::Ref(_, r_ty, _) = expected_ty.sty {
153 if let ty::Slice(_) = r_ty.sty {
154 pat_ty = tcx.mk_imm_ref(tcx.types.re_static,
155 tcx.mk_slice(tcx.types.u8))
161 // somewhat surprising: in this case, the subtyping
162 // relation goes the opposite way as the other
163 // cases. Actually what we really want is not a subtyping
164 // relation at all but rather that there exists a LUB (so
165 // that they can be compared). However, in practice,
166 // constants are always scalars or strings. For scalars
167 // subtyping is irrelevant, and for strings `ty` is
168 // type is `&'static str`, so if we say that
170 // &'static str <: expected
172 // that's equivalent to there existing a LUB.
173 self.demand_suptype(pat.span, expected, pat_ty);
176 PatKind::Range(ref begin, ref end, _) => {
177 let lhs_ty = self.check_expr(begin);
178 let rhs_ty = self.check_expr(end);
180 // Check that both end-points are of numeric or char type.
181 let numeric_or_char = |ty: Ty| ty.is_numeric() || ty.is_char();
182 let lhs_compat = numeric_or_char(lhs_ty);
183 let rhs_compat = numeric_or_char(rhs_ty);
185 if !lhs_compat || !rhs_compat {
186 let span = if !lhs_compat && !rhs_compat {
188 } else if !lhs_compat {
194 let mut err = struct_span_err!(
198 "only char and numeric types are allowed in range patterns"
200 err.span_label(span, "ranges require char or numeric types");
201 err.note(&format!("start type: {}", self.ty_to_string(lhs_ty)));
202 err.note(&format!("end type: {}", self.ty_to_string(rhs_ty)));
203 if tcx.sess.teach(&err.get_code().unwrap()) {
205 "In a match expression, only numbers and characters can be matched \
206 against a range. This is because the compiler checks that the range \
207 is non-empty at compile-time, and is unable to evaluate arbitrary \
208 comparison functions. If you want to capture values of an orderable \
209 type between two end-points, you can use a guard."
216 // Now that we know the types can be unified we find the unified type and use
217 // it to type the entire expression.
218 let common_type = self.resolve_type_vars_if_possible(&lhs_ty);
220 // subtyping doesn't matter here, as the value is some kind of scalar
221 self.demand_eqtype(pat.span, expected, lhs_ty);
222 self.demand_eqtype(pat.span, expected, rhs_ty);
225 PatKind::Binding(ba, var_id, _, ref sub) => {
226 let bm = if ba == hir::BindingAnnotation::Unannotated {
229 ty::BindingMode::convert(ba)
234 .pat_binding_modes_mut()
235 .insert(pat.hir_id, bm);
236 debug!("check_pat_walk: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
237 let local_ty = self.local_ty(pat.span, pat.id).decl_ty;
239 ty::BindByReference(mutbl) => {
240 // if the binding is like
241 // ref x | ref const x | ref mut x
242 // then `x` is assigned a value of type `&M T` where M is the mutability
243 // and T is the expected type.
244 let region_var = self.next_region_var(infer::PatternRegion(pat.span));
245 let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
246 let region_ty = tcx.mk_ref(region_var, mt);
248 // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
249 // required. However, we use equality, which is stronger. See (*) for
251 self.demand_eqtype(pat.span, region_ty, local_ty);
253 // otherwise the type of x is the expected type T
254 ty::BindByValue(_) => {
255 // As above, `T <: typeof(x)` is required but we
256 // use equality, see (*) below.
257 self.demand_eqtype(pat.span, expected, local_ty);
261 // if there are multiple arms, make sure they all agree on
262 // what the type of the binding `x` ought to be
263 if var_id != pat.id {
264 let vt = self.local_ty(pat.span, var_id).decl_ty;
265 self.demand_eqtype(pat.span, vt, local_ty);
268 if let Some(ref p) = *sub {
269 self.check_pat_walk(&p, expected, def_bm, true);
274 PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
275 self.check_pat_tuple_struct(pat, qpath, &subpats, ddpos, expected, def_bm)
277 PatKind::Path(ref qpath) => {
278 self.check_pat_path(pat, qpath, expected)
280 PatKind::Struct(ref qpath, ref fields, etc) => {
281 self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm)
283 PatKind::Tuple(ref elements, ddpos) => {
284 let mut expected_len = elements.len();
286 // Require known type only when `..` is present
287 if let ty::Tuple(ref tys) =
288 self.structurally_resolved_type(pat.span, expected).sty {
289 expected_len = tys.len();
292 let max_len = cmp::max(expected_len, elements.len());
294 let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(
295 // FIXME: MiscVariable for now, obtaining the span and name information
296 // from all tuple elements isn't trivial.
297 TypeVariableOrigin::TypeInference(pat.span)));
298 let element_tys = tcx.mk_type_list(element_tys_iter);
299 let pat_ty = tcx.mk_ty(ty::Tuple(element_tys));
300 if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) {
302 // Walk subpatterns with an expected type of `err` in this case to silence
303 // further errors being emitted when using the bindings. #50333
304 let element_tys_iter = (0..max_len).map(|_| tcx.types.err);
305 for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
306 self.check_pat_walk(elem, &tcx.types.err, def_bm, true);
308 tcx.mk_tup(element_tys_iter)
310 for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
311 self.check_pat_walk(elem, &element_tys[i], def_bm, true);
316 PatKind::Box(ref inner) => {
317 let inner_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(inner.span));
318 let uniq_ty = tcx.mk_box(inner_ty);
320 if self.check_dereferencable(pat.span, expected, &inner) {
321 // Here, `demand::subtype` is good enough, but I don't
322 // think any errors can be introduced by using
324 self.demand_eqtype(pat.span, expected, uniq_ty);
325 self.check_pat_walk(&inner, inner_ty, def_bm, true);
328 self.check_pat_walk(&inner, tcx.types.err, def_bm, true);
332 PatKind::Ref(ref inner, mutbl) => {
333 let expected = self.shallow_resolve(expected);
334 if self.check_dereferencable(pat.span, expected, &inner) {
335 // `demand::subtype` would be good enough, but using
336 // `eqtype` turns out to be equally general. See (*)
337 // below for details.
339 // Take region, inner-type from expected type if we
340 // can, to avoid creating needless variables. This
341 // also helps with the bad interactions of the given
342 // hack detailed in (*) below.
343 debug!("check_pat_walk: expected={:?}", expected);
344 let (rptr_ty, inner_ty) = match expected.sty {
345 ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => {
349 let inner_ty = self.next_ty_var(
350 TypeVariableOrigin::TypeInference(inner.span));
351 let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
352 let region = self.next_region_var(infer::PatternRegion(pat.span));
353 let rptr_ty = tcx.mk_ref(region, mt);
354 debug!("check_pat_walk: demanding {:?} = {:?}", expected, rptr_ty);
355 let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
357 // Look for a case like `fn foo(&foo: u32)` and suggest
358 // `fn foo(foo: &u32)`
359 if let Some(mut err) = err {
361 if let PatKind::Binding(..) = inner.node {
362 if let Ok(snippet) = tcx.sess.source_map()
363 .span_to_snippet(pat.span)
365 err.help(&format!("did you mean `{}: &{}`?",
377 self.check_pat_walk(&inner, inner_ty, def_bm, true);
380 self.check_pat_walk(&inner, tcx.types.err, def_bm, true);
384 PatKind::Slice(ref before, ref slice, ref after) => {
385 let expected_ty = self.structurally_resolved_type(pat.span, expected);
386 let (inner_ty, slice_ty) = match expected_ty.sty {
387 ty::Array(inner_ty, size) => {
388 let size = size.unwrap_usize(tcx);
389 let min_len = before.len() as u64 + after.len() as u64;
393 tcx.sess, pat.span, E0527,
394 "pattern requires {} elements but array has {}",
396 .span_label(pat.span, format!("expected {} elements", size))
399 (inner_ty, tcx.types.err)
400 } else if let Some(rest) = size.checked_sub(min_len) {
401 (inner_ty, tcx.mk_array(inner_ty, rest))
403 struct_span_err!(tcx.sess, pat.span, E0528,
404 "pattern requires at least {} elements but array has {}",
406 .span_label(pat.span,
407 format!("pattern cannot match array of {} elements", size))
409 (inner_ty, tcx.types.err)
412 ty::Slice(inner_ty) => (inner_ty, expected_ty),
414 if !expected_ty.references_error() {
415 let mut err = struct_span_err!(
416 tcx.sess, pat.span, E0529,
417 "expected an array or slice, found `{}`",
419 if let ty::Ref(_, ty, _) = expected_ty.sty {
421 ty::Array(..) | ty::Slice(..) => {
422 err.help("the semantics of slice patterns changed \
423 recently; see issue #23121");
429 err.span_label( pat.span,
430 format!("pattern cannot match with input type `{}`", expected_ty)
433 (tcx.types.err, tcx.types.err)
438 self.check_pat_walk(&elt, inner_ty, def_bm, true);
440 if let Some(ref slice) = *slice {
441 self.check_pat_walk(&slice, slice_ty, def_bm, true);
444 self.check_pat_walk(&elt, inner_ty, def_bm, true);
450 self.write_ty(pat.hir_id, ty);
452 // (*) In most of the cases above (literals and constants being
453 // the exception), we relate types using strict equality, even
454 // though subtyping would be sufficient. There are a few reasons
455 // for this, some of which are fairly subtle and which cost me
456 // (nmatsakis) an hour or two debugging to remember, so I thought
457 // I'd write them down this time.
459 // 1. There is no loss of expressiveness here, though it does
460 // cause some inconvenience. What we are saying is that the type
461 // of `x` becomes *exactly* what is expected. This can cause unnecessary
462 // errors in some cases, such as this one:
465 // fn foo<'x>(x: &'x int) {
472 // The reason we might get an error is that `z` might be
473 // assigned a type like `&'x int`, and then we would have
474 // a problem when we try to assign `&a` to `z`, because
475 // the lifetime of `&a` (i.e., the enclosing block) is
476 // shorter than `'x`.
478 // HOWEVER, this code works fine. The reason is that the
479 // expected type here is whatever type the user wrote, not
480 // the initializer's type. In this case the user wrote
481 // nothing, so we are going to create a type variable `Z`.
482 // Then we will assign the type of the initializer (`&'x
483 // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
484 // will instantiate `Z` as a type `&'0 int` where `'0` is
485 // a fresh region variable, with the constraint that `'x :
486 // '0`. So basically we're all set.
488 // Note that there are two tests to check that this remains true
489 // (`regions-reassign-{match,let}-bound-pointer.rs`).
491 // 2. Things go horribly wrong if we use subtype. The reason for
492 // THIS is a fairly subtle case involving bound regions. See the
493 // `givens` field in `region_constraints`, as well as the test
494 // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
495 // for details. Short version is that we must sometimes detect
496 // relationships between specific region variables and regions
497 // bound in a closure signature, and that detection gets thrown
498 // off when we substitute fresh region variables here to enable
502 pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
503 if let PatKind::Binding(..) = inner.node {
504 if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) {
505 if let ty::Dynamic(..) = mt.ty.sty {
506 // This is "x = SomeTrait" being reduced from
507 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
508 let type_str = self.ty_to_string(expected);
509 let mut err = struct_span_err!(
513 "type `{}` cannot be dereferenced",
516 err.span_label(span, format!("type `{}` cannot be dereferenced", type_str));
517 if self.tcx.sess.teach(&err.get_code().unwrap()) {
519 This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \
520 pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \
521 this type has no compile-time size. Therefore, all accesses to trait types must be through \
522 pointers. If you encounter this error you should try to avoid dereferencing the pointer.
524 You can read more about trait objects in the Trait Objects section of the Reference: \
525 https://doc.rust-lang.org/reference/types.html#trait-objects");
535 pub fn check_match(&self,
536 expr: &'gcx hir::Expr,
537 discrim: &'gcx hir::Expr,
538 arms: &'gcx [hir::Arm],
539 expected: Expectation<'tcx>,
540 match_src: hir::MatchSource) -> Ty<'tcx> {
543 // Not entirely obvious: if matches may create ref bindings, we want to
544 // use the *precise* type of the discriminant, *not* some supertype, as
545 // the "discriminant type" (issue #23116).
547 // arielb1 [writes here in this comment thread][c] that there
548 // is certainly *some* potential danger, e.g. for an example
551 // [c]: https://github.com/rust-lang/rust/pull/43399#discussion_r130223956
554 // let Foo(x) = f()[0];
557 // Then if the pattern matches by reference, we want to match
558 // `f()[0]` as a lexpr, so we can't allow it to be
559 // coerced. But if the pattern matches by value, `f()[0]` is
560 // still syntactically a lexpr, but we *do* want to allow
563 // However, *likely* we are ok with allowing coercions to
564 // happen if there are no explicit ref mut patterns - all
565 // implicit ref mut patterns must occur behind a reference, so
566 // they will have the "correct" variance and lifetime.
568 // This does mean that the following pattern would be legal:
573 // impl Deref for Foo {
574 // type Target = Bar;
575 // fn deref(&self) -> &Bar { &self.0 }
577 // impl DerefMut for Foo {
578 // fn deref_mut(&mut self) -> &mut Bar { &mut self.0 }
580 // fn foo(x: &mut Foo) {
582 // let Bar(z): &mut Bar = x;
585 // assert_eq!(foo.0.0, 42);
589 // FIXME(tschottdorf): don't call contains_explicit_ref_binding, which
590 // is problematic as the HIR is being scraped, but ref bindings may be
591 // implicit after #42640. We need to make sure that pat_adjustments
592 // (once introduced) is populated by the time we get here.
595 let contains_ref_bindings = arms.iter()
596 .filter_map(|a| a.contains_explicit_ref_binding())
597 .max_by_key(|m| match *m {
598 hir::MutMutable => 1,
599 hir::MutImmutable => 0,
602 if let Some(m) = contains_ref_bindings {
603 discrim_ty = self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m));
605 // ...but otherwise we want to use any supertype of the
606 // discriminant. This is sort of a workaround, see note (*) in
607 // `check_pat` for some details.
608 discrim_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(discrim.span));
609 self.check_expr_has_type_or_error(discrim, discrim_ty);
612 // If there are no arms, that is a diverging match; a special case.
614 self.diverges.set(self.diverges.get() | Diverges::Always);
615 return tcx.types.never;
618 if self.diverges.get().always() {
620 self.warn_if_unreachable(arm.body.id, arm.body.span, "arm");
624 // Otherwise, we have to union together the types that the
625 // arms produce and so forth.
626 let discrim_diverges = self.diverges.get();
627 self.diverges.set(Diverges::Maybe);
629 // rust-lang/rust#55810: Typecheck patterns first (via eager
630 // collection into `Vec`), so we get types for all bindings.
631 let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| {
632 let mut all_pats_diverge = Diverges::WarnedAlways;
634 self.diverges.set(Diverges::Maybe);
635 self.check_pat_walk(&p, discrim_ty,
636 ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), true);
637 all_pats_diverge &= self.diverges.get();
640 // As discussed with @eddyb, this is for disabling unreachable_code
641 // warnings on patterns (they're now subsumed by unreachable_patterns
643 match all_pats_diverge {
644 Diverges::Maybe => Diverges::Maybe,
645 Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
649 // Now typecheck the blocks.
651 // The result of the match is the common supertype of all the
652 // arms. Start out the value as bottom, since it's the, well,
653 // bottom the type lattice, and we'll be moving up the lattice as
654 // we process each arm. (Note that any match with 0 arms is matching
655 // on any empty type and is therefore unreachable; should the flow
656 // of execution reach it, we will panic, so bottom is an appropriate
657 // type in that case)
658 let mut all_arms_diverge = Diverges::WarnedAlways;
660 let expected = expected.adjust_for_branches(self);
663 let coerce_first = match expected {
664 // We don't coerce to `()` so that if the match expression is a
665 // statement it's branches can have any consistent type. That allows
666 // us to give better error messages (pointing to a usually better
667 // arm for inconsistent arms or to the whole match when a `()` type
669 Expectation::ExpectHasType(ety) if ety != self.tcx.mk_unit() => ety,
670 _ => self.next_ty_var(TypeVariableOrigin::MiscVariable(expr.span)),
672 CoerceMany::with_coercion_sites(coerce_first, arms)
675 for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
676 if let Some(ref g) = arm.guard {
677 self.diverges.set(pats_diverge);
679 hir::Guard::If(e) => self.check_expr_has_type_or_error(e, tcx.types.bool),
683 self.diverges.set(pats_diverge);
684 let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
685 all_arms_diverge &= self.diverges.get();
687 // Handle the fallback arm of a desugared if-let like a missing else.
688 let is_if_let_fallback = match match_src {
689 hir::MatchSource::IfLetDesugar { contains_else_clause: false } => {
690 i == arms.len() - 1 && arm_ty.is_unit()
695 if is_if_let_fallback {
696 let cause = self.cause(expr.span, ObligationCauseCode::IfExpressionWithNoElse);
697 assert!(arm_ty.is_unit());
698 coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
700 let cause = self.cause(expr.span, ObligationCauseCode::MatchExpressionArm {
701 arm_span: arm.body.span,
704 coercion.coerce(self, &cause, &arm.body, arm_ty);
708 // We won't diverge unless the discriminant or all arms diverge.
709 self.diverges.set(discrim_diverges | all_arms_diverge);
711 coercion.complete(self)
714 fn check_pat_struct(&self,
717 fields: &'gcx [Spanned<hir::FieldPat>],
720 def_bm: ty::BindingMode) -> Ty<'tcx>
722 // Resolve the path and check the definition for errors.
723 let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.id) {
726 for field in fields {
727 self.check_pat_walk(&field.node.pat, self.tcx.types.err, def_bm, true);
729 return self.tcx.types.err;
732 // Type check the path.
733 self.demand_eqtype(pat.span, expected, pat_ty);
735 // Type check subpatterns.
736 if self.check_struct_pat_fields(pat_ty, pat.id, pat.span, variant, fields, etc, def_bm) {
743 fn check_pat_path(&self,
746 expected: Ty<'tcx>) -> Ty<'tcx>
749 let report_unexpected_def = |def: Def| {
750 span_err!(tcx.sess, pat.span, E0533,
751 "expected unit struct/variant or constant, found {} `{}`",
753 hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false)));
756 // Resolve the path and check the definition for errors.
757 let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
760 self.set_tainted_by_errors();
761 return tcx.types.err;
764 report_unexpected_def(def);
765 return tcx.types.err;
767 Def::VariantCtor(_, CtorKind::Const) |
768 Def::StructCtor(_, CtorKind::Const) |
770 Def::Const(..) | Def::AssociatedConst(..) => {} // OK
771 _ => bug!("unexpected pattern definition: {:?}", def)
774 // Type check the path.
775 let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id).0;
776 self.demand_suptype(pat.span, expected, pat_ty);
780 fn check_pat_tuple_struct(&self,
783 subpats: &'gcx [P<hir::Pat>],
784 ddpos: Option<usize>,
786 def_bm: ty::BindingMode) -> Ty<'tcx>
791 self.check_pat_walk(&pat, tcx.types.err, def_bm, true);
794 let report_unexpected_def = |def: Def| {
795 let msg = format!("expected tuple struct/variant, found {} `{}`",
797 hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false)));
798 struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg)
799 .span_label(pat.span, "not a tuple variant or struct").emit();
803 // Resolve the path and check the definition for errors.
804 let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
806 self.set_tainted_by_errors();
808 return self.tcx.types.err;
811 // Type check the path.
812 let (pat_ty, def) = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
814 report_unexpected_def(def);
815 return self.tcx.types.err;
818 let variant = match def {
820 self.set_tainted_by_errors();
822 return tcx.types.err;
824 Def::AssociatedConst(..) | Def::Method(..) => {
825 report_unexpected_def(def);
826 return tcx.types.err;
828 Def::VariantCtor(_, CtorKind::Fn) |
829 Def::StructCtor(_, CtorKind::Fn) => {
830 tcx.expect_variant_def(def)
832 _ => bug!("unexpected pattern definition: {:?}", def)
835 // Replace constructor type with constructed type for tuple struct patterns.
836 let pat_ty = pat_ty.fn_sig(tcx).output();
837 let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
839 self.demand_eqtype(pat.span, expected, pat_ty);
841 // Type check subpatterns.
842 if subpats.len() == variant.fields.len() ||
843 subpats.len() < variant.fields.len() && ddpos.is_some() {
844 let substs = match pat_ty.sty {
845 ty::Adt(_, substs) => substs,
846 ref ty => bug!("unexpected pattern type {:?}", ty),
848 for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
849 let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
850 self.check_pat_walk(&subpat, field_ty, def_bm, true);
852 self.tcx.check_stability(variant.fields[i].did, Some(pat.id), subpat.span);
855 let subpats_ending = if subpats.len() == 1 { "" } else { "s" };
856 let fields_ending = if variant.fields.len() == 1 { "" } else { "s" };
857 struct_span_err!(tcx.sess, pat.span, E0023,
858 "this pattern has {} field{}, but the corresponding {} has {} field{}",
859 subpats.len(), subpats_ending, def.kind_name(),
860 variant.fields.len(), fields_ending)
861 .span_label(pat.span, format!("expected {} field{}, found {}",
862 variant.fields.len(), fields_ending, subpats.len()))
865 return tcx.types.err;
870 fn check_struct_pat_fields(&self,
874 variant: &'tcx ty::VariantDef,
875 fields: &'gcx [Spanned<hir::FieldPat>],
877 def_bm: ty::BindingMode) -> bool {
880 let (substs, adt) = match adt_ty.sty {
881 ty::Adt(adt, substs) => (substs, adt),
882 _ => span_bug!(span, "struct pattern is not an ADT")
884 let kind_name = adt.variant_descr();
886 // Index the struct fields' types.
887 let field_map = variant.fields
890 .map(|(i, field)| (field.ident.modern(), (i, field)))
891 .collect::<FxHashMap<_, _>>();
893 // Keep track of which fields have already appeared in the pattern.
894 let mut used_fields = FxHashMap::default();
895 let mut no_field_errors = true;
897 let mut inexistent_fields = vec![];
898 // Typecheck each field.
899 for &Spanned { node: ref field, span } in fields {
900 let ident = tcx.adjust_ident(field.ident, variant.did, self.body_id).0;
901 let field_ty = match used_fields.entry(ident) {
902 Occupied(occupied) => {
903 struct_span_err!(tcx.sess, span, E0025,
904 "field `{}` bound multiple times \
908 format!("multiple uses of `{}` in pattern", field.ident))
909 .span_label(*occupied.get(), format!("first use of `{}`", field.ident))
911 no_field_errors = false;
916 field_map.get(&ident)
918 self.write_field_index(field.id, *i);
919 self.tcx.check_stability(f.did, Some(pat_id), span);
920 self.field_ty(span, f, substs)
923 inexistent_fields.push((span, field.ident));
924 no_field_errors = false;
930 self.check_pat_walk(&field.pat, field_ty, def_bm, true);
932 let mut unmentioned_fields = variant.fields
934 .map(|field| field.ident.modern())
935 .filter(|ident| !used_fields.contains_key(&ident))
936 .collect::<Vec<_>>();
937 if inexistent_fields.len() > 0 {
938 let (field_names, t, plural) = if inexistent_fields.len() == 1 {
939 (format!("a field named `{}`", inexistent_fields[0].1), "this", "")
941 (format!("fields named {}",
942 inexistent_fields.iter()
943 .map(|(_, name)| format!("`{}`", name))
944 .collect::<Vec<String>>()
945 .join(", ")), "these", "s")
947 let spans = inexistent_fields.iter().map(|(span, _)| *span).collect::<Vec<_>>();
948 let mut err = struct_span_err!(tcx.sess,
951 "{} `{}` does not have {}",
953 tcx.item_path_str(variant.did),
955 if let Some((span, ident)) = inexistent_fields.last() {
956 err.span_label(*span,
957 format!("{} `{}` does not have {} field{}",
959 tcx.item_path_str(variant.did),
963 let input = unmentioned_fields.iter().map(|field| &field.name);
965 find_best_match_for_name(input, &ident.name.as_str(), None);
966 if let Some(suggested_name) = suggested_name {
967 err.span_suggestion(*span, "did you mean", suggested_name.to_string());
968 // we don't want to throw `E0027` in case we have thrown `E0026` for them
969 unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str());
973 if tcx.sess.teach(&err.get_code().unwrap()) {
975 "This error indicates that a struct pattern attempted to \
976 extract a non-existent field from a struct. Struct fields \
977 are identified by the name used before the colon : so struct \
978 patterns should resemble the declaration of the struct type \
980 If you are using shorthand field patterns but want to refer \
981 to the struct field by a different name, you should rename \
988 // Require `..` if struct has non_exhaustive attribute.
989 if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
990 span_err!(tcx.sess, span, E0638,
991 "`..` required with {} marked as non-exhaustive",
995 // Report an error if incorrect number of the fields were specified.
996 if kind_name == "union" {
997 if fields.len() != 1 {
998 tcx.sess.span_err(span, "union patterns should have exactly one field");
1001 tcx.sess.span_err(span, "`..` cannot be used in union patterns");
1004 if unmentioned_fields.len() > 0 {
1005 let field_names = if unmentioned_fields.len() == 1 {
1006 format!("field `{}`", unmentioned_fields[0])
1008 format!("fields {}",
1009 unmentioned_fields.iter()
1010 .map(|name| format!("`{}`", name))
1011 .collect::<Vec<String>>()
1014 let mut diag = struct_span_err!(tcx.sess, span, E0027,
1015 "pattern does not mention {}",
1017 diag.span_label(span, format!("missing {}", field_names));
1018 if variant.ctor_kind == CtorKind::Fn {
1019 diag.note("trying to match a tuple variant with a struct variant pattern");
1021 if tcx.sess.teach(&diag.get_code().unwrap()) {
1023 "This error indicates that a pattern for a struct fails to specify a \
1024 sub-pattern for every one of the struct's fields. Ensure that each field \
1025 from the struct's definition is mentioned in the pattern, or use `..` to \
1026 ignore unwanted fields."