]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/hair/pattern/mod.rs
869aeeba418da5475b4cab7a3c1070b76a4da679
[rust.git] / src / librustc_mir / hair / pattern / mod.rs
1 //! Validation of patterns/matches.
2
3 mod _match;
4 mod check_match;
5 mod const_to_pat;
6
7 pub(crate) use self::check_match::check_match;
8
9 use crate::hair::constant::*;
10 use crate::hair::util::UserAnnotatedTyHelpers;
11
12 use rustc::hir::def::{CtorKind, CtorOf, DefKind, Res};
13 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
14 use rustc::hir::ptr::P;
15 use rustc::hir::{self, RangeEnd};
16 use rustc::mir::interpret::{get_slice_bytes, sign_extend, ConstValue, ErrorHandled};
17 use rustc::mir::UserTypeProjection;
18 use rustc::mir::{BorrowKind, Field, Mutability};
19 use rustc::ty::layout::VariantIdx;
20 use rustc::ty::subst::{GenericArg, SubstsRef};
21 use rustc::ty::{self, AdtDef, DefIdTree, Region, Ty, TyCtxt, UserType};
22 use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
23
24 use rustc_index::vec::Idx;
25
26 use std::cmp::Ordering;
27 use std::fmt;
28 use syntax::ast;
29 use syntax_pos::{Span, DUMMY_SP};
30
31 use rustc_error_codes::*;
32
33 #[derive(Clone, Debug)]
34 pub enum PatternError {
35     AssocConstInPattern(Span),
36     StaticInPattern(Span),
37     FloatBug,
38     NonConstPath(Span),
39 }
40
41 #[derive(Copy, Clone, Debug)]
42 pub enum BindingMode {
43     ByValue,
44     ByRef(BorrowKind),
45 }
46
47 #[derive(Clone, Debug)]
48 pub struct FieldPat<'tcx> {
49     pub field: Field,
50     pub pattern: Pat<'tcx>,
51 }
52
53 #[derive(Clone, Debug)]
54 pub struct Pat<'tcx> {
55     pub ty: Ty<'tcx>,
56     pub span: Span,
57     pub kind: Box<PatKind<'tcx>>,
58 }
59
60 impl<'tcx> Pat<'tcx> {
61     pub(crate) fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
62         Pat { ty, span: DUMMY_SP, kind: Box::new(PatKind::Wild) }
63     }
64 }
65
66 #[derive(Copy, Clone, Debug, PartialEq)]
67 pub struct PatTyProj<'tcx> {
68     pub user_ty: CanonicalUserType<'tcx>,
69 }
70
71 impl<'tcx> PatTyProj<'tcx> {
72     pub(crate) fn from_user_type(user_annotation: CanonicalUserType<'tcx>) -> Self {
73         Self { user_ty: user_annotation }
74     }
75
76     pub(crate) fn user_ty(
77         self,
78         annotations: &mut CanonicalUserTypeAnnotations<'tcx>,
79         inferred_ty: Ty<'tcx>,
80         span: Span,
81     ) -> UserTypeProjection {
82         UserTypeProjection {
83             base: annotations.push(CanonicalUserTypeAnnotation {
84                 span,
85                 user_ty: self.user_ty,
86                 inferred_ty,
87             }),
88             projs: Vec::new(),
89         }
90     }
91 }
92
93 #[derive(Copy, Clone, Debug, PartialEq)]
94 pub struct Ascription<'tcx> {
95     pub user_ty: PatTyProj<'tcx>,
96     /// Variance to use when relating the type `user_ty` to the **type of the value being
97     /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
98     /// have a type that is some subtype of the ascribed type.
99     ///
100     /// Note that this variance does not apply for any bindings within subpatterns. The type
101     /// assigned to those bindings must be exactly equal to the `user_ty` given here.
102     ///
103     /// The only place where this field is not `Covariant` is when matching constants, where
104     /// we currently use `Contravariant` -- this is because the constant type just needs to
105     /// be "comparable" to the type of the input value. So, for example:
106     ///
107     /// ```text
108     /// match x { "foo" => .. }
109     /// ```
110     ///
111     /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
112     /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
113     /// of the old type-check for now. See #57280 for details.
114     pub variance: ty::Variance,
115     pub user_ty_span: Span,
116 }
117
118 #[derive(Clone, Debug)]
119 pub enum PatKind<'tcx> {
120     Wild,
121
122     AscribeUserType {
123         ascription: Ascription<'tcx>,
124         subpattern: Pat<'tcx>,
125     },
126
127     /// `x`, `ref x`, `x @ P`, etc.
128     Binding {
129         mutability: Mutability,
130         name: ast::Name,
131         mode: BindingMode,
132         var: hir::HirId,
133         ty: Ty<'tcx>,
134         subpattern: Option<Pat<'tcx>>,
135     },
136
137     /// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
138     /// multiple variants.
139     Variant {
140         adt_def: &'tcx AdtDef,
141         substs: SubstsRef<'tcx>,
142         variant_index: VariantIdx,
143         subpatterns: Vec<FieldPat<'tcx>>,
144     },
145
146     /// `(...)`, `Foo(...)`, `Foo{...}`, or `Foo`, where `Foo` is a variant name from an ADT with
147     /// a single variant.
148     Leaf {
149         subpatterns: Vec<FieldPat<'tcx>>,
150     },
151
152     /// `box P`, `&P`, `&mut P`, etc.
153     Deref {
154         subpattern: Pat<'tcx>,
155     },
156
157     Constant {
158         value: &'tcx ty::Const<'tcx>,
159     },
160
161     Range(PatRange<'tcx>),
162
163     /// Matches against a slice, checking the length and extracting elements.
164     /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
165     /// e.g., `&[ref xs @ ..]`.
166     Slice {
167         prefix: Vec<Pat<'tcx>>,
168         slice: Option<Pat<'tcx>>,
169         suffix: Vec<Pat<'tcx>>,
170     },
171
172     /// Fixed match against an array; irrefutable.
173     Array {
174         prefix: Vec<Pat<'tcx>>,
175         slice: Option<Pat<'tcx>>,
176         suffix: Vec<Pat<'tcx>>,
177     },
178
179     /// An or-pattern, e.g. `p | q`.
180     /// Invariant: `pats.len() >= 2`.
181     Or {
182         pats: Vec<Pat<'tcx>>,
183     },
184 }
185
186 #[derive(Copy, Clone, Debug, PartialEq)]
187 pub struct PatRange<'tcx> {
188     pub lo: &'tcx ty::Const<'tcx>,
189     pub hi: &'tcx ty::Const<'tcx>,
190     pub end: RangeEnd,
191 }
192
193 impl<'tcx> fmt::Display for Pat<'tcx> {
194     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195         // Printing lists is a chore.
196         let mut first = true;
197         let mut start_or_continue = |s| {
198             if first {
199                 first = false;
200                 ""
201             } else {
202                 s
203             }
204         };
205         let mut start_or_comma = || start_or_continue(", ");
206
207         match *self.kind {
208             PatKind::Wild => write!(f, "_"),
209             PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{}: _", subpattern),
210             PatKind::Binding { mutability, name, mode, ref subpattern, .. } => {
211                 let is_mut = match mode {
212                     BindingMode::ByValue => mutability == Mutability::Mut,
213                     BindingMode::ByRef(bk) => {
214                         write!(f, "ref ")?;
215                         match bk {
216                             BorrowKind::Mut { .. } => true,
217                             _ => false,
218                         }
219                     }
220                 };
221                 if is_mut {
222                     write!(f, "mut ")?;
223                 }
224                 write!(f, "{}", name)?;
225                 if let Some(ref subpattern) = *subpattern {
226                     write!(f, " @ {}", subpattern)?;
227                 }
228                 Ok(())
229             }
230             PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
231                 let variant = match *self.kind {
232                     PatKind::Variant { adt_def, variant_index, .. } => {
233                         Some(&adt_def.variants[variant_index])
234                     }
235                     _ => {
236                         if let ty::Adt(adt, _) = self.ty.kind {
237                             if !adt.is_enum() {
238                                 Some(&adt.variants[VariantIdx::new(0)])
239                             } else {
240                                 None
241                             }
242                         } else {
243                             None
244                         }
245                     }
246                 };
247
248                 if let Some(variant) = variant {
249                     write!(f, "{}", variant.ident)?;
250
251                     // Only for Adt we can have `S {...}`,
252                     // which we handle separately here.
253                     if variant.ctor_kind == CtorKind::Fictive {
254                         write!(f, " {{ ")?;
255
256                         let mut printed = 0;
257                         for p in subpatterns {
258                             if let PatKind::Wild = *p.pattern.kind {
259                                 continue;
260                             }
261                             let name = variant.fields[p.field.index()].ident;
262                             write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
263                             printed += 1;
264                         }
265
266                         if printed < variant.fields.len() {
267                             write!(f, "{}..", start_or_comma())?;
268                         }
269
270                         return write!(f, " }}");
271                     }
272                 }
273
274                 let num_fields = variant.map_or(subpatterns.len(), |v| v.fields.len());
275                 if num_fields != 0 || variant.is_none() {
276                     write!(f, "(")?;
277                     for i in 0..num_fields {
278                         write!(f, "{}", start_or_comma())?;
279
280                         // Common case: the field is where we expect it.
281                         if let Some(p) = subpatterns.get(i) {
282                             if p.field.index() == i {
283                                 write!(f, "{}", p.pattern)?;
284                                 continue;
285                             }
286                         }
287
288                         // Otherwise, we have to go looking for it.
289                         if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
290                             write!(f, "{}", p.pattern)?;
291                         } else {
292                             write!(f, "_")?;
293                         }
294                     }
295                     write!(f, ")")?;
296                 }
297
298                 Ok(())
299             }
300             PatKind::Deref { ref subpattern } => {
301                 match self.ty.kind {
302                     ty::Adt(def, _) if def.is_box() => write!(f, "box ")?,
303                     ty::Ref(_, _, mutbl) => {
304                         write!(f, "&{}", mutbl.prefix_str())?;
305                     }
306                     _ => bug!("{} is a bad Deref pattern type", self.ty),
307                 }
308                 write!(f, "{}", subpattern)
309             }
310             PatKind::Constant { value } => write!(f, "{}", value),
311             PatKind::Range(PatRange { lo, hi, end }) => {
312                 write!(f, "{}", lo)?;
313                 write!(f, "{}", end)?;
314                 write!(f, "{}", hi)
315             }
316             PatKind::Slice { ref prefix, ref slice, ref suffix }
317             | PatKind::Array { ref prefix, ref slice, ref suffix } => {
318                 write!(f, "[")?;
319                 for p in prefix {
320                     write!(f, "{}{}", start_or_comma(), p)?;
321                 }
322                 if let Some(ref slice) = *slice {
323                     write!(f, "{}", start_or_comma())?;
324                     match *slice.kind {
325                         PatKind::Wild => {}
326                         _ => write!(f, "{}", slice)?,
327                     }
328                     write!(f, "..")?;
329                 }
330                 for p in suffix {
331                     write!(f, "{}{}", start_or_comma(), p)?;
332                 }
333                 write!(f, "]")
334             }
335             PatKind::Or { ref pats } => {
336                 for pat in pats {
337                     write!(f, "{}{}", start_or_continue(" | "), pat)?;
338                 }
339                 Ok(())
340             }
341         }
342     }
343 }
344
345 pub struct PatCtxt<'a, 'tcx> {
346     pub tcx: TyCtxt<'tcx>,
347     pub param_env: ty::ParamEnv<'tcx>,
348     pub tables: &'a ty::TypeckTables<'tcx>,
349     pub substs: SubstsRef<'tcx>,
350     pub errors: Vec<PatternError>,
351     include_lint_checks: bool,
352 }
353
354 impl<'a, 'tcx> Pat<'tcx> {
355     pub fn from_hir(
356         tcx: TyCtxt<'tcx>,
357         param_env_and_substs: ty::ParamEnvAnd<'tcx, SubstsRef<'tcx>>,
358         tables: &'a ty::TypeckTables<'tcx>,
359         pat: &'tcx hir::Pat,
360     ) -> Self {
361         let mut pcx = PatCtxt::new(tcx, param_env_and_substs, tables);
362         let result = pcx.lower_pattern(pat);
363         if !pcx.errors.is_empty() {
364             let msg = format!("encountered errors lowering pattern: {:?}", pcx.errors);
365             tcx.sess.delay_span_bug(pat.span, &msg);
366         }
367         debug!("Pat::from_hir({:?}) = {:?}", pat, result);
368         result
369     }
370 }
371
372 impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
373     pub fn new(
374         tcx: TyCtxt<'tcx>,
375         param_env_and_substs: ty::ParamEnvAnd<'tcx, SubstsRef<'tcx>>,
376         tables: &'a ty::TypeckTables<'tcx>,
377     ) -> Self {
378         PatCtxt {
379             tcx,
380             param_env: param_env_and_substs.param_env,
381             tables,
382             substs: param_env_and_substs.value,
383             errors: vec![],
384             include_lint_checks: false,
385         }
386     }
387
388     pub fn include_lint_checks(&mut self) -> &mut Self {
389         self.include_lint_checks = true;
390         self
391     }
392
393     pub fn lower_pattern(&mut self, pat: &'tcx hir::Pat) -> Pat<'tcx> {
394         // When implicit dereferences have been inserted in this pattern, the unadjusted lowered
395         // pattern has the type that results *after* dereferencing. For example, in this code:
396         //
397         // ```
398         // match &&Some(0i32) {
399         //     Some(n) => { ... },
400         //     _ => { ... },
401         // }
402         // ```
403         //
404         // the type assigned to `Some(n)` in `unadjusted_pat` would be `Option<i32>` (this is
405         // determined in rustc_typeck::check::match). The adjustments would be
406         //
407         // `vec![&&Option<i32>, &Option<i32>]`.
408         //
409         // Applying the adjustments, we want to instead output `&&Some(n)` (as a HAIR pattern). So
410         // we wrap the unadjusted pattern in `PatKind::Deref` repeatedly, consuming the
411         // adjustments in *reverse order* (last-in-first-out, so that the last `Deref` inserted
412         // gets the least-dereferenced type).
413         let unadjusted_pat = self.lower_pattern_unadjusted(pat);
414         self.tables.pat_adjustments().get(pat.hir_id).unwrap_or(&vec![]).iter().rev().fold(
415             unadjusted_pat,
416             |pat, ref_ty| {
417                 debug!("{:?}: wrapping pattern with type {:?}", pat, ref_ty);
418                 Pat {
419                     span: pat.span,
420                     ty: ref_ty,
421                     kind: Box::new(PatKind::Deref { subpattern: pat }),
422                 }
423             },
424         )
425     }
426
427     fn lower_range_expr(
428         &mut self,
429         expr: &'tcx hir::Expr,
430     ) -> (PatKind<'tcx>, Option<Ascription<'tcx>>) {
431         match self.lower_lit(expr) {
432             PatKind::AscribeUserType {
433                 ascription: lo_ascription,
434                 subpattern: Pat { kind: box kind, .. },
435             } => (kind, Some(lo_ascription)),
436             kind => (kind, None),
437         }
438     }
439
440     fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pat<'tcx> {
441         let mut ty = self.tables.node_type(pat.hir_id);
442
443         if let ty::Error = ty.kind {
444             // Avoid ICEs (e.g., #50577 and #50585).
445             return Pat { span: pat.span, ty, kind: Box::new(PatKind::Wild) };
446         }
447
448         let kind = match pat.kind {
449             hir::PatKind::Wild => PatKind::Wild,
450
451             hir::PatKind::Lit(ref value) => self.lower_lit(value),
452
453             hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => {
454                 let (lo, lo_ascription) = self.lower_range_expr(lo_expr);
455                 let (hi, hi_ascription) = self.lower_range_expr(hi_expr);
456
457                 let mut kind = match (lo, hi) {
458                     (PatKind::Constant { value: lo }, PatKind::Constant { value: hi }) => {
459                         assert_eq!(lo.ty, ty);
460                         assert_eq!(hi.ty, ty);
461                         let cmp = compare_const_vals(self.tcx, lo, hi, self.param_env, ty);
462                         match (end, cmp) {
463                             (RangeEnd::Excluded, Some(Ordering::Less)) => {
464                                 PatKind::Range(PatRange { lo, hi, end })
465                             }
466                             (RangeEnd::Excluded, _) => {
467                                 span_err!(
468                                     self.tcx.sess,
469                                     lo_expr.span,
470                                     E0579,
471                                     "lower range bound must be less than upper",
472                                 );
473                                 PatKind::Wild
474                             }
475                             (RangeEnd::Included, Some(Ordering::Equal)) => {
476                                 PatKind::Constant { value: lo }
477                             }
478                             (RangeEnd::Included, Some(Ordering::Less)) => {
479                                 PatKind::Range(PatRange { lo, hi, end })
480                             }
481                             (RangeEnd::Included, _) => {
482                                 let mut err = struct_span_err!(
483                                     self.tcx.sess,
484                                     lo_expr.span,
485                                     E0030,
486                                     "lower range bound must be less than or equal to upper"
487                                 );
488                                 err.span_label(lo_expr.span, "lower bound larger than upper bound");
489                                 if self.tcx.sess.teach(&err.get_code().unwrap()) {
490                                     err.note(
491                                         "When matching against a range, the compiler \
492                                               verifies that the range is non-empty. Range \
493                                               patterns include both end-points, so this is \
494                                               equivalent to requiring the start of the range \
495                                               to be less than or equal to the end of the range.",
496                                     );
497                                 }
498                                 err.emit();
499                                 PatKind::Wild
500                             }
501                         }
502                     }
503                     ref pats => {
504                         self.tcx.sess.delay_span_bug(
505                             pat.span,
506                             &format!(
507                                 "found bad range pattern `{:?}` outside of error recovery",
508                                 pats,
509                             ),
510                         );
511
512                         PatKind::Wild
513                     }
514                 };
515
516                 // If we are handling a range with associated constants (e.g.
517                 // `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
518                 // constants somewhere. Have them on the range pattern.
519                 for ascription in &[lo_ascription, hi_ascription] {
520                     if let Some(ascription) = ascription {
521                         kind = PatKind::AscribeUserType {
522                             ascription: *ascription,
523                             subpattern: Pat { span: pat.span, ty, kind: Box::new(kind) },
524                         };
525                     }
526                 }
527
528                 kind
529             }
530
531             hir::PatKind::Path(ref qpath) => {
532                 return self.lower_path(qpath, pat.hir_id, pat.span);
533             }
534
535             hir::PatKind::Ref(ref subpattern, _) | hir::PatKind::Box(ref subpattern) => {
536                 PatKind::Deref { subpattern: self.lower_pattern(subpattern) }
537             }
538
539             hir::PatKind::Slice(ref prefix, ref slice, ref suffix) => {
540                 self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix)
541             }
542
543             hir::PatKind::Tuple(ref pats, ddpos) => {
544                 let tys = match ty.kind {
545                     ty::Tuple(ref tys) => tys,
546                     _ => span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", ty),
547                 };
548                 let subpatterns = self.lower_tuple_subpats(pats, tys.len(), ddpos);
549                 PatKind::Leaf { subpatterns }
550             }
551
552             hir::PatKind::Binding(_, id, ident, ref sub) => {
553                 let bm =
554                     *self.tables.pat_binding_modes().get(pat.hir_id).expect("missing binding mode");
555                 let (mutability, mode) = match bm {
556                     ty::BindByValue(mutbl) => (mutbl, BindingMode::ByValue),
557                     ty::BindByReference(hir::Mutability::Mut) => (
558                         Mutability::Not,
559                         BindingMode::ByRef(BorrowKind::Mut { allow_two_phase_borrow: false }),
560                     ),
561                     ty::BindByReference(hir::Mutability::Not) => {
562                         (Mutability::Not, BindingMode::ByRef(BorrowKind::Shared))
563                     }
564                 };
565
566                 // A ref x pattern is the same node used for x, and as such it has
567                 // x's type, which is &T, where we want T (the type being matched).
568                 let var_ty = ty;
569                 if let ty::BindByReference(_) = bm {
570                     if let ty::Ref(_, rty, _) = ty.kind {
571                         ty = rty;
572                     } else {
573                         bug!("`ref {}` has wrong type {}", ident, ty);
574                     }
575                 };
576
577                 PatKind::Binding {
578                     mutability,
579                     mode,
580                     name: ident.name,
581                     var: id,
582                     ty: var_ty,
583                     subpattern: self.lower_opt_pattern(sub),
584                 }
585             }
586
587             hir::PatKind::TupleStruct(ref qpath, ref pats, ddpos) => {
588                 let res = self.tables.qpath_res(qpath, pat.hir_id);
589                 let adt_def = match ty.kind {
590                     ty::Adt(adt_def, _) => adt_def,
591                     _ => span_bug!(pat.span, "tuple struct pattern not applied to an ADT {:?}", ty),
592                 };
593                 let variant_def = adt_def.variant_of_res(res);
594                 let subpatterns = self.lower_tuple_subpats(pats, variant_def.fields.len(), ddpos);
595                 self.lower_variant_or_leaf(res, pat.hir_id, pat.span, ty, subpatterns)
596             }
597
598             hir::PatKind::Struct(ref qpath, ref fields, _) => {
599                 let res = self.tables.qpath_res(qpath, pat.hir_id);
600                 let subpatterns = fields
601                     .iter()
602                     .map(|field| FieldPat {
603                         field: Field::new(self.tcx.field_index(field.hir_id, self.tables)),
604                         pattern: self.lower_pattern(&field.pat),
605                     })
606                     .collect();
607
608                 self.lower_variant_or_leaf(res, pat.hir_id, pat.span, ty, subpatterns)
609             }
610
611             hir::PatKind::Or(ref pats) => PatKind::Or { pats: self.lower_patterns(pats) },
612         };
613
614         Pat { span: pat.span, ty, kind: Box::new(kind) }
615     }
616
617     fn lower_tuple_subpats(
618         &mut self,
619         pats: &'tcx [P<hir::Pat>],
620         expected_len: usize,
621         gap_pos: Option<usize>,
622     ) -> Vec<FieldPat<'tcx>> {
623         pats.iter()
624             .enumerate_and_adjust(expected_len, gap_pos)
625             .map(|(i, subpattern)| FieldPat {
626                 field: Field::new(i),
627                 pattern: self.lower_pattern(subpattern),
628             })
629             .collect()
630     }
631
632     fn lower_patterns(&mut self, pats: &'tcx [P<hir::Pat>]) -> Vec<Pat<'tcx>> {
633         pats.iter().map(|p| self.lower_pattern(p)).collect()
634     }
635
636     fn lower_opt_pattern(&mut self, pat: &'tcx Option<P<hir::Pat>>) -> Option<Pat<'tcx>> {
637         pat.as_ref().map(|p| self.lower_pattern(p))
638     }
639
640     fn slice_or_array_pattern(
641         &mut self,
642         span: Span,
643         ty: Ty<'tcx>,
644         prefix: &'tcx [P<hir::Pat>],
645         slice: &'tcx Option<P<hir::Pat>>,
646         suffix: &'tcx [P<hir::Pat>],
647     ) -> PatKind<'tcx> {
648         let prefix = self.lower_patterns(prefix);
649         let slice = self.lower_opt_pattern(slice);
650         let suffix = self.lower_patterns(suffix);
651         match ty.kind {
652             // Matching a slice, `[T]`.
653             ty::Slice(..) => PatKind::Slice { prefix, slice, suffix },
654             // Fixed-length array, `[T; len]`.
655             ty::Array(_, len) => {
656                 let len = len.eval_usize(self.tcx, self.param_env);
657                 assert!(len >= prefix.len() as u64 + suffix.len() as u64);
658                 PatKind::Array { prefix, slice, suffix }
659             }
660             _ => span_bug!(span, "bad slice pattern type {:?}", ty),
661         }
662     }
663
664     fn lower_variant_or_leaf(
665         &mut self,
666         res: Res,
667         hir_id: hir::HirId,
668         span: Span,
669         ty: Ty<'tcx>,
670         subpatterns: Vec<FieldPat<'tcx>>,
671     ) -> PatKind<'tcx> {
672         let res = match res {
673             Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
674                 let variant_id = self.tcx.parent(variant_ctor_id).unwrap();
675                 Res::Def(DefKind::Variant, variant_id)
676             }
677             res => res,
678         };
679
680         let mut kind = match res {
681             Res::Def(DefKind::Variant, variant_id) => {
682                 let enum_id = self.tcx.parent(variant_id).unwrap();
683                 let adt_def = self.tcx.adt_def(enum_id);
684                 if adt_def.is_enum() {
685                     let substs = match ty.kind {
686                         ty::Adt(_, substs) | ty::FnDef(_, substs) => substs,
687                         ty::Error => {
688                             // Avoid ICE (#50585)
689                             return PatKind::Wild;
690                         }
691                         _ => bug!("inappropriate type for def: {:?}", ty),
692                     };
693                     PatKind::Variant {
694                         adt_def,
695                         substs,
696                         variant_index: adt_def.variant_index_with_id(variant_id),
697                         subpatterns,
698                     }
699                 } else {
700                     PatKind::Leaf { subpatterns }
701                 }
702             }
703
704             Res::Def(DefKind::Struct, _)
705             | Res::Def(DefKind::Ctor(CtorOf::Struct, ..), _)
706             | Res::Def(DefKind::Union, _)
707             | Res::Def(DefKind::TyAlias, _)
708             | Res::Def(DefKind::AssocTy, _)
709             | Res::SelfTy(..)
710             | Res::SelfCtor(..) => PatKind::Leaf { subpatterns },
711
712             _ => {
713                 self.errors.push(PatternError::NonConstPath(span));
714                 PatKind::Wild
715             }
716         };
717
718         if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) {
719             debug!("lower_variant_or_leaf: kind={:?} user_ty={:?} span={:?}", kind, user_ty, span);
720             kind = PatKind::AscribeUserType {
721                 subpattern: Pat { span, ty, kind: Box::new(kind) },
722                 ascription: Ascription {
723                     user_ty: PatTyProj::from_user_type(user_ty),
724                     user_ty_span: span,
725                     variance: ty::Variance::Covariant,
726                 },
727             };
728         }
729
730         kind
731     }
732
733     /// Takes a HIR Path. If the path is a constant, evaluates it and feeds
734     /// it to `const_to_pat`. Any other path (like enum variants without fields)
735     /// is converted to the corresponding pattern via `lower_variant_or_leaf`.
736     fn lower_path(&mut self, qpath: &hir::QPath, id: hir::HirId, span: Span) -> Pat<'tcx> {
737         let ty = self.tables.node_type(id);
738         let res = self.tables.qpath_res(qpath, id);
739         let is_associated_const = match res {
740             Res::Def(DefKind::AssocConst, _) => true,
741             _ => false,
742         };
743         let kind = match res {
744             Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => {
745                 let substs = self.tables.node_substs(id);
746                 match self.tcx.const_eval_resolve(self.param_env, def_id, substs, Some(span)) {
747                     Ok(value) => {
748                         let pattern = self.const_to_pat(value, id, span);
749                         if !is_associated_const {
750                             return pattern;
751                         }
752
753                         let user_provided_types = self.tables().user_provided_types();
754                         return if let Some(u_ty) = user_provided_types.get(id) {
755                             let user_ty = PatTyProj::from_user_type(*u_ty);
756                             Pat {
757                                 span,
758                                 kind: Box::new(PatKind::AscribeUserType {
759                                     subpattern: pattern,
760                                     ascription: Ascription {
761                                         /// Note that use `Contravariant` here. See the
762                                         /// `variance` field documentation for details.
763                                         variance: ty::Variance::Contravariant,
764                                         user_ty,
765                                         user_ty_span: span,
766                                     },
767                                 }),
768                                 ty: value.ty,
769                             }
770                         } else {
771                             pattern
772                         };
773                     }
774                     Err(ErrorHandled::TooGeneric) => {
775                         self.errors.push(if is_associated_const {
776                             PatternError::AssocConstInPattern(span)
777                         } else {
778                             PatternError::StaticInPattern(span)
779                         });
780                         PatKind::Wild
781                     }
782                     Err(_) => {
783                         self.tcx.sess.span_err(span, "could not evaluate constant pattern");
784                         PatKind::Wild
785                     }
786                 }
787             }
788             _ => self.lower_variant_or_leaf(res, id, span, ty, vec![]),
789         };
790
791         Pat { span, ty, kind: Box::new(kind) }
792     }
793
794     /// Converts literals, paths and negation of literals to patterns.
795     /// The special case for negation exists to allow things like `-128_i8`
796     /// which would overflow if we tried to evaluate `128_i8` and then negate
797     /// afterwards.
798     fn lower_lit(&mut self, expr: &'tcx hir::Expr) -> PatKind<'tcx> {
799         match expr.kind {
800             hir::ExprKind::Lit(ref lit) => {
801                 let ty = self.tables.expr_ty(expr);
802                 match lit_to_const(&lit.node, self.tcx, ty, false) {
803                     Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span).kind,
804                     Err(LitToConstError::UnparseableFloat) => {
805                         self.errors.push(PatternError::FloatBug);
806                         PatKind::Wild
807                     }
808                     Err(LitToConstError::Reported) => PatKind::Wild,
809                 }
810             }
811             hir::ExprKind::Path(ref qpath) => *self.lower_path(qpath, expr.hir_id, expr.span).kind,
812             hir::ExprKind::Unary(hir::UnNeg, ref expr) => {
813                 let ty = self.tables.expr_ty(expr);
814                 let lit = match expr.kind {
815                     hir::ExprKind::Lit(ref lit) => lit,
816                     _ => span_bug!(expr.span, "not a literal: {:?}", expr),
817                 };
818                 match lit_to_const(&lit.node, self.tcx, ty, true) {
819                     Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span).kind,
820                     Err(LitToConstError::UnparseableFloat) => {
821                         self.errors.push(PatternError::FloatBug);
822                         PatKind::Wild
823                     }
824                     Err(LitToConstError::Reported) => PatKind::Wild,
825                 }
826             }
827             _ => span_bug!(expr.span, "not a literal: {:?}", expr),
828         }
829     }
830 }
831
832 impl UserAnnotatedTyHelpers<'tcx> for PatCtxt<'_, 'tcx> {
833     fn tcx(&self) -> TyCtxt<'tcx> {
834         self.tcx
835     }
836
837     fn tables(&self) -> &ty::TypeckTables<'tcx> {
838         self.tables
839     }
840 }
841
842 pub trait PatternFoldable<'tcx>: Sized {
843     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
844         self.super_fold_with(folder)
845     }
846
847     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self;
848 }
849
850 pub trait PatternFolder<'tcx>: Sized {
851     fn fold_pattern(&mut self, pattern: &Pat<'tcx>) -> Pat<'tcx> {
852         pattern.super_fold_with(self)
853     }
854
855     fn fold_pattern_kind(&mut self, kind: &PatKind<'tcx>) -> PatKind<'tcx> {
856         kind.super_fold_with(self)
857     }
858 }
859
860 impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Box<T> {
861     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
862         let content: T = (**self).fold_with(folder);
863         box content
864     }
865 }
866
867 impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Vec<T> {
868     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
869         self.iter().map(|t| t.fold_with(folder)).collect()
870     }
871 }
872
873 impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Option<T> {
874     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
875         self.as_ref().map(|t| t.fold_with(folder))
876     }
877 }
878
879 macro_rules! CloneImpls {
880     (<$lt_tcx:tt> $($ty:ty),+) => {
881         $(
882             impl<$lt_tcx> PatternFoldable<$lt_tcx> for $ty {
883                 fn super_fold_with<F: PatternFolder<$lt_tcx>>(&self, _: &mut F) -> Self {
884                     Clone::clone(self)
885                 }
886             }
887         )+
888     }
889 }
890
891 CloneImpls! { <'tcx>
892     Span, Field, Mutability, ast::Name, hir::HirId, usize, ty::Const<'tcx>,
893     Region<'tcx>, Ty<'tcx>, BindingMode, &'tcx AdtDef,
894     SubstsRef<'tcx>, &'tcx GenericArg<'tcx>, UserType<'tcx>,
895     UserTypeProjection, PatTyProj<'tcx>
896 }
897
898 impl<'tcx> PatternFoldable<'tcx> for FieldPat<'tcx> {
899     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
900         FieldPat { field: self.field.fold_with(folder), pattern: self.pattern.fold_with(folder) }
901     }
902 }
903
904 impl<'tcx> PatternFoldable<'tcx> for Pat<'tcx> {
905     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
906         folder.fold_pattern(self)
907     }
908
909     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
910         Pat {
911             ty: self.ty.fold_with(folder),
912             span: self.span.fold_with(folder),
913             kind: self.kind.fold_with(folder),
914         }
915     }
916 }
917
918 impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> {
919     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
920         folder.fold_pattern_kind(self)
921     }
922
923     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
924         match *self {
925             PatKind::Wild => PatKind::Wild,
926             PatKind::AscribeUserType {
927                 ref subpattern,
928                 ascription: Ascription { variance, ref user_ty, user_ty_span },
929             } => PatKind::AscribeUserType {
930                 subpattern: subpattern.fold_with(folder),
931                 ascription: Ascription {
932                     user_ty: user_ty.fold_with(folder),
933                     variance,
934                     user_ty_span,
935                 },
936             },
937             PatKind::Binding { mutability, name, mode, var, ty, ref subpattern } => {
938                 PatKind::Binding {
939                     mutability: mutability.fold_with(folder),
940                     name: name.fold_with(folder),
941                     mode: mode.fold_with(folder),
942                     var: var.fold_with(folder),
943                     ty: ty.fold_with(folder),
944                     subpattern: subpattern.fold_with(folder),
945                 }
946             }
947             PatKind::Variant { adt_def, substs, variant_index, ref subpatterns } => {
948                 PatKind::Variant {
949                     adt_def: adt_def.fold_with(folder),
950                     substs: substs.fold_with(folder),
951                     variant_index,
952                     subpatterns: subpatterns.fold_with(folder),
953                 }
954             }
955             PatKind::Leaf { ref subpatterns } => {
956                 PatKind::Leaf { subpatterns: subpatterns.fold_with(folder) }
957             }
958             PatKind::Deref { ref subpattern } => {
959                 PatKind::Deref { subpattern: subpattern.fold_with(folder) }
960             }
961             PatKind::Constant { value } => PatKind::Constant { value },
962             PatKind::Range(range) => PatKind::Range(range),
963             PatKind::Slice { ref prefix, ref slice, ref suffix } => PatKind::Slice {
964                 prefix: prefix.fold_with(folder),
965                 slice: slice.fold_with(folder),
966                 suffix: suffix.fold_with(folder),
967             },
968             PatKind::Array { ref prefix, ref slice, ref suffix } => PatKind::Array {
969                 prefix: prefix.fold_with(folder),
970                 slice: slice.fold_with(folder),
971                 suffix: suffix.fold_with(folder),
972             },
973             PatKind::Or { ref pats } => PatKind::Or { pats: pats.fold_with(folder) },
974         }
975     }
976 }
977
978 pub fn compare_const_vals<'tcx>(
979     tcx: TyCtxt<'tcx>,
980     a: &'tcx ty::Const<'tcx>,
981     b: &'tcx ty::Const<'tcx>,
982     param_env: ty::ParamEnv<'tcx>,
983     ty: Ty<'tcx>,
984 ) -> Option<Ordering> {
985     trace!("compare_const_vals: {:?}, {:?}", a, b);
986
987     let from_bool = |v: bool| v.then_some(Ordering::Equal);
988
989     let fallback = || from_bool(a == b);
990
991     // Use the fallback if any type differs
992     if a.ty != b.ty || a.ty != ty {
993         return fallback();
994     }
995
996     let a_bits = a.try_eval_bits(tcx, param_env, ty);
997     let b_bits = b.try_eval_bits(tcx, param_env, ty);
998
999     if let (Some(a), Some(b)) = (a_bits, b_bits) {
1000         use ::rustc_apfloat::Float;
1001         return match ty.kind {
1002             ty::Float(ast::FloatTy::F32) => {
1003                 let l = ::rustc_apfloat::ieee::Single::from_bits(a);
1004                 let r = ::rustc_apfloat::ieee::Single::from_bits(b);
1005                 l.partial_cmp(&r)
1006             }
1007             ty::Float(ast::FloatTy::F64) => {
1008                 let l = ::rustc_apfloat::ieee::Double::from_bits(a);
1009                 let r = ::rustc_apfloat::ieee::Double::from_bits(b);
1010                 l.partial_cmp(&r)
1011             }
1012             ty::Int(ity) => {
1013                 use rustc::ty::layout::{Integer, IntegerExt};
1014                 use syntax::attr::SignedInt;
1015                 let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
1016                 let a = sign_extend(a, size);
1017                 let b = sign_extend(b, size);
1018                 Some((a as i128).cmp(&(b as i128)))
1019             }
1020             _ => Some(a.cmp(&b)),
1021         };
1022     }
1023
1024     if let ty::Str = ty.kind {
1025         match (a.val, b.val) {
1026             (
1027                 ty::ConstKind::Value(a_val @ ConstValue::Slice { .. }),
1028                 ty::ConstKind::Value(b_val @ ConstValue::Slice { .. }),
1029             ) => {
1030                 let a_bytes = get_slice_bytes(&tcx, a_val);
1031                 let b_bytes = get_slice_bytes(&tcx, b_val);
1032                 return from_bool(a_bytes == b_bytes);
1033             }
1034             _ => (),
1035         }
1036     }
1037
1038     fallback()
1039 }