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