]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/hair/pattern/mod.rs
Rollup merge of #60527 - davidtwco:issue-60518, r=cramertj
[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, Res, DefKind, 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 res = self.tables.qpath_res(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_res(res);
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(res, pat.hir_id, pat.span, ty, subpatterns)
624             }
625
626             PatKind::Struct(ref qpath, ref fields, _) => {
627                 let res = self.tables.qpath_res(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(res, 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         res: Res,
730         hir_id: hir::HirId,
731         span: Span,
732         ty: Ty<'tcx>,
733         subpatterns: Vec<FieldPattern<'tcx>>,
734     ) -> PatternKind<'tcx> {
735         let res = match res {
736             Res::Def(DefKind::Ctor(CtorOf::Variant, ..), variant_ctor_id) => {
737                 let variant_id = self.tcx.parent(variant_ctor_id).unwrap();
738                 Res::Def(DefKind::Variant, variant_id)
739             },
740             res => res,
741         };
742
743         let mut kind = match res {
744             Res::Def(DefKind::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             Res::Def(DefKind::Struct, _)
768             | Res::Def(DefKind::Ctor(CtorOf::Struct, ..), _)
769             | Res::Def(DefKind::Union, _)
770             | Res::Def(DefKind::TyAlias, _)
771             | Res::Def(DefKind::AssociatedTy, _)
772             | Res::SelfTy(..)
773             | Res::SelfCtor(..) => {
774                 PatternKind::Leaf { subpatterns }
775             }
776
777             _ => {
778                 self.errors.push(PatternError::NonConstPath(span));
779                 PatternKind::Wild
780             }
781         };
782
783         if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) {
784             debug!("lower_variant_or_leaf: kind={:?} user_ty={:?} span={:?}", kind, user_ty, span);
785             kind = PatternKind::AscribeUserType {
786                 subpattern: Pattern {
787                     span,
788                     ty,
789                     kind: Box::new(kind),
790                 },
791                 ascription: Ascription {
792                     user_ty: PatternTypeProjection::from_user_type(user_ty),
793                     user_ty_span: span,
794                     variance: ty::Variance::Covariant,
795                 },
796             };
797         }
798
799         kind
800     }
801
802     /// Takes a HIR Path. If the path is a constant, evaluates it and feeds
803     /// it to `const_to_pat`. Any other path (like enum variants without fields)
804     /// is converted to the corresponding pattern via `lower_variant_or_leaf`.
805     fn lower_path(&mut self,
806                   qpath: &hir::QPath,
807                   id: hir::HirId,
808                   span: Span)
809                   -> Pattern<'tcx> {
810         let ty = self.tables.node_type(id);
811         let res = self.tables.qpath_res(qpath, id);
812         let is_associated_const = match res {
813             Res::Def(DefKind::AssociatedConst, _) => true,
814             _ => false,
815         };
816         let kind = match res {
817             Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssociatedConst, def_id) => {
818                 let substs = self.tables.node_substs(id);
819                 match ty::Instance::resolve(
820                     self.tcx,
821                     self.param_env,
822                     def_id,
823                     substs,
824                 ) {
825                     Some(instance) => {
826                         let cid = GlobalId {
827                             instance,
828                             promoted: None,
829                         };
830                         match self.tcx.at(span).const_eval(self.param_env.and(cid)) {
831                             Ok(value) => {
832                                 let pattern = self.const_to_pat(instance, value, id, span);
833                                 if !is_associated_const {
834                                     return pattern;
835                                 }
836
837                                 let user_provided_types = self.tables().user_provided_types();
838                                 return if let Some(u_ty) = user_provided_types.get(id) {
839                                     let user_ty = PatternTypeProjection::from_user_type(*u_ty);
840                                     Pattern {
841                                         span,
842                                         kind: Box::new(
843                                             PatternKind::AscribeUserType {
844                                                 subpattern: pattern,
845                                                 ascription: Ascription {
846                                                     /// Note that use `Contravariant` here. See the
847                                                     /// `variance` field documentation for details.
848                                                     variance: ty::Variance::Contravariant,
849                                                     user_ty,
850                                                     user_ty_span: span,
851                                                 },
852                                             }
853                                         ),
854                                         ty: value.ty,
855                                     }
856                                 } else {
857                                     pattern
858                                 }
859                             },
860                             Err(_) => {
861                                 self.tcx.sess.span_err(
862                                     span,
863                                     "could not evaluate constant pattern",
864                                 );
865                                 PatternKind::Wild
866                             }
867                         }
868                     },
869                     None => {
870                         self.errors.push(if is_associated_const {
871                             PatternError::AssociatedConstInPattern(span)
872                         } else {
873                             PatternError::StaticInPattern(span)
874                         });
875                         PatternKind::Wild
876                     },
877                 }
878             }
879             _ => self.lower_variant_or_leaf(res, id, span, ty, vec![]),
880         };
881
882         Pattern {
883             span,
884             ty,
885             kind: Box::new(kind),
886         }
887     }
888
889     /// Converts literals, paths and negation of literals to patterns.
890     /// The special case for negation exists to allow things like `-128_i8`
891     /// which would overflow if we tried to evaluate `128_i8` and then negate
892     /// afterwards.
893     fn lower_lit(&mut self, expr: &'tcx hir::Expr) -> PatternKind<'tcx> {
894         match expr.node {
895             hir::ExprKind::Lit(ref lit) => {
896                 let ty = self.tables.expr_ty(expr);
897                 match lit_to_const(&lit.node, self.tcx, ty, false) {
898                     Ok(val) => {
899                         let instance = ty::Instance::new(
900                             self.tables.local_id_root.expect("literal outside any scope"),
901                             self.substs,
902                         );
903                         *self.const_to_pat(instance, val, expr.hir_id, lit.span).kind
904                     },
905                     Err(LitToConstError::UnparseableFloat) => {
906                         self.errors.push(PatternError::FloatBug);
907                         PatternKind::Wild
908                     },
909                     Err(LitToConstError::Reported) => PatternKind::Wild,
910                 }
911             },
912             hir::ExprKind::Path(ref qpath) => *self.lower_path(qpath, expr.hir_id, expr.span).kind,
913             hir::ExprKind::Unary(hir::UnNeg, ref expr) => {
914                 let ty = self.tables.expr_ty(expr);
915                 let lit = match expr.node {
916                     hir::ExprKind::Lit(ref lit) => lit,
917                     _ => span_bug!(expr.span, "not a literal: {:?}", expr),
918                 };
919                 match lit_to_const(&lit.node, self.tcx, ty, true) {
920                     Ok(val) => {
921                         let instance = ty::Instance::new(
922                             self.tables.local_id_root.expect("literal outside any scope"),
923                             self.substs,
924                         );
925                         *self.const_to_pat(instance, val, expr.hir_id, lit.span).kind
926                     },
927                     Err(LitToConstError::UnparseableFloat) => {
928                         self.errors.push(PatternError::FloatBug);
929                         PatternKind::Wild
930                     },
931                     Err(LitToConstError::Reported) => PatternKind::Wild,
932                 }
933             }
934             _ => span_bug!(expr.span, "not a literal: {:?}", expr),
935         }
936     }
937
938     /// Converts an evaluated constant to a pattern (if possible).
939     /// This means aggregate values (like structs and enums) are converted
940     /// to a pattern that matches the value (as if you'd compared via equality).
941     fn const_to_pat(
942         &self,
943         instance: ty::Instance<'tcx>,
944         cv: ty::Const<'tcx>,
945         id: hir::HirId,
946         span: Span,
947     ) -> Pattern<'tcx> {
948         debug!("const_to_pat: cv={:#?} id={:?}", cv, id);
949         let adt_subpattern = |i, variant_opt| {
950             let field = Field::new(i);
951             let val = const_field(self.tcx, self.param_env, variant_opt, field, cv);
952             self.const_to_pat(instance, val, id, span)
953         };
954         let adt_subpatterns = |n, variant_opt| {
955             (0..n).map(|i| {
956                 let field = Field::new(i);
957                 FieldPattern {
958                     field,
959                     pattern: adt_subpattern(i, variant_opt),
960                 }
961             }).collect::<Vec<_>>()
962         };
963         debug!("const_to_pat: cv.ty={:?} span={:?}", cv.ty, span);
964         let kind = match cv.ty.sty {
965             ty::Float(_) => {
966                 self.tcx.lint_hir(
967                     ::rustc::lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
968                     id,
969                     span,
970                     "floating-point types cannot be used in patterns",
971                 );
972                 PatternKind::Constant {
973                     value: cv,
974                 }
975             }
976             ty::Adt(adt_def, _) if adt_def.is_union() => {
977                 // Matching on union fields is unsafe, we can't hide it in constants
978                 self.tcx.sess.span_err(span, "cannot use unions in constant patterns");
979                 PatternKind::Wild
980             }
981             ty::Adt(adt_def, _) if !self.tcx.has_attr(adt_def.did, "structural_match") => {
982                 let path = self.tcx.def_path_str(adt_def.did);
983                 let msg = format!(
984                     "to use a constant of type `{}` in a pattern, \
985                      `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
986                     path,
987                     path,
988                 );
989                 self.tcx.sess.span_err(span, &msg);
990                 PatternKind::Wild
991             }
992             ty::Ref(_, ty::TyS { sty: ty::Adt(adt_def, _), .. }, _)
993             if !self.tcx.has_attr(adt_def.did, "structural_match") => {
994                 // HACK(estebank): Side-step ICE #53708, but anything other than erroring here
995                 // would be wrong. Returnging `PatternKind::Wild` is not technically correct.
996                 let path = self.tcx.def_path_str(adt_def.did);
997                 let msg = format!(
998                     "to use a constant of type `{}` in a pattern, \
999                      `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
1000                     path,
1001                     path,
1002                 );
1003                 self.tcx.sess.span_err(span, &msg);
1004                 PatternKind::Wild
1005             }
1006             ty::Adt(adt_def, substs) if adt_def.is_enum() => {
1007                 let variant_index = const_variant_index(self.tcx, self.param_env, cv);
1008                 let subpatterns = adt_subpatterns(
1009                     adt_def.variants[variant_index].fields.len(),
1010                     Some(variant_index),
1011                 );
1012                 PatternKind::Variant {
1013                     adt_def,
1014                     substs,
1015                     variant_index,
1016                     subpatterns,
1017                 }
1018             }
1019             ty::Adt(adt_def, _) => {
1020                 let struct_var = adt_def.non_enum_variant();
1021                 PatternKind::Leaf {
1022                     subpatterns: adt_subpatterns(struct_var.fields.len(), None),
1023                 }
1024             }
1025             ty::Tuple(fields) => {
1026                 PatternKind::Leaf {
1027                     subpatterns: adt_subpatterns(fields.len(), None),
1028                 }
1029             }
1030             ty::Array(_, n) => {
1031                 PatternKind::Array {
1032                     prefix: (0..n.unwrap_usize(self.tcx))
1033                         .map(|i| adt_subpattern(i as usize, None))
1034                         .collect(),
1035                     slice: None,
1036                     suffix: Vec::new(),
1037                 }
1038             }
1039             _ => {
1040                 PatternKind::Constant {
1041                     value: cv,
1042                 }
1043             }
1044         };
1045
1046         Pattern {
1047             span,
1048             ty: cv.ty,
1049             kind: Box::new(kind),
1050         }
1051     }
1052 }
1053
1054 impl UserAnnotatedTyHelpers<'tcx, 'tcx> for PatternContext<'_, 'tcx> {
1055     fn tcx(&self) -> TyCtxt<'_, 'tcx, 'tcx> {
1056         self.tcx
1057     }
1058
1059     fn tables(&self) -> &ty::TypeckTables<'tcx> {
1060         self.tables
1061     }
1062 }
1063
1064
1065 pub trait PatternFoldable<'tcx> : Sized {
1066     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
1067         self.super_fold_with(folder)
1068     }
1069
1070     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self;
1071 }
1072
1073 pub trait PatternFolder<'tcx> : Sized {
1074     fn fold_pattern(&mut self, pattern: &Pattern<'tcx>) -> Pattern<'tcx> {
1075         pattern.super_fold_with(self)
1076     }
1077
1078     fn fold_pattern_kind(&mut self, kind: &PatternKind<'tcx>) -> PatternKind<'tcx> {
1079         kind.super_fold_with(self)
1080     }
1081 }
1082
1083
1084 impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Box<T> {
1085     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
1086         let content: T = (**self).fold_with(folder);
1087         box content
1088     }
1089 }
1090
1091 impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Vec<T> {
1092     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
1093         self.iter().map(|t| t.fold_with(folder)).collect()
1094     }
1095 }
1096
1097 impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Option<T> {
1098     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self{
1099         self.as_ref().map(|t| t.fold_with(folder))
1100     }
1101 }
1102
1103 macro_rules! CloneImpls {
1104     (<$lt_tcx:tt> $($ty:ty),+) => {
1105         $(
1106             impl<$lt_tcx> PatternFoldable<$lt_tcx> for $ty {
1107                 fn super_fold_with<F: PatternFolder<$lt_tcx>>(&self, _: &mut F) -> Self {
1108                     Clone::clone(self)
1109                 }
1110             }
1111         )+
1112     }
1113 }
1114
1115 CloneImpls!{ <'tcx>
1116     Span, Field, Mutability, ast::Name, hir::HirId, usize, ty::Const<'tcx>,
1117     Region<'tcx>, Ty<'tcx>, BindingMode, &'tcx AdtDef,
1118     SubstsRef<'tcx>, &'tcx Kind<'tcx>, UserType<'tcx>,
1119     UserTypeProjection, PatternTypeProjection<'tcx>
1120 }
1121
1122 impl<'tcx> PatternFoldable<'tcx> for FieldPattern<'tcx> {
1123     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
1124         FieldPattern {
1125             field: self.field.fold_with(folder),
1126             pattern: self.pattern.fold_with(folder)
1127         }
1128     }
1129 }
1130
1131 impl<'tcx> PatternFoldable<'tcx> for Pattern<'tcx> {
1132     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
1133         folder.fold_pattern(self)
1134     }
1135
1136     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
1137         Pattern {
1138             ty: self.ty.fold_with(folder),
1139             span: self.span.fold_with(folder),
1140             kind: self.kind.fold_with(folder)
1141         }
1142     }
1143 }
1144
1145 impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> {
1146     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
1147         folder.fold_pattern_kind(self)
1148     }
1149
1150     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
1151         match *self {
1152             PatternKind::Wild => PatternKind::Wild,
1153             PatternKind::AscribeUserType {
1154                 ref subpattern,
1155                 ascription: Ascription {
1156                     variance,
1157                     ref user_ty,
1158                     user_ty_span,
1159                 },
1160             } => PatternKind::AscribeUserType {
1161                 subpattern: subpattern.fold_with(folder),
1162                 ascription: Ascription {
1163                     user_ty: user_ty.fold_with(folder),
1164                     variance,
1165                     user_ty_span,
1166                 },
1167             },
1168             PatternKind::Binding {
1169                 mutability,
1170                 name,
1171                 mode,
1172                 var,
1173                 ty,
1174                 ref subpattern,
1175             } => PatternKind::Binding {
1176                 mutability: mutability.fold_with(folder),
1177                 name: name.fold_with(folder),
1178                 mode: mode.fold_with(folder),
1179                 var: var.fold_with(folder),
1180                 ty: ty.fold_with(folder),
1181                 subpattern: subpattern.fold_with(folder),
1182             },
1183             PatternKind::Variant {
1184                 adt_def,
1185                 substs,
1186                 variant_index,
1187                 ref subpatterns,
1188             } => PatternKind::Variant {
1189                 adt_def: adt_def.fold_with(folder),
1190                 substs: substs.fold_with(folder),
1191                 variant_index,
1192                 subpatterns: subpatterns.fold_with(folder)
1193             },
1194             PatternKind::Leaf {
1195                 ref subpatterns,
1196             } => PatternKind::Leaf {
1197                 subpatterns: subpatterns.fold_with(folder),
1198             },
1199             PatternKind::Deref {
1200                 ref subpattern,
1201             } => PatternKind::Deref {
1202                 subpattern: subpattern.fold_with(folder),
1203             },
1204             PatternKind::Constant {
1205                 value
1206             } => PatternKind::Constant {
1207                 value: value.fold_with(folder)
1208             },
1209             PatternKind::Range(PatternRange {
1210                 lo,
1211                 hi,
1212                 ty,
1213                 end,
1214             }) => PatternKind::Range(PatternRange {
1215                 lo: lo.fold_with(folder),
1216                 hi: hi.fold_with(folder),
1217                 ty: ty.fold_with(folder),
1218                 end,
1219             }),
1220             PatternKind::Slice {
1221                 ref prefix,
1222                 ref slice,
1223                 ref suffix,
1224             } => PatternKind::Slice {
1225                 prefix: prefix.fold_with(folder),
1226                 slice: slice.fold_with(folder),
1227                 suffix: suffix.fold_with(folder)
1228             },
1229             PatternKind::Array {
1230                 ref prefix,
1231                 ref slice,
1232                 ref suffix
1233             } => PatternKind::Array {
1234                 prefix: prefix.fold_with(folder),
1235                 slice: slice.fold_with(folder),
1236                 suffix: suffix.fold_with(folder)
1237             },
1238         }
1239     }
1240 }
1241
1242 pub fn compare_const_vals<'a, 'gcx, 'tcx>(
1243     tcx: TyCtxt<'a, 'gcx, 'tcx>,
1244     a: ty::Const<'tcx>,
1245     b: ty::Const<'tcx>,
1246     ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
1247 ) -> Option<Ordering> {
1248     trace!("compare_const_vals: {:?}, {:?}", a, b);
1249
1250     let from_bool = |v: bool| {
1251         if v {
1252             Some(Ordering::Equal)
1253         } else {
1254             None
1255         }
1256     };
1257
1258     let fallback = || from_bool(a == b);
1259
1260     // Use the fallback if any type differs
1261     if a.ty != b.ty || a.ty != ty.value {
1262         return fallback();
1263     }
1264
1265     // FIXME: This should use assert_bits(ty) instead of use_bits
1266     // but triggers possibly bugs due to mismatching of arrays and slices
1267     if let (Some(a), Some(b)) = (a.to_bits(tcx, ty), b.to_bits(tcx, ty)) {
1268         use ::rustc_apfloat::Float;
1269         return match ty.value.sty {
1270             ty::Float(ast::FloatTy::F32) => {
1271                 let l = ::rustc_apfloat::ieee::Single::from_bits(a);
1272                 let r = ::rustc_apfloat::ieee::Single::from_bits(b);
1273                 l.partial_cmp(&r)
1274             }
1275             ty::Float(ast::FloatTy::F64) => {
1276                 let l = ::rustc_apfloat::ieee::Double::from_bits(a);
1277                 let r = ::rustc_apfloat::ieee::Double::from_bits(b);
1278                 l.partial_cmp(&r)
1279             }
1280             ty::Int(ity) => {
1281                 use rustc::ty::layout::{Integer, IntegerExt};
1282                 use syntax::attr::SignedInt;
1283                 let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
1284                 let a = sign_extend(a, size);
1285                 let b = sign_extend(b, size);
1286                 Some((a as i128).cmp(&(b as i128)))
1287             }
1288             _ => Some(a.cmp(&b)),
1289         }
1290     }
1291
1292     if let ty::Str = ty.value.sty {
1293         match (a.val, b.val) {
1294             (
1295                 ConstValue::Slice(
1296                     Scalar::Ptr(ptr_a),
1297                     len_a,
1298                 ),
1299                 ConstValue::Slice(
1300                     Scalar::Ptr(ptr_b),
1301                     len_b,
1302                 ),
1303             ) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => {
1304                 if len_a == len_b {
1305                     let map = tcx.alloc_map.lock();
1306                     let alloc_a = map.unwrap_memory(ptr_a.alloc_id);
1307                     let alloc_b = map.unwrap_memory(ptr_b.alloc_id);
1308                     if alloc_a.bytes.len() as u64 == len_a {
1309                         return from_bool(alloc_a == alloc_b);
1310                     }
1311                 }
1312             }
1313             _ => (),
1314         }
1315     }
1316
1317     fallback()
1318 }