Skip to content

Commit 89ff2b2

Browse files
committed
redo git history
1 parent bf1e3f3 commit 89ff2b2

File tree

5 files changed

+110
-20
lines changed

5 files changed

+110
-20
lines changed

compiler/rustc_middle/src/arena.rs

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ macro_rules! arena_types {
106106
[] tys: rustc_type_ir::WithCachedTypeInfo<rustc_middle::ty::TyKind<'tcx>>,
107107
[] predicates: rustc_type_ir::WithCachedTypeInfo<rustc_middle::ty::PredicateKind<'tcx>>,
108108
[] consts: rustc_middle::ty::ConstData<'tcx>,
109+
[] pats: rustc_middle::thir::Pat<'tcx>,
109110

110111
// Note that this deliberately duplicates items in the `rustc_hir::arena`,
111112
// since we need to allocate this type on both the `rustc_hir` arena

compiler/rustc_middle/src/ty/consts.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use super::sty::ConstKind;
2424
/// Use this rather than `ConstData`, whenever possible.
2525
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
2626
#[rustc_pass_by_value]
27-
pub struct Const<'tcx>(pub(super) Interned<'tcx, ConstData<'tcx>>);
27+
pub struct Const<'tcx>(pub Interned<'tcx, ConstData<'tcx>>);
2828

2929
/// Typed constant value.
3030
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)]

compiler/rustc_middle/src/ty/consts/valtree.rs

+6
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ impl<'tcx> ValTree<'tcx> {
6363
Self::Branch(interned)
6464
}
6565

66+
pub fn from_scalars<'a>(tcx: TyCtxt<'tcx>, scalars: &'a [ScalarInt]) -> Self {
67+
let interned = tcx.arena.alloc_from_iter(scalars.iter().map(|&s| Self::Leaf(s)));
68+
69+
Self::Branch(interned)
70+
}
71+
6672
pub fn from_scalar_int(i: ScalarInt) -> Self {
6773
Self::Leaf(i)
6874
}

compiler/rustc_mir_build/src/build/matches/simplify.rs

+97-17
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@
1515
use crate::build::expr::as_place::PlaceBuilder;
1616
use crate::build::matches::{Ascription, Binding, Candidate, MatchPair};
1717
use crate::build::Builder;
18+
use rustc_data_structures::intern::Interned;
1819
use rustc_hir::RangeEnd;
20+
use rustc_middle::mir::ConstantKind;
1921
use rustc_middle::thir::{self, *};
20-
use rustc_middle::ty;
2122
use rustc_middle::ty::layout::IntegerExt;
23+
use rustc_middle::ty::Const;
24+
use rustc_middle::ty::{self, Ty, ValTree};
2225
use rustc_target::abi::{Integer, Size};
2326

2427
use std::mem;
@@ -120,6 +123,38 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
120123
}
121124
}
122125

