@@ -284,10 +284,9 @@ use super::{FieldPat, Pat, PatKind, PatRange};
284
284
285
285
use rustc_arena::TypedArena;
286
286
use rustc_attr::{SignedInt, UnsignedInt};
287
- use rustc_errors::ErrorReported;
288
287
use rustc_hir::def_id::DefId;
289
288
use rustc_hir::{HirId, RangeEnd};
290
- use rustc_middle::mir::interpret::{truncate, AllocId, ConstValue, Pointer, Scalar };
289
+ use rustc_middle::mir::interpret::{truncate, ConstValue};
291
290
use rustc_middle::mir::Field;
292
291
use rustc_middle::ty::layout::IntegerExt;
293
292
use rustc_middle::ty::{self, Const, Ty, TyCtxt};
@@ -296,84 +295,21 @@ use rustc_span::{Span, DUMMY_SP};
296
295
use rustc_target::abi::{Integer, Size, VariantIdx};
297
296
298
297
use smallvec::{smallvec, SmallVec};
299
- use std::borrow::Cow;
300
298
use std::cmp::{self, max, min, Ordering};
301
- use std::convert::TryInto;
302
299
use std::fmt;
303
300
use std::iter::{FromIterator, IntoIterator};
304
301
use std::ops::RangeInclusive;
305
302
306
- crate fn expand_pattern<'a, ' tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pat<'tcx>) -> Pat<'tcx> {
307
- LiteralExpander { tcx: cx.tcx } .fold_pattern(&pat)
303
+ crate fn expand_pattern<'tcx>(pat: Pat<'tcx>) -> Pat<'tcx> {
304
+ LiteralExpander.fold_pattern(&pat)
308
305
}
309
306
310
- struct LiteralExpander<'tcx> {
311
- tcx: TyCtxt<'tcx>,
312
- }
307
+ struct LiteralExpander;
313
308
314
- impl<'tcx> LiteralExpander<'tcx> {
315
- /// Derefs `val` and potentially unsizes the value if `crty` is an array and `rty` a slice.
316
- ///
317
- /// `crty` and `rty` can differ because you can use array constants in the presence of slice
318
- /// patterns. So the pattern may end up being a slice, but the constant is an array. We convert
319
- /// the array to a slice in that case.
320
- fn fold_const_value_deref(
321
- &mut self,
322
- val: ConstValue<'tcx>,
323
- // the pattern's pointee type
324
- rty: Ty<'tcx>,
325
- // the constant's pointee type
326
- crty: Ty<'tcx>,
327
- ) -> ConstValue<'tcx> {
328
- debug!("fold_const_value_deref {:?} {:?} {:?}", val, rty, crty);
329
- match (val, &crty.kind(), &rty.kind()) {
330
- // unsize array to slice if pattern is array but match value or other patterns are slice
331
- (ConstValue::Scalar(Scalar::Ptr(p)), ty::Array(t, n), ty::Slice(u)) => {
332
- assert_eq!(t, u);
333
- assert_eq!(p.offset, Size::ZERO);
334
- ConstValue::Slice {
335
- data: self.tcx.global_alloc(p.alloc_id).unwrap_memory(),
336
- start: 0,
337
- end: n.eval_usize(self.tcx, ty::ParamEnv::empty()).try_into().unwrap(),
338
- }
339
- }
340
- _ => val,
341
- }
342
- }
343
- }
344
-
345
- impl<'tcx> PatternFolder<'tcx> for LiteralExpander<'tcx> {
309
+ impl<'tcx> PatternFolder<'tcx> for LiteralExpander {
346
310
fn fold_pattern(&mut self, pat: &Pat<'tcx>) -> Pat<'tcx> {
347
311
debug!("fold_pattern {:?} {:?} {:?}", pat, pat.ty.kind(), pat.kind);
348
312
match (pat.ty.kind(), &*pat.kind) {
349
- (&ty::Ref(_, rty, _), &PatKind::Constant { value: Const { val, ty: const_ty } })
350
- if const_ty.is_ref() =>
351
- {
352
- let crty =
353
- if let ty::Ref(_, crty, _) = const_ty.kind() { crty } else { unreachable!() };
354
- if let ty::ConstKind::Value(val) = val {
355
- Pat {
356
- ty: pat.ty,
357
- span: pat.span,
358
- kind: box PatKind::Deref {
359
- subpattern: Pat {
360
- ty: rty,
361
- span: pat.span,
362
- kind: box PatKind::Constant {
363
- value: Const::from_value(
364
- self.tcx,
365
- self.fold_const_value_deref(*val, rty, crty),
366
- rty,
367
- ),
368
- },
369
- },
370
- },
371
- }
372
- } else {
373
- bug!("cannot deref {:#?}, {} -> {}", val, crty, rty)
374
- }
375
- }
376
-
377
313
(_, &PatKind::Binding { subpattern: Some(ref s), .. }) => s.fold_with(self),
378
314
(_, &PatKind::AscribeUserType { subpattern: ref s, .. }) => s.fold_with(self),
379
315
_ => pat.super_fold_with(self),
@@ -941,8 +877,6 @@ impl<'tcx> Constructor<'tcx> {
941
877
.iter()
942
878
.filter_map(|c: &Constructor<'_>| match c {
943
879
Slice(slice) => Some(*slice),
944
- // FIXME(oli-obk): implement `deref` for `ConstValue`
945
- ConstantValue(..) => None,
946
880
_ => bug!("bad slice pattern constructor {:?}", c),
947
881
})
948
882
.map(Slice::value_kind);
@@ -1162,12 +1096,6 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1162
1096
Fields::Slice(std::slice::from_ref(pat))
1163
1097
}
1164
1098
1165
- /// Construct a new `Fields` from the given patterns. You must be sure those patterns can't
1166
- /// contain fields that need to be filtered out. When in doubt, prefer `replace_fields`.
1167
- fn from_slice_unfiltered(pats: &'p [Pat<'tcx>]) -> Self {
1168
- Fields::Slice(pats)
1169
- }
1170
-
1171
1099
/// Convenience; internal use.
1172
1100
fn wildcards_from_tys(
1173
1101
cx: &MatchCheckCtxt<'p, 'tcx>,
@@ -2183,19 +2111,7 @@ fn pat_constructor<'tcx>(
2183
2111
if let Some(int_range) = IntRange::from_const(tcx, param_env, value, pat.span) {
2184
2112
Some(IntRange(int_range))
2185
2113
} else {
2186
- match (value.val, &value.ty.kind()) {
2187
- (_, ty::Array(_, n)) => {
2188
- let len = n.eval_usize(tcx, param_env);
2189
- Some(Slice(Slice { array_len: Some(len), kind: FixedLen(len) }))
2190
- }
2191
- (ty::ConstKind::Value(ConstValue::Slice { start, end, .. }), ty::Slice(_)) => {
2192
- let len = (end - start) as u64;
2193
- Some(Slice(Slice { array_len: None, kind: FixedLen(len) }))
2194
- }
2195
- // FIXME(oli-obk): implement `deref` for `ConstValue`
2196
- // (ty::ConstKind::Value(ConstValue::ByRef { .. }), ty::Slice(_)) => { ... }
2197
- _ => Some(ConstantValue(value)),
2198
- }
2114
+ Some(ConstantValue(value))
2199
2115
}
2200
2116
}
2201
2117
PatKind::Range(PatRange { lo, hi, end }) => {
@@ -2230,75 +2146,6 @@ fn pat_constructor<'tcx>(
2230
2146
}
2231
2147
}
2232
2148
2233
- // checks whether a constant is equal to a user-written slice pattern. Only supports byte slices,
2234
- // meaning all other types will compare unequal and thus equal patterns often do not cause the
2235
- // second pattern to lint about unreachable match arms.
2236
- fn slice_pat_covered_by_const<'tcx>(
2237
- tcx: TyCtxt<'tcx>,
2238
- _span: Span,
2239
- const_val: &'tcx ty::Const<'tcx>,
2240
- prefix: &[Pat<'tcx>],
2241
- slice: &Option<Pat<'tcx>>,
2242
- suffix: &[Pat<'tcx>],
2243
- param_env: ty::ParamEnv<'tcx>,
2244
- ) -> Result<bool, ErrorReported> {
2245
- let const_val_val = if let ty::ConstKind::Value(val) = const_val.val {
2246
- val
2247
- } else {
2248
- bug!(
2249
- "slice_pat_covered_by_const: {:#?}, {:#?}, {:#?}, {:#?}",
2250
- const_val,
2251
- prefix,
2252
- slice,
2253
- suffix,
2254
- )
2255
- };
2256
-
2257
- let data: &[u8] = match (const_val_val, &const_val.ty.kind()) {
2258
- (ConstValue::ByRef { offset, alloc, .. }, ty::Array(t, n)) => {
2259
- assert_eq!(*t, tcx.types.u8);
2260
- let n = n.eval_usize(tcx, param_env);
2261
- let ptr = Pointer::new(AllocId(0), offset);
2262
- alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap()
2263
- }
2264
- (ConstValue::Slice { data, start, end }, ty::Slice(t)) => {
2265
- assert_eq!(*t, tcx.types.u8);
2266
- let ptr = Pointer::new(AllocId(0), Size::from_bytes(start));
2267
- data.get_bytes(&tcx, ptr, Size::from_bytes(end - start)).unwrap()
2268
- }
2269
- // FIXME(oli-obk): create a way to extract fat pointers from ByRef
2270
- (_, ty::Slice(_)) => return Ok(false),
2271
- _ => bug!(
2272
- "slice_pat_covered_by_const: {:#?}, {:#?}, {:#?}, {:#?}",
2273
- const_val,
2274
- prefix,
2275
- slice,
2276
- suffix,
2277
- ),
2278
- };
2279
-
2280
- let pat_len = prefix.len() + suffix.len();
2281
- if data.len() < pat_len || (slice.is_none() && data.len() > pat_len) {
2282
- return Ok(false);
2283
- }
2284
-
2285
- for (ch, pat) in data[..prefix.len()]
2286
- .iter()
2287
- .zip(prefix)
2288
- .chain(data[data.len() - suffix.len()..].iter().zip(suffix))
2289
- {
2290
- if let box PatKind::Constant { value } = pat.kind {
2291
- let b = value.eval_bits(tcx, param_env, pat.ty);
2292
- assert_eq!(b as u8 as u128, b);
2293
- if b as u8 != *ch {
2294
- return Ok(false);
2295
- }
2296
- }
2297
- }
2298
-
2299
- Ok(true)
2300
- }
2301
-
2302
2149
/// For exhaustive integer matching, some constructors are grouped within other constructors
2303
2150
/// (namely integer typed values are grouped within ranges). However, when specialising these
2304
2151
/// constructors, we want to be specialising for the underlying constructors (the integers), not
@@ -2670,73 +2517,7 @@ fn specialize_one_pattern<'p, 'tcx>(
2670
2517
PatKind::Deref { ref subpattern } => Some(Fields::from_single_pattern(subpattern)),
2671
2518
2672
2519
PatKind::Constant { value } if constructor.is_slice() => {
2673
- // We extract an `Option` for the pointer because slices of zero
2674
- // elements don't necessarily point to memory, they are usually
2675
- // just integers. The only time they should be pointing to memory
2676
- // is when they are subslices of nonzero slices.
2677
- let (alloc, offset, n, ty) = match value.ty.kind() {
2678
- ty::Array(t, n) => {
2679
- let n = n.eval_usize(cx.tcx, cx.param_env);
2680
- // Shortcut for `n == 0` where no matter what `alloc` and `offset` we produce,
2681
- // the result would be exactly what we early return here.
2682
- if n == 0 {
2683
- if ctor_wild_subpatterns.len() as u64 != n {
2684
- return None;
2685
- }
2686
- return Some(Fields::empty());
2687
- }
2688
- match value.val {
2689
- ty::ConstKind::Value(ConstValue::ByRef { offset, alloc, .. }) => {
2690
- (Cow::Borrowed(alloc), offset, n, t)
2691
- }
2692
- _ => span_bug!(pat.span, "array pattern is {:?}", value,),
2693
- }
2694
- }
2695
- ty::Slice(t) => {
2696
- match value.val {
2697
- ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => {
2698
- let offset = Size::from_bytes(start);
2699
- let n = (end - start) as u64;
2700
- (Cow::Borrowed(data), offset, n, t)
2701
- }
2702
- ty::ConstKind::Value(ConstValue::ByRef { .. }) => {
2703
- // FIXME(oli-obk): implement `deref` for `ConstValue`
2704
- return None;
2705
- }
2706
- _ => span_bug!(
2707
- pat.span,
2708
- "slice pattern constant must be scalar pair but is {:?}",
2709
- value,
2710
- ),
2711
- }
2712
- }
2713
- _ => span_bug!(
2714
- pat.span,
2715
- "unexpected const-val {:?} with ctor {:?}",
2716
- value,
2717
- constructor,
2718
- ),
2719
- };
2720
- if ctor_wild_subpatterns.len() as u64 != n {
2721
- return None;
2722
- }
2723
-
2724
- // Convert a constant slice/array pattern to a list of patterns.
2725
- let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?;
2726
- let ptr = Pointer::new(AllocId(0), offset);
2727
- let pats = cx.pattern_arena.alloc_from_iter((0..n).filter_map(|i| {
2728
- let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?;
2729
- let scalar = alloc.read_scalar(&cx.tcx, ptr, layout.size).ok()?;
2730
- let scalar = scalar.check_init().ok()?;
2731
- let value = ty::Const::from_scalar(cx.tcx, scalar, ty);
2732
- let pattern = Pat { ty, span: pat.span, kind: box PatKind::Constant { value } };
2733
- Some(pattern)
2734
- }));
2735
- // Ensure none of the dereferences failed.
2736
- if pats.len() as u64 != n {
2737
- return None;
2738
- }
2739
- Some(Fields::from_slice_unfiltered(pats))
2520
+ span_bug!(pat.span, "unexpected const-val {:?} with ctor {:?}", value, constructor)
2740
2521
}
2741
2522
2742
2523
PatKind::Constant { .. } | PatKind::Range { .. } => {
@@ -2778,21 +2559,7 @@ fn specialize_one_pattern<'p, 'tcx>(
2778
2559
let suffix = suffix.iter().enumerate().map(|(i, p)| (arity - suffix.len() + i, p));
2779
2560
Some(ctor_wild_subpatterns.replace_fields_indexed(prefix.chain(suffix)))
2780
2561
}
2781
- ConstantValue(cv) => {
2782
- match slice_pat_covered_by_const(
2783
- cx.tcx,
2784
- pat.span,
2785
- cv,
2786
- prefix,
2787
- slice,
2788
- suffix,
2789
- cx.param_env,
2790
- ) {
2791
- Ok(true) => Some(Fields::empty()),
2792
- Ok(false) => None,
2793
- Err(ErrorReported) => None,
2794
- }
2795
- }
2562
+ ConstantValue(_) => None,
2796
2563
_ => span_bug!(pat.span, "unexpected ctor {:?} for slice pat", constructor),
2797
2564
},
2798
2565
0 commit comments