]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/hair/pattern/mod.rs
Rollup merge of #59634 - DevQps:explain-E0704, r=estebank
[rust.git] / src / librustc_mir / hair / pattern / mod.rs
1 //! Validation of patterns/matches.
2
3 mod _match;
4 mod check_match;
5
6 pub(crate) use self::check_match::check_match;
7
8 use crate::const_eval::{const_field, const_variant_index};
9
10 use crate::hair::util::UserAnnotatedTyHelpers;
11 use crate::hair::constant::*;
12
13 use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
14 use rustc::mir::{UserTypeProjection};
15 use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
16 use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, UserType, DefIdTree};
17 use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
18 use rustc::ty::subst::{SubstsRef, Kind};
19 use rustc::ty::layout::VariantIdx;
20 use rustc::hir::{self, PatKind, RangeEnd};
21 use rustc::hir::def::{CtorOf, Def, CtorKind};
22 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
23
24 use rustc_data_structures::indexed_vec::Idx;
25
26 use std::cmp::Ordering;
27 use std::fmt;
28 use syntax::ast;
29 use syntax::ptr::P;
30 use syntax_pos::Span;
31
32 #[derive(Clone, Debug)]
33 pub enum PatternError {
34     AssociatedConstInPattern(Span),
35     StaticInPattern(Span),
36     FloatBug,
37     NonConstPath(Span),
38 }
39
40 #[derive(Copy, Clone, Debug)]
41 pub enum BindingMode {
42     ByValue,
43     ByRef(BorrowKind),
44 }
45
46 #[derive(Clone, Debug)]
47 pub struct FieldPattern<'tcx> {
48     pub field: Field,
49     pub pattern: Pattern<'tcx>,
50 }
51
52 #[derive(Clone, Debug)]
53 pub struct Pattern<'tcx> {
54     pub ty: Ty<'tcx>,
55     pub span: Span,
56     pub kind: Box<PatternKind<'tcx>>,
57 }
58
59
60 #[derive(Copy, Clone, Debug, PartialEq)]
61 pub struct PatternTypeProjection<'tcx> {
62     pub user_ty: CanonicalUserType<'tcx>,
63 }
64
65 impl<'tcx> PatternTypeProjection<'tcx> {
66     pub(crate) fn from_user_type(user_annotation: CanonicalUserType<'tcx>) -> Self {
67         Self {
68             user_ty: user_annotation,
69         }
70     }
71
72     pub(crate) fn user_ty(
73         self,
74         annotations: &mut CanonicalUserTypeAnnotations<'tcx>,
75         inferred_ty: Ty<'tcx>,
76         span: Span,
77     ) -> UserTypeProjection {
78         UserTypeProjection {
79             base: annotations.push(CanonicalUserTypeAnnotation {
80                 span,
81                 user_ty: self.user_ty,
82                 inferred_ty,
83             }),
84             projs: Vec::new(),
85         }
86     }
87 }
88
89 #[derive(Copy, Clone, Debug, PartialEq)]
90 pub struct Ascription<'tcx> {
91     pub user_ty: PatternTypeProjection<'tcx>,
92     /// Variance to use when relating the type `user_ty` to the **type of the value being
93     /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
94     /// have a type that is some subtype of the ascribed type.
95     ///
96     /// Note that this variance does not apply for any bindings within subpatterns. The type
97     /// assigned to those bindings must be exactly equal to the `user_ty` given here.
98     ///
99     /// The only place where this field is not `Covariant` is when matching constants, where
100     /// we currently use `Contravariant` -- this is because the constant type just needs to
101     /// be "comparable" to the type of the input value. So, for example:
102     ///
103     /// ```text
104     /// match x { "foo" => .. }
105     /// ```
106     ///
107     /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
108     /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
109     /// of the old type-check for now. See #57280 for details.
110     pub variance: ty::Variance,
111     pub user_ty_span: Span,
112 }
113
114 #[derive(Clone, Debug)]
115 pub enum PatternKind<'tcx> {
116     Wild,
117
118     AscribeUserType {
119         ascription: Ascription<'tcx>,
120         subpattern: Pattern<'tcx>,
121     },
122
123     /// `x`, `ref x`, `x @ P`, etc.
124     Binding {
125         mutability: Mutability,
126         name: ast::Name,
127         mode: BindingMode,
128         var: hir::HirId,
129         ty: Ty<'tcx>,
130         subpattern: Option<Pattern<'tcx>>,
131     },
132
133     /// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
134     /// multiple variants.
135     Variant {
136         adt_def: &'tcx AdtDef,
137         substs: SubstsRef<'tcx>,
138         variant_index: VariantIdx,
139         subpatterns: Vec<FieldPattern<'tcx>>,
140     },
141
142     /// `(...)`, `Foo(...)`, `Foo{...}`, or `Foo`, where `Foo` is a variant name from an ADT with
143     /// a single variant.
144     Leaf {
145         subpatterns: Vec<FieldPattern<'tcx>>,
146     },
147
148     /// `box P`, `&P`, `&mut P`, etc.
149     Deref {
150         subpattern: Pattern<'tcx>,
151     },
152
153     Constant {
154         value: ty::Const<'tcx>,
155     },
156
157     Range(PatternRange<'tcx>),
158
159     /// Matches against a slice, checking the length and extracting elements.
160     /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
161     /// e.g., `&[ref xs..]`.
162     Slice {
163         prefix: Vec<Pattern<'tcx>>,
164         slice: Option<Pattern<'tcx>>,
165         suffix: Vec<Pattern<'tcx>>,
166     },
167
168     /// Fixed match against an array; irrefutable.
169     Array {
170         prefix: Vec<Pattern<'tcx>>,
171         slice: Option<Pattern<'tcx>>,
172         suffix: Vec<Pattern<'tcx>>,
173     },
174 }
175
176 #[derive(Copy, Clone, Debug, PartialEq)]
177 pub struct PatternRange<'tcx> {
178     pub lo: ty::Const<'tcx>,
179     pub hi: ty::Const<'tcx>,
180     pub ty: Ty<'tcx>,
181     pub end: RangeEnd,
182 }
183
184 impl<'tcx> fmt::Display for Pattern<'tcx> {
185     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186         match *self.kind {
187             PatternKind::Wild => write!(f, "_"),
188             PatternKind::AscribeUserType { ref subpattern, .. } =>
189                 write!(f, "{}: _", subpattern),
190             PatternKind::Binding { mutability, name, mode, ref subpattern, .. } => {
191                 let is_mut = match mode {
192                     BindingMode::ByValue => mutability == Mutability::Mut,
193                     BindingMode::ByRef(bk) => {
194                         write!(f, "ref ")?;
195                         match bk { BorrowKind::Mut { .. } => true, _ => false }
196                     }
197                 };
198                 if is_mut {
199                     write!(f, "mut ")?;
200                 }
201                 write!(f, "{}", name)?;
202                 if let Some(ref subpattern) = *subpattern {
203                     write!(f, " @ {}", subpattern)?;
204                 }
205                 Ok(())
206             }
207             PatternKind::Variant { ref subpatterns, .. } |
208             PatternKind::Leaf { ref subpatterns } => {
209                 let variant = match *self.kind {
210                     PatternKind::Variant { adt_def, variant_index, .. } => {
211                         Some(&adt_def.variants[variant_index])
212                     }
213                     _ => if let ty::Adt(adt, _) = self.ty.sty {
214                         if !adt.is_enum() {
215                             Some(&adt.variants[VariantIdx::new(0)])
216                         } else {
217                             None
218                         }
219                     } else {
220                         None
221                     }
222                 };
223
224                 let mut first = true;
225                 let mut start_or_continue = || if first { first = false; "" } else { ", " };
226
227                 if let Some(variant) = variant {
228                     write!(f, "{}", variant.ident)?;
229
230                     // Only for Adt we can have `S {...}`,
231                     // which we handle separately here.
232                     if variant.ctor_kind == CtorKind::Fictive {
233                         write!(f, " {{ ")?;
234
235                         let mut printed = 0;
236                         for p in subpatterns {
237                             if let PatternKind::Wild = *p.pattern.kind {
238                                 continue;
239                             }
240                             let name = variant.fields[p.field.index()].ident;
241                             write!(f, "{}{}: {}", start_or_continue(), name, p.pattern)?;
242                             printed += 1;
243                         }
244
245                         if printed < variant.fields.len() {
246                             write!(f, "{}..", start_or_continue())?;
247                         }
248
249                         return write!(f, " }}");
250                     }
251                 }
252
253                 let num_fields = variant.map_or(subpatterns.len(), |v| v.fields.len());
254                 if num_fields != 0 || variant.is_none() {
255                     write!(f, "(")?;
256                     for i in 0..num_fields {
257                         write!(f, "{}", start_or_continue())?;
258
259                         // Common case: the field is where we expect it.
260                         if let Some(p) = subpatterns.get(i) {
261                             if p.field.index() == i {
262                                 write!(f, "{}", p.pattern)?;
263                                 continue;
264                             }
265                         }
266
267                         // Otherwise, we have to go looking for it.
268                         if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
269                             write!(f, "{}", p.pattern)?;
270                         } else {
271                             write!(f, "_")?;
272                         }
273                     }
274                     write!(f, ")")?;
275                 }
276
277                 Ok(())
278             }
279             PatternKind::Deref { ref subpattern } => {
280                 match self.ty.sty {
281                     ty::Adt(def, _) if def.is_box() => write!(f, "box ")?,
282                     ty::Ref(_, _, mutbl) => {
283                         write!(f, "&")?;
284                         if mutbl == hir::MutMutable {
285                             write!(f, "mut ")?;
286                         }
287                     }
288                     _ => bug!("{} is a bad Deref pattern type", self.ty)
289                 }
290                 write!(f, "{}", subpattern)
291             }
292             PatternKind::Constant { value } => {
293                 fmt_const_val(f, value)
294             }
295             PatternKind::Range(PatternRange { lo, hi, ty: _, end }) => {
296                 fmt_const_val(f, lo)?;
297                 match end {
298                     RangeEnd::Included => write!(f, "..=")?,
299                     RangeEnd::Excluded => write!(f, "..")?,
300                 }
301                 fmt_const_val(f, hi)
302             }
303             PatternKind::Slice { ref prefix, ref slice, ref suffix } |
304             PatternKind::Array { ref prefix, ref slice, ref suffix } => {
305                 let mut first = true;
306                 let mut start_or_continue = || if first { first = false; "" } else { ", " };
307                 write!(f, "[")?;
308                 for p in prefix {
309                     write!(f, "{}{}", start_or_continue(), p)?;
310                 }
311                 if let Some(ref slice) = *slice {
312                     write!(f, "{}", start_or_continue())?;
313                     match *slice.kind {
314                         PatternKind::Wild => {}
315                         _ => write!(f, "{}", slice)?
316                     }
317                     write!(f, "..")?;
318                 }
319                 for p in suffix {
320                     write!(f, "{}{}", start_or_continue(), p)?;
321                 }
322                 write!(f, "]")
323             }
324         }
325     }
326 }
327
328 pub struct PatternContext<'a, 'tcx: 'a> {
329     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
330     pub param_env: ty::ParamEnv<'tcx>,
331     pub tables: &'a ty::TypeckTables<'tcx>,
332     pub substs: SubstsRef<'tcx>,
333     pub errors: Vec<PatternError>,
334 }
335
336 impl<'a, 'tcx> Pattern<'tcx> {
337     pub fn from_hir(tcx: TyCtxt<'a, 'tcx, 'tcx>,
338                     param_env_and_substs: ty::ParamEnvAnd<'tcx, SubstsRef<'tcx>>,
339                     tables: &'a ty::TypeckTables<'tcx>,
340                     pat: &'tcx hir::Pat) -> Self {
341         let mut pcx = PatternContext::new(tcx, param_env_and_substs, tables);
342         let result = pcx.lower_pattern(pat);
343         if !pcx.errors.is_empty() {
344             let msg = format!("encountered errors lowering pattern: {:?}", pcx.errors);
345             tcx.sess.delay_span_bug(pat.span, &msg);
346         }
347         debug!("Pattern::from_hir({:?}) = {:?}", pat, result);
348         result
349     }
350 }
351
352 impl<'a, 'tcx> PatternContext<'a, 'tcx> {
353     pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
354                param_env_and_substs: ty::ParamEnvAnd<'tcx, SubstsRef<'tcx>>,
355                tables: &'a ty::TypeckTables<'tcx>) -> Self {
356         PatternContext {
357             tcx,
358             param_env: param_env_and_substs.param_env,
359             tables,
360             substs: param_env_and_substs.value,
361             errors: vec![]
362         }
363     }
364
365     pub fn lower_pattern(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
366         // When implicit dereferences have been inserted in this pattern, the unadjusted lowered
367         // pattern has the type that results *after* dereferencing. For example, in this code:
368         //
369         // ```
370         // match &&Some(0i32) {
371         //     Some(n) => { ... },
372         //     _ => { ... },
373         // }
374         // ```
375         //
376         // the type assigned to `Some(n)` in `unadjusted_pat` would be `Option<i32>` (this is
377         // determined in rustc_typeck::check::match). The adjustments would be
378         //
379         // `vec![&&Option<i32>, &Option<i32>]`.
380         //
381         // Applying the adjustments, we want to instead output `&&Some(n)` (as a HAIR pattern). So
382         // we wrap the unadjusted pattern in `PatternKind::Deref` repeatedly, consuming the
383         // adjustments in *reverse order* (last-in-first-out, so that the last `Deref` inserted
384         // gets the least-dereferenced type).
385         let unadjusted_pat = self.lower_pattern_unadjusted(pat);
386         self.tables
387             .pat_adjustments()
388             .get(pat.hir_id)
389             .unwrap_or(&vec![])
390             .iter()
391             .rev()
392             .fold(unadjusted_pat, |pat, ref_ty| {
393                     debug!("{:?}: wrapping pattern with type {:?}", pat, ref_ty);
394                     Pattern {
395                         span: pat.span,
396                         ty: ref_ty,
397                         kind: Box::new(PatternKind::Deref { subpattern: pat }),
398                     }
399                 },
400             )
401     }
402
403     fn lower_range_expr(
404         &mut self,
405         expr: &'tcx hir::Expr,
406     ) -> (PatternKind<'tcx>, Option<Ascription<'tcx>>) {
407         match self.lower_lit(expr) {
408             PatternKind::AscribeUserType {
409                 ascription: lo_ascription,
410                 subpattern: Pattern { kind: box kind, .. },
411             } => (kind, Some(lo_ascription)),
412             kind => (kind, None),
413         }
414     }
415
416     fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
417         let mut ty = self.tables.node_type(pat.hir_id);
418
419         let kind = match pat.node {
420             PatKind::Wild => PatternKind::Wild,
421
422             PatKind::Lit(ref value) => self.lower_lit(value),
423
424             PatKind::Range(ref lo_expr, ref hi_expr, end) => {
425                 let (lo, lo_ascription) = self.lower_range_expr(lo_expr);
426                 let (hi, hi_ascription) = self.lower_range_expr(hi_expr);
427
428                 let mut kind = match (lo, hi) {
429                     (PatternKind::Constant { value: lo }, PatternKind::Constant { value: hi }) => {
430                         let cmp = compare_const_vals(
431                             self.tcx,
432                             lo,
433                             hi,
434                             self.param_env.and(ty),
435                         );
436                         match (end, cmp) {
437                             (RangeEnd::Excluded, Some(Ordering::Less)) =>
438                                 PatternKind::Range(PatternRange { lo, hi, ty, end }),
439                             (RangeEnd::Excluded, _) => {
440                                 span_err!(
441                                     self.tcx.sess,
442                                     lo_expr.span,
443                                     E0579,
444                                     "lower range bound must be less than upper",
445                                 );
446                                 PatternKind::Wild
447                             }
448                             (RangeEnd::Included, Some(Ordering::Equal)) => {
449                                 PatternKind::Constant { value: lo }
450                             }
451                             (RangeEnd::Included, Some(Ordering::Less)) => {
452                                 PatternKind::Range(PatternRange { lo, hi, ty, end })
453                             }
454                             (RangeEnd::Included, _) => {
455                                 let mut err = struct_span_err!(
456                                     self.tcx.sess,
457                                     lo_expr.span,
458                                     E0030,
459                                     "lower range bound must be less than or equal to upper"
460                                 );
461                                 err.span_label(
462                                     lo_expr.span,
463                                     "lower bound larger than upper bound",
464                                 );
465                                 if self.tcx.sess.teach(&err.get_code().unwrap()) {
466                                     err.note("When matching against a range, the compiler \
467                                               verifies that the range is non-empty. Range \
468                                               patterns include both end-points, so this is \
469                                               equivalent to requiring the start of the range \
470                                               to be less than or equal to the end of the range.");
471                                 }
472                                 err.emit();
473                                 PatternKind::Wild
474                             }
475                         }
476                     },
477                     ref pats => {
478                         self.tcx.sess.delay_span_bug(
479                             pat.span,
480                             &format!(
481                                 "found bad range pattern `{:?}` outside of error recovery",
482                                 pats,
483                             ),
484                         );
485
486                         PatternKind::Wild
487                     },
488                 };
489
490                 // If we are handling a range with associated constants (e.g.
491                 // `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
492                 // constants somewhere. Have them on the range pattern.
493                 for ascription in &[lo_ascription, hi_ascription] {
494                     if let Some(ascription) = ascription {
495                         kind = PatternKind::AscribeUserType {
496                             ascription: *ascription,
497                             subpattern: Pattern { span: pat.span, ty, kind: Box::new(kind), },
498                         };
499                     }
500                 }
501
502                 kind
503             }
504
505             PatKind::Path(ref qpath) => {
506                 return self.lower_path(qpath, pat.hir_id, pat.span);
507             }
508
509             PatKind::Ref(ref subpattern, _) |
510             PatKind::Box(ref subpattern) => {
511                 PatternKind::Deref { subpattern: self.lower_pattern(subpattern) }
512             }
513
514             PatKind::Slice(ref prefix, ref slice, ref suffix) => {
515                 match ty.sty {
516                     ty::Ref(_, ty, _) =>
517                         PatternKind::Deref {
518                             subpattern: Pattern {
519                                 ty,
520                                 span: pat.span,
521                                 kind: Box::new(self.slice_or_array_pattern(
522                                     pat.span, ty, prefix, slice, suffix))
523                             },
524                         },
525                     ty::Slice(..) |
526                     ty::Array(..) =>
527                         self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix),
528                     ty::Error => { // Avoid ICE
529                         return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
530                     }
531                     _ =>
532                         span_bug!(
533                             pat.span,
534                             "unexpanded type for vector pattern: {:?}",
535                             ty),
536                 }
537             }
538
539             PatKind::Tuple(ref subpatterns, ddpos) => {
540                 match ty.sty {
541                     ty::Tuple(ref tys) => {
542                         let subpatterns =
543                             subpatterns.iter()
544                                        .enumerate_and_adjust(tys.len(), ddpos)
545                                        .map(|(i, subpattern)| FieldPattern {
546                                             field: Field::new(i),
547                                             pattern: self.lower_pattern(subpattern)
548                                        })
549                                        .collect();
550
551                         PatternKind::Leaf { subpatterns }
552                     }
553                     ty::Error => { // Avoid ICE (#50577)
554                         return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
555                     }
556                     _ => span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", ty),
557                 }
558             }
559
560             PatKind::Binding(_, id, ident, ref sub) => {
561                 let var_ty = self.tables.node_type(pat.hir_id);
562                 if let ty::Error = var_ty.sty {
563                     // Avoid ICE
564                     return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
565                 };
566                 let bm = *self.tables.pat_binding_modes().get(pat.hir_id)
567                                                          .expect("missing binding mode");
568                 let (mutability, mode) = match bm {
569                     ty::BindByValue(hir::MutMutable) =>
570                         (Mutability::Mut, BindingMode::ByValue),
571                     ty::BindByValue(hir::MutImmutable) =>
572                         (Mutability::Not, BindingMode::ByValue),
573                     ty::BindByReference(hir::MutMutable) =>
574                         (Mutability::Not, BindingMode::ByRef(
575                             BorrowKind::Mut { allow_two_phase_borrow: false })),
576                     ty::BindByReference(hir::MutImmutable) =>
577                         (Mutability::Not, BindingMode::ByRef(
578                             BorrowKind::Shared)),
579                 };
580
581                 // A ref x pattern is the same node used for x, and as such it has
582                 // x's type, which is &T, where we want T (the type being matched).
583                 if let ty::BindByReference(_) = bm {
584                     if let ty::Ref(_, rty, _) = ty.sty {
585                         ty = rty;
586                     } else {
587                         bug!("`ref {}` has wrong type {}", ident, ty);
588                     }
589                 }
590
591                 PatternKind::Binding {
592                     mutability,
593                     mode,
594                     name: ident.name,
595                     var: id,
596                     ty: var_ty,
597                     subpattern: self.lower_opt_pattern(sub),
598                 }
599             }
600
601             PatKind::TupleStruct(ref qpath, ref subpatterns, ddpos) => {
602                 let def = self.tables.qpath_def(qpath, pat.hir_id);
603                 let adt_def = match ty.sty {
604                     ty::Adt(adt_def, _) => adt_def,
605                     ty::Error => { // Avoid ICE (#50585)
606                         return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
607                     }
608                     _ => span_bug!(pat.span,
609                                    "tuple struct pattern not applied to an ADT {:?}",
610                                    ty),
611                 };
612                 let variant_def = adt_def.variant_of_def(def);
613
614                 let subpatterns =
615                         subpatterns.iter()
616                                    .enumerate_and_adjust(variant_def.fields.len(), ddpos)
617                                    .map(|(i, field)| FieldPattern {
618                                        field: Field::new(i),
619                                        pattern: self.lower_pattern(field),
620                                    })
621                     .collect();
622
623                 self.lower_variant_or_leaf(def, pat.hir_id, pat.span, ty, subpatterns)
624             }
625
626             PatKind::Struct(ref qpath, ref fields, _) => {
627                 let def = self.tables.qpath_def(qpath, pat.hir_id);
628                 let subpatterns =
629                     fields.iter()
630                           .map(|field| {
631                               FieldPattern {
632                                   field: Field::new(self.tcx.field_index(field.node.hir_id,
633                                                                          self.tables)),
634                                   pattern: self.lower_pattern(&field.node.pat),
635                               }
636                           })
637                           .collect();
638
639                 self.lower_variant_or_leaf(def, pat.hir_id, pat.span, ty, subpatterns)
640             }
641         };
642
643         Pattern {
644             span: pat.span,
645             ty,
646             kind: Box::new(kind),
647         }
648     }
649
650     fn lower_patterns(&mut self, pats: &'tcx [P<hir::Pat>]) -> Vec<Pattern<'tcx>> {
651         pats.iter().map(|p| self.lower_pattern(p)).collect()
652     }
653
654     fn lower_opt_pattern(&mut self, pat: &'tcx Option<P<hir::Pat>>) -> Option<Pattern<'tcx>>
655     {
656         pat.as_ref().map(|p| self.lower_pattern(p))
657     }
658
659     fn flatten_nested_slice_patterns(
660         &mut self,
661         prefix: Vec<Pattern<'tcx>>,
662         slice: Option<Pattern<'tcx>>,
663         suffix: Vec<Pattern<'tcx>>)
664         -> (Vec<Pattern<'tcx>>, Option<Pattern<'tcx>>, Vec<Pattern<'tcx>>)
665     {
666         let orig_slice = match slice {
667             Some(orig_slice) => orig_slice,
668             None => return (prefix, slice, suffix)
669         };
670         let orig_prefix = prefix;
671         let orig_suffix = suffix;
672
673         // dance because of intentional borrow-checker stupidity.
674         let kind = *orig_slice.kind;
675         match kind {
676             PatternKind::Slice { prefix, slice, mut suffix } |
677             PatternKind::Array { prefix, slice, mut suffix } => {
678                 let mut orig_prefix = orig_prefix;
679
680                 orig_prefix.extend(prefix);
681                 suffix.extend(orig_suffix);
682
683                 (orig_prefix, slice, suffix)
684             }
685             _ => {
686                 (orig_prefix, Some(Pattern {
687                     kind: box kind, ..orig_slice
688                 }), orig_suffix)
689             }
690         }
691     }
692
693     fn slice_or_array_pattern(
694         &mut self,
695         span: Span,
696         ty: Ty<'tcx>,
697         prefix: &'tcx [P<hir::Pat>],
698         slice: &'tcx Option<P<hir::Pat>>,
699         suffix: &'tcx [P<hir::Pat>])
700         -> PatternKind<'tcx>
701     {
702         let prefix = self.lower_patterns(prefix);
703         let slice = self.lower_opt_pattern(slice);
704         let suffix = self.lower_patterns(suffix);
705         let (prefix, slice, suffix) =
706             self.flatten_nested_slice_patterns(prefix, slice, suffix);
707
708         match ty.sty {
709             ty::Slice(..) => {
710                 // matching a slice or fixed-length array
711                 PatternKind::Slice { prefix: prefix, slice: slice, suffix: suffix }
712             }
713
714             ty::Array(_, len) => {
715                 // fixed-length array
716                 let len = len.unwrap_usize(self.tcx);
717                 assert!(len >= prefix.len() as u64 + suffix.len() as u64);
718                 PatternKind::Array { prefix: prefix, slice: slice, suffix: suffix }
719             }
720
721             _ => {
722                 span_bug!(span, "bad slice pattern type {:?}", ty);
723             }
724         }
725     }
726
727     fn lower_variant_or_leaf(
728         &mut self,
729         def: Def,
730         hir_id: hir::HirId,
731         span: Span,
732         ty: Ty<'tcx>,
733         subpatterns: Vec<FieldPattern<'tcx>>,
734     ) -> PatternKind<'tcx> {
735         let def = match def {
736             Def::Ctor(variant_ctor_id, CtorOf::Variant, ..) => {
737                 let variant_id = self.tcx.parent(variant_ctor_id).unwrap();
738                 Def::Variant(variant_id)
739             },
740             def => def,
741         };
742
743         let mut kind = match def {
744             Def::Variant(variant_id) => {
745                 let enum_id = self.tcx.parent(variant_id).unwrap();
746                 let adt_def = self.tcx.adt_def(enum_id);
747                 if adt_def.is_enum() {
748                     let substs = match ty.sty {
749                         ty::Adt(_, substs) |
750                         ty::FnDef(_, substs) => substs,
751                         ty::Error => {  // Avoid ICE (#50585)
752                             return PatternKind::Wild;
753                         }
754                         _ => bug!("inappropriate type for def: {:?}", ty),
755                     };
756                     PatternKind::Variant {
757                         adt_def,
758                         substs,
759                         variant_index: adt_def.variant_index_with_id(variant_id),
760                         subpatterns,
761                     }
762                 } else {
763                     PatternKind::Leaf { subpatterns }
764                 }
765             }
766
767             Def::Struct(..) | Def::Ctor(_, CtorOf::Struct, ..) | Def::Union(..) |
768             Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) => {
769                 PatternKind::Leaf { subpatterns }
770             }
771
772             _ => {
773                 self.errors.push(PatternError::NonConstPath(span));
774                 PatternKind::Wild
775             }
776         };
777
778         if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) {
779             debug!("lower_variant_or_leaf: kind={:?} user_ty={:?} span={:?}", kind, user_ty, span);
780             kind = PatternKind::AscribeUserType {
781                 subpattern: Pattern {
782                     span,
783                     ty,
784                     kind: Box::new(kind),
785                 },
786                 ascription: Ascription {
787                     user_ty: PatternTypeProjection::from_user_type(user_ty),
788                     user_ty_span: span,
789                     variance: ty::Variance::Covariant,
790                 },
791             };
792         }
793
794         kind
795     }
796
797     /// Takes a HIR Path. If the path is a constant, evaluates it and feeds
798     /// it to `const_to_pat`. Any other path (like enum variants without fields)
799     /// is converted to the corresponding pattern via `lower_variant_or_leaf`.
800     fn lower_path(&mut self,
801                   qpath: &hir::QPath,
802                   id: hir::HirId,
803                   span: Span)
804                   -> Pattern<'tcx> {
805         let ty = self.tables.node_type(id);
806         let def = self.tables.qpath_def(qpath, id);
807         let is_associated_const = match def {
808             Def::AssociatedConst(_) => true,
809             _ => false,
810         };
811         let kind = match def {
812             Def::Const(def_id) | Def::AssociatedConst(def_id) => {
813                 let substs = self.tables.node_substs(id);
814                 match ty::Instance::resolve(
815                     self.tcx,
816                     self.param_env,
817                     def_id,
818                     substs,
819                 ) {
820                     Some(instance) => {
821                         let cid = GlobalId {
822                             instance,
823                             promoted: None,
824                         };
825                         match self.tcx.at(span).const_eval(self.param_env.and(cid)) {
826                             Ok(value) => {
827                                 let pattern = self.const_to_pat(instance, value, id, span);
828                                 if !is_associated_const {
829                                     return pattern;
830                                 }
831
832                                 let user_provided_types = self.tables().user_provided_types();
833                                 return if let Some(u_ty) = user_provided_types.get(id) {
834                                     let user_ty = PatternTypeProjection::from_user_type(*u_ty);
835                                     Pattern {
836                                         span,
837                                         kind: Box::new(
838                                             PatternKind::AscribeUserType {
839                                                 subpattern: pattern,
840                                                 ascription: Ascription {
841                                                     /// Note that use `Contravariant` here. See the
842                                                     /// `variance` field documentation for details.
843                                                     variance: ty::Variance::Contravariant,
844                                                     user_ty,
845                                                     user_ty_span: span,
846                                                 },
847                                             }
848                                         ),
849                                         ty: value.ty,
850                                     }
851                                 } else {
852                                     pattern
853                                 }
854                             },
855                             Err(_) => {
856                                 self.tcx.sess.span_err(
857                                     span,
858                                     "could not evaluate constant pattern",
859                                 );
860                                 PatternKind::Wild
861                             }
862                         }
863                     },
864                     None => {
865                         self.errors.push(if is_associated_const {
866                             PatternError::AssociatedConstInPattern(span)
867                         } else {
868                             PatternError::StaticInPattern(span)
869                         });
870                         PatternKind::Wild
871                     },
872                 }
873             }
874             _ => self.lower_variant_or_leaf(def, id, span, ty, vec![]),
875         };
876
877         Pattern {
878             span,
879             ty,
880             kind: Box::new(kind),
881         }
882     }
883
884     /// Converts literals, paths and negation of literals to patterns.
885     /// The special case for negation exists to allow things like `-128_i8`
886     /// which would overflow if we tried to evaluate `128_i8` and then negate
887     /// afterwards.
888     fn lower_lit(&mut self, expr: &'tcx hir::Expr) -> PatternKind<'tcx> {
889         match expr.node {
890             hir::ExprKind::Lit(ref lit) => {
891                 let ty = self.tables.expr_ty(expr);
892                 match lit_to_const(&lit.node, self.tcx, ty, false) {
893                     Ok(val) => {
894                         let instance = ty::Instance::new(
895                             self.tables.local_id_root.expect("literal outside any scope"),
896                             self.substs,
897                         );
898                         *self.const_to_pat(instance, val, expr.hir_id, lit.span).kind
899                     },
900                     Err(LitToConstError::UnparseableFloat) => {
901                         self.errors.push(PatternError::FloatBug);
902                         PatternKind::Wild
903                     },
904                     Err(LitToConstError::Reported) => PatternKind::Wild,
905                 }
906             },
907             hir::ExprKind::Path(ref qpath) => *self.lower_path(qpath, expr.hir_id, expr.span).kind,
908             hir::ExprKind::Unary(hir::UnNeg, ref expr) => {
909                 let ty = self.tables.expr_ty(expr);
910                 let lit = match expr.node {
911                     hir::ExprKind::Lit(ref lit) => lit,
912                     _ => span_bug!(expr.span, "not a literal: {:?}", expr),
913                 };
914                 match lit_to_const(&lit.node, self.tcx, ty, true) {
915                     Ok(val) => {
916                         let instance = ty::Instance::new(
917                             self.tables.local_id_root.expect("literal outside any scope"),
918                             self.substs,
919                         );
920                         *self.const_to_pat(instance, val, expr.hir_id, lit.span).kind
921                     },
922                     Err(LitToConstError::UnparseableFloat) => {
923                         self.errors.push(PatternError::FloatBug);
924                         PatternKind::Wild
925                     },
926                     Err(LitToConstError::Reported) => PatternKind::Wild,
927                 }
928             }
929             _ => span_bug!(expr.span, "not a literal: {:?}", expr),
930         }
931     }
932
933     /// Converts an evaluated constant to a pattern (if possible).
934     /// This means aggregate values (like structs and enums) are converted
935     /// to a pattern that matches the value (as if you'd compared via equality).
936     fn const_to_pat(
937         &self,
938         instance: ty::Instance<'tcx>,
939         cv: ty::Const<'tcx>,
940         id: hir::HirId,
941         span: Span,
942     ) -> Pattern<'tcx> {
943         debug!("const_to_pat: cv={:#?} id={:?}", cv, id);
944         let adt_subpattern = |i, variant_opt| {
945             let field = Field::new(i);
946             let val = const_field(self.tcx, self.param_env, variant_opt, field, cv);
947             self.const_to_pat(instance, val, id, span)
948         };
949         let adt_subpatterns = |n, variant_opt| {
950             (0..n).map(|i| {
951                 let field = Field::new(i);
952                 FieldPattern {
953                     field,
954                     pattern: adt_subpattern(i, variant_opt),
955                 }
956             }).collect::<Vec<_>>()
957         };
958         debug!("const_to_pat: cv.ty={:?} span={:?}", cv.ty, span);
959         let kind = match cv.ty.sty {
960             ty::Float(_) => {
961                 self.tcx.lint_hir(
962                     ::rustc::lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
963                     id,
964                     span,
965                     "floating-point types cannot be used in patterns",
966                 );
967                 PatternKind::Constant {
968                     value: cv,
969                 }
970             }
971             ty::Adt(adt_def, _) if adt_def.is_union() => {
972                 // Matching on union fields is unsafe, we can't hide it in constants
973                 self.tcx.sess.span_err(span, "cannot use unions in constant patterns");
974                 PatternKind::Wild
975             }
976             ty::Adt(adt_def, _) if !self.tcx.has_attr(adt_def.did, "structural_match") => {
977                 let path = self.tcx.def_path_str(adt_def.did);
978                 let msg = format!(
979                     "to use a constant of type `{}` in a pattern, \
980                      `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
981                     path,
982                     path,
983                 );
984                 self.tcx.sess.span_err(span, &msg);
985                 PatternKind::Wild
986             }
987             ty::Ref(_, ty::TyS { sty: ty::Adt(adt_def, _), .. }, _)
988             if !self.tcx.has_attr(adt_def.did, "structural_match") => {
989                 // HACK(estebank): Side-step ICE #53708, but anything other than erroring here
990                 // would be wrong. Returnging `PatternKind::Wild` is not technically correct.
991                 let path = self.tcx.def_path_str(adt_def.did);
992                 let msg = format!(
993                     "to use a constant of type `{}` in a pattern, \
994                      `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
995                     path,
996                     path,
997                 );
998                 self.tcx.sess.span_err(span, &msg);
999                 PatternKind::Wild
1000             }
1001             ty::Adt(adt_def, substs) if adt_def.is_enum() => {
1002                 let variant_index = const_variant_index(self.tcx, self.param_env, cv);
1003                 let subpatterns = adt_subpatterns(
1004                     adt_def.variants[variant_index].fields.len(),
1005                     Some(variant_index),
1006                 );
1007                 PatternKind::Variant {
1008                     adt_def,
1009                     substs,
1010                     variant_index,
1011                     subpatterns,
1012                 }
1013             }
1014             ty::Adt(adt_def, _) => {
1015                 let struct_var = adt_def.non_enum_variant();
1016                 PatternKind::Leaf {
1017                     subpatterns: adt_subpatterns(struct_var.fields.len(), None),
1018                 }
1019             }
1020             ty::Tuple(fields) => {
1021                 PatternKind::Leaf {
1022                     subpatterns: adt_subpatterns(fields.len(), None),
1023                 }
1024             }
1025             ty::Array(_, n) => {
1026                 PatternKind::Array {
1027                     prefix: (0..n.unwrap_usize(self.tcx))
1028                         .map(|i| adt_subpattern(i as usize, None))
1029                         .collect(),
1030                     slice: None,
1031                     suffix: Vec::new(),
1032                 }
1033             }
1034             _ => {
1035                 PatternKind::Constant {
1036                     value: cv,
1037                 }
1038             }
1039         };
1040
1041         Pattern {
1042             span,
1043             ty: cv.ty,
1044             kind: Box::new(kind),
1045         }
1046     }
1047 }
1048
1049 impl UserAnnotatedTyHelpers<'tcx, 'tcx> for PatternContext<'_, 'tcx> {
1050     fn tcx(&self) -> TyCtxt<'_, 'tcx, 'tcx> {
1051         self.tcx
1052     }
1053
1054     fn tables(&self) -> &ty::TypeckTables<'tcx> {
1055         self.tables
1056     }
1057 }
1058
1059
1060 pub trait PatternFoldable<'tcx> : Sized {
1061     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
1062         self.super_fold_with(folder)
1063     }
1064
1065     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self;
1066 }
1067
1068 pub trait PatternFolder<'tcx> : Sized {
1069     fn fold_pattern(&mut self, pattern: &Pattern<'tcx>) -> Pattern<'tcx> {
1070         pattern.super_fold_with(self)
1071     }
1072
1073     fn fold_pattern_kind(&mut self, kind: &PatternKind<'tcx>) -> PatternKind<'tcx> {
1074         kind.super_fold_with(self)
1075     }
1076 }
1077
1078
1079 impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Box<T> {
1080     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
1081         let content: T = (**self).fold_with(folder);
1082         box content
1083     }
1084 }
1085
1086 impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Vec<T> {
1087     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
1088         self.iter().map(|t| t.fold_with(folder)).collect()
1089     }
1090 }
1091
1092 impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Option<T> {
1093     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self{
1094         self.as_ref().map(|t| t.fold_with(folder))
1095     }
1096 }
1097
1098 macro_rules! CloneImpls {
1099     (<$lt_tcx:tt> $($ty:ty),+) => {
1100         $(
1101             impl<$lt_tcx> PatternFoldable<$lt_tcx> for $ty {
1102                 fn super_fold_with<F: PatternFolder<$lt_tcx>>(&self, _: &mut F) -> Self {
1103                     Clone::clone(self)
1104                 }
1105             }
1106         )+
1107     }
1108 }
1109
1110 CloneImpls!{ <'tcx>
1111     Span, Field, Mutability, ast::Name, hir::HirId, usize, ty::Const<'tcx>,
1112     Region<'tcx>, Ty<'tcx>, BindingMode, &'tcx AdtDef,
1113     SubstsRef<'tcx>, &'tcx Kind<'tcx>, UserType<'tcx>,
1114     UserTypeProjection, PatternTypeProjection<'tcx>
1115 }
1116
1117 impl<'tcx> PatternFoldable<'tcx> for FieldPattern<'tcx> {
1118     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
1119         FieldPattern {
1120             field: self.field.fold_with(folder),
1121             pattern: self.pattern.fold_with(folder)
1122         }
1123     }
1124 }
1125
1126 impl<'tcx> PatternFoldable<'tcx> for Pattern<'tcx> {
1127     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
1128         folder.fold_pattern(self)
1129     }
1130
1131     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
1132         Pattern {
1133             ty: self.ty.fold_with(folder),
1134             span: self.span.fold_with(folder),
1135             kind: self.kind.fold_with(folder)
1136         }
1137     }
1138 }
1139
1140 impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> {
1141     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
1142         folder.fold_pattern_kind(self)
1143     }
1144
1145     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
1146         match *self {
1147             PatternKind::Wild => PatternKind::Wild,
1148             PatternKind::AscribeUserType {
1149                 ref subpattern,
1150                 ascription: Ascription {
1151                     variance,
1152                     ref user_ty,
1153                     user_ty_span,
1154                 },
1155             } => PatternKind::AscribeUserType {
1156                 subpattern: subpattern.fold_with(folder),
1157                 ascription: Ascription {
1158                     user_ty: user_ty.fold_with(folder),
1159                     variance,
1160                     user_ty_span,
1161                 },
1162             },
1163             PatternKind::Binding {
1164                 mutability,
1165                 name,
1166                 mode,
1167                 var,
1168                 ty,
1169                 ref subpattern,
1170             } => PatternKind::Binding {
1171                 mutability: mutability.fold_with(folder),
1172                 name: name.fold_with(folder),
1173                 mode: mode.fold_with(folder),
1174                 var: var.fold_with(folder),
1175                 ty: ty.fold_with(folder),
1176                 subpattern: subpattern.fold_with(folder),
1177             },
1178             PatternKind::Variant {
1179                 adt_def,
1180                 substs,
1181                 variant_index,
1182                 ref subpatterns,
1183             } => PatternKind::Variant {
1184                 adt_def: adt_def.fold_with(folder),
1185                 substs: substs.fold_with(folder),
1186                 variant_index,
1187                 subpatterns: subpatterns.fold_with(folder)
1188             },
1189             PatternKind::Leaf {
1190                 ref subpatterns,
1191             } => PatternKind::Leaf {
1192                 subpatterns: subpatterns.fold_with(folder),
1193             },
1194             PatternKind::Deref {
1195                 ref subpattern,
1196             } => PatternKind::Deref {
1197                 subpattern: subpattern.fold_with(folder),
1198             },
1199             PatternKind::Constant {
1200                 value
1201             } => PatternKind::Constant {
1202                 value: value.fold_with(folder)
1203             },
1204             PatternKind::Range(PatternRange {
1205                 lo,
1206                 hi,
1207                 ty,
1208                 end,
1209             }) => PatternKind::Range(PatternRange {
1210                 lo: lo.fold_with(folder),
1211                 hi: hi.fold_with(folder),
1212                 ty: ty.fold_with(folder),
1213                 end,
1214             }),
1215             PatternKind::Slice {
1216                 ref prefix,
1217                 ref slice,
1218                 ref suffix,
1219             } => PatternKind::Slice {
1220                 prefix: prefix.fold_with(folder),
1221                 slice: slice.fold_with(folder),
1222                 suffix: suffix.fold_with(folder)
1223             },
1224             PatternKind::Array {
1225                 ref prefix,
1226                 ref slice,
1227                 ref suffix
1228             } => PatternKind::Array {
1229                 prefix: prefix.fold_with(folder),
1230                 slice: slice.fold_with(folder),
1231                 suffix: suffix.fold_with(folder)
1232             },
1233         }
1234     }
1235 }
1236
1237 pub fn compare_const_vals<'a, 'gcx, 'tcx>(
1238     tcx: TyCtxt<'a, 'gcx, 'tcx>,
1239     a: ty::Const<'tcx>,
1240     b: ty::Const<'tcx>,
1241     ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
1242 ) -> Option<Ordering> {
1243     trace!("compare_const_vals: {:?}, {:?}", a, b);
1244
1245     let from_bool = |v: bool| {
1246         if v {
1247             Some(Ordering::Equal)
1248         } else {
1249             None
1250         }
1251     };
1252
1253     let fallback = || from_bool(a == b);
1254
1255     // Use the fallback if any type differs
1256     if a.ty != b.ty || a.ty != ty.value {
1257         return fallback();
1258     }
1259
1260     // FIXME: This should use assert_bits(ty) instead of use_bits
1261     // but triggers possibly bugs due to mismatching of arrays and slices
1262     if let (Some(a), Some(b)) = (a.to_bits(tcx, ty), b.to_bits(tcx, ty)) {
1263         use ::rustc_apfloat::Float;
1264         return match ty.value.sty {
1265             ty::Float(ast::FloatTy::F32) => {
1266                 let l = ::rustc_apfloat::ieee::Single::from_bits(a);
1267                 let r = ::rustc_apfloat::ieee::Single::from_bits(b);
1268                 l.partial_cmp(&r)
1269             }
1270             ty::Float(ast::FloatTy::F64) => {
1271                 let l = ::rustc_apfloat::ieee::Double::from_bits(a);
1272                 let r = ::rustc_apfloat::ieee::Double::from_bits(b);
1273                 l.partial_cmp(&r)
1274             }
1275             ty::Int(ity) => {
1276                 use rustc::ty::layout::{Integer, IntegerExt};
1277                 use syntax::attr::SignedInt;
1278                 let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
1279                 let a = sign_extend(a, size);
1280                 let b = sign_extend(b, size);
1281                 Some((a as i128).cmp(&(b as i128)))
1282             }
1283             _ => Some(a.cmp(&b)),
1284         }
1285     }
1286
1287     if let ty::Str = ty.value.sty {
1288         match (a.val, b.val) {
1289             (
1290                 ConstValue::Slice(
1291                     Scalar::Ptr(ptr_a),
1292                     len_a,
1293                 ),
1294                 ConstValue::Slice(
1295                     Scalar::Ptr(ptr_b),
1296                     len_b,
1297                 ),
1298             ) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => {
1299                 if len_a == len_b {
1300                     let map = tcx.alloc_map.lock();
1301                     let alloc_a = map.unwrap_memory(ptr_a.alloc_id);
1302                     let alloc_b = map.unwrap_memory(ptr_b.alloc_id);
1303                     if alloc_a.bytes.len() as u64 == len_a {
1304                         return from_bool(alloc_a == alloc_b);
1305                     }
1306                 }
1307             }
1308             _ => (),
1309         }
1310     }
1311
1312     fallback()
1313 }