126+
fn try_build_valtree(&self, elements: &Box<[Box<Pat<'tcx>>]>) -> Option<ValTree<'tcx>> {
127+
if elements.iter().all(|p| {
128+
matches!(
129+
p.kind,
130+
PatKind::Constant {
131+
value: ConstantKind::Ty(ty::Const(Interned(
132+
ty::ConstData { kind: ty::ConstKind::Value(ty::ValTree::Leaf(_)), .. },
133+
_
134+
)))
135+
}
136+
)
137+
}) {
138+
// This ValTree represents the content of the simple array.
139+
// We then create a new pattern that matches against this ValTree.
140+
// This reduces a match against `[1, 2, 3, 4]` from 4 basic-blocks in the MIR to just 1
141+
Some(ValTree::from_scalars(
142+
self.tcx,
143+
&elements
144+
.iter()
145+
.map(|p| match p.kind {
146+
PatKind::Constant { value: ConstantKind::Ty(c) } => {
147+
c.to_valtree().unwrap_leaf()
148+
}
149+
_ => unreachable!(),
150+
})
151+
.collect::<Vec<_>>(),
152+
))
153+
} else {
154+
None
155+
}
156+
}
157+
123158
/// Given `candidate` that has a single or-pattern for its match-pairs,
124159
/// creates a fresh candidate for each of its input subpatterns passed via
125160
/// `pats`.
@@ -243,22 +278,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
243278
Err(match_pair)
244279
}
245280

246-
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
247-
if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
248-
// irrefutable
249-
self.prefix_slice_suffix(
250-
&mut candidate.match_pairs,
251-
&match_pair.place,
252-
prefix,
253-
slice,
254-
suffix,
255-
);
256-
Ok(())
257-
} else {
258-
Err(match_pair)
259-
}
260-
}
261-
262281
PatKind::Variant { adt_def, args, variant_index, ref subpatterns } => {
263282
let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| {
264283
i == variant_index || {
@@ -281,6 +300,51 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
281300
}
282301
}
283302

303+
// Looks for simple array patterns such as `[1, 2, 3]`
304+
// They cannot have slices (e.g `[1, .., 3, 4]` is not simple), and
305+
// all the elements of the array must be leaf constants (so no strings!)
306+
PatKind::Array { ref prefix, slice: None, ref suffix }
307+
| PatKind::Slice { ref prefix, slice: None, ref suffix }
308+
if let Some(_val) = self.try_build_valtree(prefix)
309+
&& !prefix.is_empty()
310+
&& suffix.is_empty() =>
311+
{
312+
// This ValTree represents the content of the simple array.
313+
// We then create a new pattern that matches against this ValTree.
314+
// This reduces a match against `[1, 2, 3, 4]` from 4 basic-blocks in the MIR to just 1
315+
let val = self.try_build_valtree(prefix).unwrap(); // FIXME: false positive
316+
317+
let el_ty = prefix.iter().next().unwrap().ty;
318+
let (place, cnst_ty, pat_ty) =
319+
if match_pair.pattern.ty.is_slice() {
320+
(
321+
PlaceBuilder::from(match_pair.place.base()),
322+
Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, Ty::new_array(tcx, el_ty, prefix.len() as u64)),
323+
Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, Ty::new_slice(tcx, el_ty))
324+
)
325+
} else {
326+
let arr_ty = Ty::new_array(tcx, el_ty, prefix.len() as u64);
327+
(
328+
match_pair.place,
329+
arr_ty,
330+
arr_ty
331+
)
332+
};
333+
334+
let cnst = Const::new(tcx, ty::ConstKind::Value(val), cnst_ty);
335+
let new_pat = Pat {
336+
ty: pat_ty,
337+
span: match_pair.pattern.span,
338+
kind: PatKind::Constant { value: ConstantKind::Ty(cnst) },
339+
};
340+
341+
let pat = tcx.arena.alloc(new_pat);
342+
343+
candidate.match_pairs.push(MatchPair::new(place, pat, self));
344+
345+
Ok(())
346+
}
347+
284348
PatKind::Array { ref prefix, ref slice, ref suffix } => {
285349
self.prefix_slice_suffix(
286350
&mut candidate.match_pairs,
@@ -292,6 +356,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
292356
Ok(())
293357
}
294358

359+
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
360+
if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
361+
// irrefutable
362+
self.prefix_slice_suffix(
363+
&mut candidate.match_pairs,
364+
&match_pair.place,
365+
prefix,
366+
slice,
367+
suffix,
368+
);
369+
Ok(())
370+
} else {
371+
Err(match_pair)
372+
}
373+
}
374+
295375
PatKind::Leaf { ref subpatterns } => {
296376
// tuple struct, match subpats (if any)
297377
candidate.match_pairs.extend(self.field_match_pairs(match_pair.place, subpatterns));

compiler/rustc_mir_build/src/build/matches/test.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
9494
};
9595

9696
match match_pair.pattern.kind {
97-
PatKind::Constant { value } => {
97+
PatKind::Constant {
98+
value
99+
} if let Some(result) = value.try_eval_bits(self.tcx, self.param_env, switch_ty) => {
98100
options
99101
.entry(value)
100-
.or_insert_with(|| value.eval_bits(self.tcx, self.param_env, switch_ty));
102+
.or_insert(result);
101103
true
102104
}
103105
PatKind::Variant { .. } => {
@@ -108,6 +110,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
108110
self.values_not_contained_in_range(&*range, options).unwrap_or(false)
109111
}
110112
PatKind::Slice { .. }
113+
| PatKind::Constant { .. }
111114
| PatKind::Array { .. }
112115
| PatKind::Wild
113116
| PatKind::Or { .. }

0 commit comments

Comments
 (0)