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::codemap::Spanned;
29 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
30 /// The `is_arg` argument indicates whether this pattern is the
31 /// *outermost* pattern in an argument (e.g., in `fn foo(&x:
32 /// &u32)`, it is true for the `&x` pattern but not `x`). This is
33 /// used to tailor error reporting.
34 pub fn check_pat_walk(
37 mut expected: Ty<'tcx>,
38 mut def_bm: ty::BindingMode,
43 debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?},is_arg={})",
44 pat, expected, def_bm, is_arg);
46 let is_non_ref_pat = match pat.node {
48 PatKind::TupleStruct(..) |
52 PatKind::Slice(..) => true,
53 PatKind::Lit(ref lt) => {
54 let ty = self.check_expr(lt);
56 ty::TypeVariants::TyRef(..) => false,
60 PatKind::Path(ref qpath) => {
61 let (def, _, _) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
63 Def::Const(..) | Def::AssociatedConst(..) => false,
68 PatKind::Binding(..) |
69 PatKind::Ref(..) => false,
72 debug!("pattern is non reference pattern");
73 let mut exp_ty = self.resolve_type_vars_with_obligations(&expected);
75 // Peel off as many `&` or `&mut` from the discriminant as possible. For example,
76 // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
77 // the `Some(5)` which is not of type TyRef.
79 // For each ampersand peeled off, update the binding mode and push the original
80 // type into the adjustments vector.
82 // See the examples in `run-pass/match-defbm*.rs`.
83 let mut pat_adjustments = vec![];
85 debug!("inspecting {:?} with type {:?}", exp_ty, exp_ty.sty);
87 ty::TypeVariants::TyRef(_, ty::TypeAndMut{
88 ty: inner_ty, mutbl: inner_mutability,
90 debug!("current discriminant is TyRef, inserting implicit deref");
91 // Preserve the reference type. We'll need it later during HAIR lowering.
92 pat_adjustments.push(exp_ty);
95 def_bm = match def_bm {
96 // If default binding mode is by value, make it `ref` or `ref mut`
97 // (depending on whether we observe `&` or `&mut`).
99 ty::BindByReference(inner_mutability),
101 // Once a `ref`, always a `ref`. This is because a `& &mut` can't mutate
102 // the underlying value.
103 ty::BindByReference(hir::Mutability::MutImmutable) =>
104 ty::BindByReference(hir::Mutability::MutImmutable),
106 // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref`
108 ty::BindByReference(hir::Mutability::MutMutable) =>
109 ty::BindByReference(inner_mutability),
115 if pat_adjustments.len() > 0 {
116 debug!("default binding mode is now {:?}", def_bm);
117 self.inh.tables.borrow_mut()
118 .pat_adjustments_mut()
119 .insert(pat.hir_id, pat_adjustments);
121 } else if let PatKind::Ref(..) = pat.node {
122 // When you encounter a `&pat` pattern, reset to "by
123 // value". This is so that `x` and `y` here are by value,
124 // as they appear to be:
127 // match &(&22, &44) {
133 def_bm = ty::BindByValue(hir::MutImmutable);
136 // Lose mutability now that we know binding mode and discriminant type.
138 let expected = expected;
140 let ty = match pat.node {
144 PatKind::Lit(ref lt) => {
145 // We've already computed the type above (when checking for a non-ref pat), so
146 // avoid computing it again.
147 let ty = self.node_ty(lt.hir_id);
149 // Byte string patterns behave the same way as array patterns
150 // They can denote both statically and dynamically sized byte arrays
152 if let hir::ExprLit(ref lt) = lt.node {
153 if let ast::LitKind::ByteStr(_) = lt.node {
154 let expected_ty = self.structurally_resolved_type(pat.span, expected);
155 if let ty::TyRef(_, mt) = expected_ty.sty {
156 if let ty::TySlice(_) = mt.ty.sty {
157 pat_ty = tcx.mk_imm_ref(tcx.types.re_static,
158 tcx.mk_slice(tcx.types.u8))
164 // somewhat surprising: in this case, the subtyping
165 // relation goes the opposite way as the other
166 // cases. Actually what we really want is not a subtyping
167 // relation at all but rather that there exists a LUB (so
168 // that they can be compared). However, in practice,
169 // constants are always scalars or strings. For scalars
170 // subtyping is irrelevant, and for strings `ty` is
171 // type is `&'static str`, so if we say that
173 // &'static str <: expected
175 // that's equivalent to there existing a LUB.
176 self.demand_suptype(pat.span, expected, pat_ty);
179 PatKind::Range(ref begin, ref end, _) => {
180 let lhs_ty = self.check_expr(begin);
181 let rhs_ty = self.check_expr(end);
183 // Check that both end-points are of numeric or char type.
184 let numeric_or_char = |ty: Ty| ty.is_numeric() || ty.is_char();
185 let lhs_compat = numeric_or_char(lhs_ty);
186 let rhs_compat = numeric_or_char(rhs_ty);
188 if !lhs_compat || !rhs_compat {
189 let span = if !lhs_compat && !rhs_compat {
191 } else if !lhs_compat {
197 let mut err = struct_span_err!(
201 "only char and numeric types are allowed in range patterns"
203 err.span_label(span, "ranges require char or numeric types");
204 err.note(&format!("start type: {}", self.ty_to_string(lhs_ty)));
205 err.note(&format!("end type: {}", self.ty_to_string(rhs_ty)));
206 if tcx.sess.teach(&err.get_code().unwrap()) {
208 "In a match expression, only numbers and characters can be matched \
209 against a range. This is because the compiler checks that the range \
210 is non-empty at compile-time, and is unable to evaluate arbitrary \
211 comparison functions. If you want to capture values of an orderable \
212 type between two end-points, you can use a guard."
219 // Now that we know the types can be unified we find the unified type and use
220 // it to type the entire expression.
221 let common_type = self.resolve_type_vars_if_possible(&lhs_ty);
223 // subtyping doesn't matter here, as the value is some kind of scalar
224 self.demand_eqtype(pat.span, expected, lhs_ty);
225 self.demand_eqtype(pat.span, expected, rhs_ty);
228 PatKind::Binding(ba, var_id, _, ref sub) => {
229 let bm = if ba == hir::BindingAnnotation::Unannotated {
232 ty::BindingMode::convert(ba)
237 .pat_binding_modes_mut()
238 .insert(pat.hir_id, bm);
239 let typ = self.local_ty(pat.span, pat.id);
241 ty::BindByReference(mutbl) => {
242 // if the binding is like
243 // ref x | ref const x | ref mut x
244 // then `x` is assigned a value of type `&M T` where M is the mutability
245 // and T is the expected type.
246 let region_var = self.next_region_var(infer::PatternRegion(pat.span));
247 let mt = ty::TypeAndMut { ty: expected, mutbl: mutbl };
248 let region_ty = tcx.mk_ref(region_var, mt);
250 // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
251 // required. However, we use equality, which is stronger. See (*) for
253 self.demand_eqtype(pat.span, region_ty, typ);
255 // otherwise the type of x is the expected type T
256 ty::BindByValue(_) => {
257 // As above, `T <: typeof(x)` is required but we
258 // use equality, see (*) below.
259 self.demand_eqtype(pat.span, expected, typ);
263 // if there are multiple arms, make sure they all agree on
264 // what the type of the binding `x` ought to be
265 if var_id != pat.id {
266 let vt = self.local_ty(pat.span, var_id);
267 self.demand_eqtype(pat.span, vt, typ);
270 if let Some(ref p) = *sub {
271 self.check_pat_walk(&p, expected, def_bm, true);
276 PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
277 self.check_pat_tuple_struct(pat, qpath, &subpats, ddpos, expected, def_bm)
279 PatKind::Path(ref qpath) => {
280 self.check_pat_path(pat, qpath, expected)
282 PatKind::Struct(ref qpath, ref fields, etc) => {
283 self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm)
285 PatKind::Tuple(ref elements, ddpos) => {
286 let mut expected_len = elements.len();
288 // Require known type only when `..` is present
289 if let ty::TyTuple(ref tys) =
290 self.structurally_resolved_type(pat.span, expected).sty {
291 expected_len = tys.len();
294 let max_len = cmp::max(expected_len, elements.len());
296 let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(
297 // FIXME: MiscVariable for now, obtaining the span and name information
298 // from all tuple elements isn't trivial.
299 ty::UniverseIndex::ROOT,
300 TypeVariableOrigin::TypeInference(pat.span)));
301 let element_tys = tcx.mk_type_list(element_tys_iter);
302 let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys));
303 self.demand_eqtype(pat.span, expected, pat_ty);
304 for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
305 self.check_pat_walk(elem, &element_tys[i], def_bm, true);
309 PatKind::Box(ref inner) => {
310 let inner_ty = self.next_ty_var(ty::UniverseIndex::ROOT,
311 TypeVariableOrigin::TypeInference(inner.span));
312 let uniq_ty = tcx.mk_box(inner_ty);
314 if self.check_dereferencable(pat.span, expected, &inner) {
315 // Here, `demand::subtype` is good enough, but I don't
316 // think any errors can be introduced by using
318 self.demand_eqtype(pat.span, expected, uniq_ty);
319 self.check_pat_walk(&inner, inner_ty, def_bm, true);
322 self.check_pat_walk(&inner, tcx.types.err, def_bm, true);
326 PatKind::Ref(ref inner, mutbl) => {
327 let expected = self.shallow_resolve(expected);
328 if self.check_dereferencable(pat.span, expected, &inner) {
329 // `demand::subtype` would be good enough, but using
330 // `eqtype` turns out to be equally general. See (*)
331 // below for details.
333 // Take region, inner-type from expected type if we
334 // can, to avoid creating needless variables. This
335 // also helps with the bad interactions of the given
336 // hack detailed in (*) below.
337 debug!("check_pat_walk: expected={:?}", expected);
338 let (rptr_ty, inner_ty) = match expected.sty {
339 ty::TyRef(_, mt) if mt.mutbl == mutbl => {
343 let inner_ty = self.next_ty_var(
344 ty::UniverseIndex::ROOT,
345 TypeVariableOrigin::TypeInference(inner.span));
346 let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
347 let region = self.next_region_var(infer::PatternRegion(pat.span));
348 let rptr_ty = tcx.mk_ref(region, mt);
349 debug!("check_pat_walk: demanding {:?} = {:?}", expected, rptr_ty);
350 let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
352 // Look for a case like `fn foo(&foo: u32)` and suggest
353 // `fn foo(foo: &u32)`
354 if let Some(mut err) = err {
356 if let PatKind::Binding(..) = inner.node {
357 if let Ok(snippet) = tcx.sess.codemap()
358 .span_to_snippet(pat.span)
360 err.help(&format!("did you mean `{}: &{}`?",
372 self.check_pat_walk(&inner, inner_ty, def_bm, true);
375 self.check_pat_walk(&inner, tcx.types.err, def_bm, true);
379 PatKind::Slice(ref before, ref slice, ref after) => {
380 let expected_ty = self.structurally_resolved_type(pat.span, expected);
381 let (inner_ty, slice_ty) = match expected_ty.sty {
382 ty::TyArray(inner_ty, size) => {
383 let size = size.val.unwrap_u64();
384 let min_len = before.len() as u64 + after.len() as u64;
388 tcx.sess, pat.span, E0527,
389 "pattern requires {} elements but array has {}",
391 .span_label(pat.span, format!("expected {} elements",size))
394 (inner_ty, tcx.types.err)
395 } else if let Some(rest) = size.checked_sub(min_len) {
396 (inner_ty, tcx.mk_array(inner_ty, rest))
398 struct_span_err!(tcx.sess, pat.span, E0528,
399 "pattern requires at least {} elements but array has {}",
401 .span_label(pat.span,
402 format!("pattern cannot match array of {} elements", size))
404 (inner_ty, tcx.types.err)
407 ty::TySlice(inner_ty) => (inner_ty, expected_ty),
409 if !expected_ty.references_error() {
410 let mut err = struct_span_err!(
411 tcx.sess, pat.span, E0529,
412 "expected an array or slice, found `{}`",
414 if let ty::TyRef(_, ty::TypeAndMut { mutbl: _, ty }) = expected_ty.sty {
416 ty::TyArray(..) | ty::TySlice(..) => {
417 err.help("the semantics of slice patterns changed \
418 recently; see issue #23121");
424 err.span_label( pat.span,
425 format!("pattern cannot match with input type `{}`", expected_ty)
428 (tcx.types.err, tcx.types.err)
433 self.check_pat_walk(&elt, inner_ty, def_bm, true);
435 if let Some(ref slice) = *slice {
436 self.check_pat_walk(&slice, slice_ty, def_bm, true);
439 self.check_pat_walk(&elt, inner_ty, def_bm, true);
445 self.write_ty(pat.hir_id, ty);
447 // (*) In most of the cases above (literals and constants being
448 // the exception), we relate types using strict equality, even
449 // though subtyping would be sufficient. There are a few reasons
450 // for this, some of which are fairly subtle and which cost me
451 // (nmatsakis) an hour or two debugging to remember, so I thought
452 // I'd write them down this time.
454 // 1. There is no loss of expressiveness here, though it does
455 // cause some inconvenience. What we are saying is that the type
456 // of `x` becomes *exactly* what is expected. This can cause unnecessary
457 // errors in some cases, such as this one:
460 // fn foo<'x>(x: &'x int) {
467 // The reason we might get an error is that `z` might be
468 // assigned a type like `&'x int`, and then we would have
469 // a problem when we try to assign `&a` to `z`, because
470 // the lifetime of `&a` (i.e., the enclosing block) is
471 // shorter than `'x`.
473 // HOWEVER, this code works fine. The reason is that the
474 // expected type here is whatever type the user wrote, not
475 // the initializer's type. In this case the user wrote
476 // nothing, so we are going to create a type variable `Z`.
477 // Then we will assign the type of the initializer (`&'x
478 // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
479 // will instantiate `Z` as a type `&'0 int` where `'0` is
480 // a fresh region variable, with the constraint that `'x :
481 // '0`. So basically we're all set.
483 // Note that there are two tests to check that this remains true
484 // (`regions-reassign-{match,let}-bound-pointer.rs`).
486 // 2. Things go horribly wrong if we use subtype. The reason for
487 // THIS is a fairly subtle case involving bound regions. See the
488 // `givens` field in `region_constraints`, as well as the test
489 // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
490 // for details. Short version is that we must sometimes detect
491 // relationships between specific region variables and regions
492 // bound in a closure signature, and that detection gets thrown
493 // off when we substitute fresh region variables here to enable
497 pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
498 if let PatKind::Binding(..) = inner.node {
499 if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) {
500 if let ty::TyDynamic(..) = mt.ty.sty {
501 // This is "x = SomeTrait" being reduced from
502 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
503 let type_str = self.ty_to_string(expected);
504 let mut err = struct_span_err!(
508 "type `{}` cannot be dereferenced",
511 err.span_label(span, format!("type `{}` cannot be dereferenced", type_str));
512 if self.tcx.sess.teach(&err.get_code().unwrap()) {
514 This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \
515 pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \
516 this type has no compile-time size. Therefore, all accesses to trait types must be through \
517 pointers. If you encounter this error you should try to avoid dereferencing the pointer.
519 You can read more about trait objects in the Trait Objects section of the Reference: \
520 https://doc.rust-lang.org/reference/types.html#trait-objects");
530 pub fn check_match(&self,
531 expr: &'gcx hir::Expr,
532 discrim: &'gcx hir::Expr,
533 arms: &'gcx [hir::Arm],
534 expected: Expectation<'tcx>,
535 match_src: hir::MatchSource) -> Ty<'tcx> {
538 // Not entirely obvious: if matches may create ref bindings, we want to
539 // use the *precise* type of the discriminant, *not* some supertype, as
540 // the "discriminant type" (issue #23116).
542 // arielb1 [writes here in this comment thread][c] that there
543 // is certainly *some* potential danger, e.g. for an example
546 // [c]: https://github.com/rust-lang/rust/pull/43399#discussion_r130223956
549 // let Foo(x) = f()[0];
552 // Then if the pattern matches by reference, we want to match
553 // `f()[0]` as a lexpr, so we can't allow it to be
554 // coerced. But if the pattern matches by value, `f()[0]` is
555 // still syntactically a lexpr, but we *do* want to allow
558 // However, *likely* we are ok with allowing coercions to
559 // happen if there are no explicit ref mut patterns - all
560 // implicit ref mut patterns must occur behind a reference, so
561 // they will have the "correct" variance and lifetime.
563 // This does mean that the following pattern would be legal:
568 // impl Deref for Foo {
569 // type Target = Bar;
570 // fn deref(&self) -> &Bar { &self.0 }
572 // impl DerefMut for Foo {
573 // fn deref_mut(&mut self) -> &mut Bar { &mut self.0 }
575 // fn foo(x: &mut Foo) {
577 // let Bar(z): &mut Bar = x;
580 // assert_eq!(foo.0.0, 42);
584 // FIXME(tschottdorf): don't call contains_explicit_ref_binding, which
585 // is problematic as the HIR is being scraped, but ref bindings may be
586 // implicit after #42640. We need to make sure that pat_adjustments
587 // (once introduced) is populated by the time we get here.
590 let contains_ref_bindings = arms.iter()
591 .filter_map(|a| a.contains_explicit_ref_binding())
592 .max_by_key(|m| match *m {
593 hir::MutMutable => 1,
594 hir::MutImmutable => 0,
597 if let Some(m) = contains_ref_bindings {
598 discrim_ty = self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m));
600 // ...but otherwise we want to use any supertype of the
601 // discriminant. This is sort of a workaround, see note (*) in
602 // `check_pat` for some details.
603 discrim_ty = self.next_ty_var(ty::UniverseIndex::ROOT,
604 TypeVariableOrigin::TypeInference(discrim.span));
605 self.check_expr_has_type_or_error(discrim, discrim_ty);
608 // If the discriminant diverges, the match is pointless (e.g.,
609 // `match (return) { }`).
610 self.warn_if_unreachable(expr.id, expr.span, "expression");
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 // Otherwise, we have to union together the types that the
619 // arms produce and so forth.
621 let discrim_diverges = self.diverges.get();
622 self.diverges.set(Diverges::Maybe);
624 // Typecheck the patterns first, so that we get types for all the
626 let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| {
627 let mut all_pats_diverge = Diverges::WarnedAlways;
629 self.diverges.set(Diverges::Maybe);
630 self.check_pat_walk(&p, discrim_ty,
631 ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), true);
632 all_pats_diverge &= self.diverges.get();
635 // As discussed with @eddyb, this is for disabling unreachable_code
636 // warnings on patterns (they're now subsumed by unreachable_patterns
638 match all_pats_diverge {
639 Diverges::Maybe => Diverges::Maybe,
640 Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
644 // Now typecheck the blocks.
646 // The result of the match is the common supertype of all the
647 // arms. Start out the value as bottom, since it's the, well,
648 // bottom the type lattice, and we'll be moving up the lattice as
649 // we process each arm. (Note that any match with 0 arms is matching
650 // on any empty type and is therefore unreachable; should the flow
651 // of execution reach it, we will panic, so bottom is an appropriate
652 // type in that case)
653 let mut all_arms_diverge = Diverges::WarnedAlways;
655 let expected = expected.adjust_for_branches(self);
658 let coerce_first = match expected {
659 // We don't coerce to `()` so that if the match expression is a
660 // statement it's branches can have any consistent type. That allows
661 // us to give better error messages (pointing to a usually better
662 // arm for inconsistent arms or to the whole match when a `()` type
664 Expectation::ExpectHasType(ety) if ety != self.tcx.mk_nil() => ety,
665 _ => self.next_ty_var(ty::UniverseIndex::ROOT,
666 TypeVariableOrigin::MiscVariable(expr.span)),
668 CoerceMany::with_coercion_sites(coerce_first, arms)
671 for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
672 if let Some(ref e) = arm.guard {
673 self.diverges.set(pats_diverge);
674 self.check_expr_has_type_or_error(e, tcx.types.bool);
677 self.diverges.set(pats_diverge);
678 let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
679 all_arms_diverge &= self.diverges.get();
681 // Handle the fallback arm of a desugared if-let like a missing else.
682 let is_if_let_fallback = match match_src {
683 hir::MatchSource::IfLetDesugar { contains_else_clause: false } => {
684 i == arms.len() - 1 && arm_ty.is_nil()
689 if is_if_let_fallback {
690 let cause = self.cause(expr.span, ObligationCauseCode::IfExpressionWithNoElse);
691 assert!(arm_ty.is_nil());
692 coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
694 let cause = self.cause(expr.span, ObligationCauseCode::MatchExpressionArm {
695 arm_span: arm.body.span,
698 coercion.coerce(self, &cause, &arm.body, arm_ty, self.diverges.get());
702 // We won't diverge unless the discriminant or all arms diverge.
703 self.diverges.set(discrim_diverges | all_arms_diverge);
705 coercion.complete(self)
708 fn check_pat_struct(&self,
711 fields: &'gcx [Spanned<hir::FieldPat>],
714 def_bm: ty::BindingMode) -> Ty<'tcx>
716 // Resolve the path and check the definition for errors.
717 let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.id) {
720 for field in fields {
721 self.check_pat_walk(&field.node.pat, self.tcx.types.err, def_bm, true);
723 return self.tcx.types.err;
726 // Type check the path.
727 self.demand_eqtype(pat.span, expected, pat_ty);
729 // Type check subpatterns.
730 self.check_struct_pat_fields(pat_ty, pat.id, pat.span, variant, fields, etc, def_bm);
734 fn check_pat_path(&self,
737 expected: Ty<'tcx>) -> Ty<'tcx>
740 let report_unexpected_def = |def: Def| {
741 span_err!(tcx.sess, pat.span, E0533,
742 "expected unit struct/variant or constant, found {} `{}`",
744 hir::print::to_string(&tcx.hir, |s| s.print_qpath(qpath, false)));
747 // Resolve the path and check the definition for errors.
748 let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
751 self.set_tainted_by_errors();
752 return tcx.types.err;
755 report_unexpected_def(def);
756 return tcx.types.err;
758 Def::VariantCtor(_, CtorKind::Const) |
759 Def::StructCtor(_, CtorKind::Const) |
760 Def::Const(..) | Def::AssociatedConst(..) => {} // OK
761 _ => bug!("unexpected pattern definition: {:?}", def)
764 // Type check the path.
765 let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
766 self.demand_suptype(pat.span, expected, pat_ty);
770 fn check_pat_tuple_struct(&self,
773 subpats: &'gcx [P<hir::Pat>],
774 ddpos: Option<usize>,
776 def_bm: ty::BindingMode) -> Ty<'tcx>
781 self.check_pat_walk(&pat, tcx.types.err, def_bm, true);
784 let report_unexpected_def = |def: Def| {
785 let msg = format!("expected tuple struct/variant, found {} `{}`",
787 hir::print::to_string(&tcx.hir, |s| s.print_qpath(qpath, false)));
788 struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg)
789 .span_label(pat.span, "not a tuple variant or struct").emit();
793 // Resolve the path and check the definition for errors.
794 let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span);
795 let variant = match def {
797 self.set_tainted_by_errors();
799 return tcx.types.err;
801 Def::AssociatedConst(..) | Def::Method(..) => {
802 report_unexpected_def(def);
803 return tcx.types.err;
805 Def::VariantCtor(_, CtorKind::Fn) |
806 Def::StructCtor(_, CtorKind::Fn) => {
807 tcx.expect_variant_def(def)
809 _ => bug!("unexpected pattern definition: {:?}", def)
812 // Type check the path.
813 let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
814 // Replace constructor type with constructed type for tuple struct patterns.
815 let pat_ty = pat_ty.fn_sig(tcx).output();
816 let pat_ty = pat_ty.no_late_bound_regions().expect("expected fn type");
818 self.demand_eqtype(pat.span, expected, pat_ty);
820 // Type check subpatterns.
821 if subpats.len() == variant.fields.len() ||
822 subpats.len() < variant.fields.len() && ddpos.is_some() {
823 let substs = match pat_ty.sty {
824 ty::TyAdt(_, substs) => substs,
825 ref ty => bug!("unexpected pattern type {:?}", ty),
827 for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
828 let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
829 self.check_pat_walk(&subpat, field_ty, def_bm, true);
831 self.tcx.check_stability(variant.fields[i].did, Some(pat.id), subpat.span);
834 let subpats_ending = if subpats.len() == 1 { "" } else { "s" };
835 let fields_ending = if variant.fields.len() == 1 { "" } else { "s" };
836 struct_span_err!(tcx.sess, pat.span, E0023,
837 "this pattern has {} field{}, but the corresponding {} has {} field{}",
838 subpats.len(), subpats_ending, def.kind_name(),
839 variant.fields.len(), fields_ending)
840 .span_label(pat.span, format!("expected {} field{}, found {}",
841 variant.fields.len(), fields_ending, subpats.len()))
844 return tcx.types.err;
849 fn check_struct_pat_fields(&self,
853 variant: &'tcx ty::VariantDef,
854 fields: &'gcx [Spanned<hir::FieldPat>],
856 def_bm: ty::BindingMode) {
859 let (substs, adt) = match adt_ty.sty {
860 ty::TyAdt(adt, substs) => (substs, adt),
861 _ => span_bug!(span, "struct pattern is not an ADT")
863 let kind_name = adt.variant_descr();
865 // Index the struct fields' types.
866 let field_map = variant.fields
868 .map(|field| (field.name, field))
869 .collect::<FxHashMap<_, _>>();
871 // Keep track of which fields have already appeared in the pattern.
872 let mut used_fields = FxHashMap();
874 let mut inexistent_fields = vec![];
875 // Typecheck each field.
876 for &Spanned { node: ref field, span } in fields {
877 let field_ty = match used_fields.entry(field.name) {
878 Occupied(occupied) => {
879 struct_span_err!(tcx.sess, span, E0025,
880 "field `{}` bound multiple times \
884 format!("multiple uses of `{}` in pattern", field.name))
885 .span_label(*occupied.get(), format!("first use of `{}`", field.name))
891 field_map.get(&field.name)
893 self.tcx.check_stability(f.did, Some(pat_id), span);
895 self.field_ty(span, f, substs)
898 inexistent_fields.push((span, field.name));
904 self.check_pat_walk(&field.pat, field_ty, def_bm, true);
907 if inexistent_fields.len() > 0 {
908 let (field_names, t, plural) = if inexistent_fields.len() == 1 {
909 (format!("a field named `{}`", inexistent_fields[0].1), "this", "")
911 (format!("fields named {}",
912 inexistent_fields.iter()
913 .map(|(_, name)| format!("`{}`", name))
914 .collect::<Vec<String>>()
915 .join(", ")), "these", "s")
917 let spans = inexistent_fields.iter().map(|(span, _)| *span).collect::<Vec<_>>();
918 let mut err = struct_span_err!(tcx.sess,
921 "{} `{}` does not have {}",
923 tcx.item_path_str(variant.did),
925 if let Some((span, _)) = inexistent_fields.last() {
926 err.span_label(*span,
927 format!("{} `{}` does not have {} field{}",
929 tcx.item_path_str(variant.did),
933 if tcx.sess.teach(&err.get_code().unwrap()) {
935 "This error indicates that a struct pattern attempted to \
936 extract a non-existent field from a struct. Struct fields \
937 are identified by the name used before the colon : so struct \
938 patterns should resemble the declaration of the struct type \
940 If you are using shorthand field patterns but want to refer \
941 to the struct field by a different name, you should rename \
948 // Require `..` if struct has non_exhaustive attribute.
949 if adt.is_struct() && adt.is_non_exhaustive() && !adt.did.is_local() && !etc {
950 span_err!(tcx.sess, span, E0638,
951 "`..` required with {} marked as non-exhaustive",
955 // Report an error if incorrect number of the fields were specified.
956 if kind_name == "union" {
957 if fields.len() != 1 {
958 tcx.sess.span_err(span, "union patterns should have exactly one field");
961 tcx.sess.span_err(span, "`..` cannot be used in union patterns");
964 let unmentioned_fields = variant.fields
966 .map(|field| field.name)
967 .filter(|field| !used_fields.contains_key(&field))
968 .collect::<Vec<_>>();
969 if unmentioned_fields.len() > 0 {
970 let field_names = if unmentioned_fields.len() == 1 {
971 format!("field `{}`", unmentioned_fields[0])
974 unmentioned_fields.iter()
975 .map(|name| format!("`{}`", name))
976 .collect::<Vec<String>>()
979 let mut diag = struct_span_err!(tcx.sess, span, E0027,
980 "pattern does not mention {}",
982 diag.span_label(span, format!("missing {}", field_names));
983 if variant.ctor_kind == CtorKind::Fn {
984 diag.note("trying to match a tuple variant with a struct variant pattern");
986 if tcx.sess.teach(&diag.get_code().unwrap()) {
988 "This error indicates that a pattern for a struct fails to specify a \
989 sub-pattern for every one of the struct's fields. Ensure that each field \
990 from the struct's definition is mentioned in the pattern, or use `..` to \
991 ignore unwanted fields."