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