Skip to content

Commit 8687117

Browse files
committed
def new range type for pattern slicing
1 parent 49377cc commit 8687117

File tree

4 files changed

+61
-25
lines changed

4 files changed

+61
-25
lines changed

compiler/rustc_mir_build/src/builder/matches/match_pair.rs

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use rustc_middle::ty::{self, Ty, TypeVisitableExt};
44

55
use crate::builder::Builder;
66
use crate::builder::expr::as_place::{PlaceBase, PlaceBuilder};
7+
use crate::builder::matches::util::Range;
78
use crate::builder::matches::{FlatPat, MatchPairTree, TestCase};
89

910
impl<'a, 'tcx> Builder<'a, 'tcx> {
@@ -60,10 +61,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
6061
let prefix_valtree = self.simplify_const_pattern_slice_into_valtree(prefix);
6162
let match_pair = self.valtree_to_match_pair(
6263
src_path,
63-
prefix.len() as u64,
6464
prefix_valtree,
6565
place.clone(),
6666
elem_ty,
67+
Range::from_start(0..prefix.len() as u64),
6768
opt_slice.is_some() || !suffix.is_empty(),
6869
);
6970

@@ -89,16 +90,31 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
8990
match_pairs.push(MatchPairTree::for_pattern(subslice, subslice_pat, self));
9091
}
9192

92-
match_pairs.extend(suffix.iter().rev().enumerate().map(|(idx, subpattern)| {
93-
let end_offset = (idx + 1) as u64;
94-
let elem = ProjectionElem::ConstantIndex {
95-
offset: if exact_size { min_length - end_offset } else { end_offset },
96-
min_length,
97-
from_end: !exact_size,
98-
};
99-
let place = place.clone_project(elem);
100-
MatchPairTree::for_pattern(place, subpattern, self)
101-
}));
93+
if self.should_optimize_subslice(suffix) {
94+
let elem_ty = suffix[0].ty;
95+
let suffix_valtree = self.simplify_const_pattern_slice_into_valtree(suffix);
96+
let match_pair = self.valtree_to_match_pair(
97+
src_path,
98+
suffix_valtree,
99+
place.clone(),
100+
elem_ty,
101+
Range::from_end(0..suffix.len() as u64),
102+
true,
103+
);
104+
105+
match_pairs.push(match_pair);
106+
} else {
107+
match_pairs.extend(suffix.iter().rev().enumerate().map(|(idx, subpattern)| {
108+
let end_offset = (idx + 1) as u64;
109+
let elem = ProjectionElem::ConstantIndex {
110+
offset: if exact_size { min_length - end_offset } else { end_offset },
111+
min_length,
112+
from_end: !exact_size,
113+
};
114+
let place = place.clone_project(elem);
115+
MatchPairTree::for_pattern(place, subpattern, self)
116+
}));
117+
}
102118
}
103119

104120
fn should_optimize_subslice(&self, subslice: &[Box<Pat<'tcx>>]) -> bool {
@@ -141,23 +157,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
141157
fn valtree_to_match_pair<'pat>(
142158
&mut self,
143159
source_pattern: &'pat Pat<'tcx>,
144-
subslice_len: u64,
145160
valtree: ty::ValTree<'tcx>,
146161
place: PlaceBuilder<'tcx>,
147162
elem_ty: Ty<'tcx>,
163+
range: Range,
148164
subsliced: bool,
149165
) -> MatchPairTree<'pat, 'tcx> {
150166
let tcx = self.tcx;
151-
let const_ty = Ty::new_imm_ref(
152-
tcx,
153-
tcx.lifetimes.re_erased,
154-
Ty::new_array(tcx, elem_ty, subslice_len),
155-
);
167+
let const_ty =
168+
Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, Ty::new_array(tcx, elem_ty, range.len()));
156169

157170
let pat_ty = if subsliced { Ty::new_slice(tcx, elem_ty) } else { source_pattern.ty };
158171
let ty_const = ty::Const::new(tcx, ty::ConstKind::Value(const_ty, valtree));
159172
let value = Const::Ty(const_ty, ty_const);
160-
let test_case = TestCase::Constant { value, range: subsliced.then(|| 0..subslice_len) };
173+
let test_case = TestCase::Constant { value, range: subsliced.then_some(range) };
161174
let pattern = tcx.arena.alloc(Pat {
162175
ty: pat_ty,
163176
span: source_pattern.span,

compiler/rustc_mir_build/src/builder/matches/mod.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
//! This also includes code for pattern bindings in `let` statements and
66
//! function parameters.
77
8-
use std::ops::Range;
9-
108
use rustc_abi::VariantIdx;
119
use rustc_data_structures::fx::FxIndexMap;
1210
use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -21,6 +19,7 @@ use tracing::{debug, instrument};
2119

2220
use crate::builder::ForGuard::{self, OutsideGuard, RefWithinGuard};
2321
use crate::builder::expr::as_place::PlaceBuilder;
22+
use crate::builder::matches::util::Range;
2423
use crate::builder::scope::DropKind;
2524
use crate::builder::{
2625
BlockAnd, BlockAndExtension, Builder, GuardFrame, GuardFrameLocal, LocalsForNode,
@@ -1239,7 +1238,7 @@ struct Ascription<'tcx> {
12391238
enum TestCase<'pat, 'tcx> {
12401239
Irrefutable { binding: Option<Binding<'tcx>>, ascription: Option<Ascription<'tcx>> },
12411240
Variant { adt_def: ty::AdtDef<'tcx>, variant_index: VariantIdx },
1242-
Constant { value: mir::Const<'tcx>, range: Option<Range<u64>> },
1241+
Constant { value: mir::Const<'tcx>, range: Option<Range> },
12431242
Range(&'pat PatRange<'tcx>),
12441243
Slice { len: usize, variable_length: bool },
12451244
Deref { temp: Place<'tcx>, mutability: Mutability },
@@ -1315,7 +1314,7 @@ enum TestKind<'tcx> {
13151314
/// `ty`,
13161315
Eq {
13171316
value: Const<'tcx>,
1318-
range: Option<Range<u64>>,
1317+
range: Option<Range>,
13191318
// Integer types are handled by `SwitchInt`, and constants with ADT
13201319
// types are converted back into patterns, so this can only be `&str`,
13211320
// `&[T]`, `f32` or `f64`.

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
3636

3737
TestCase::Constant { .. } if match_pair.pattern.ty.is_bool() => TestKind::If,
3838
TestCase::Constant { .. } if is_switch_ty(match_pair.pattern.ty) => TestKind::SwitchInt,
39-
TestCase::Constant { value, ref range } => {
40-
TestKind::Eq { value, ty: match_pair.pattern.ty, range: range.clone() }
39+
TestCase::Constant { value, range } => {
40+
TestKind::Eq { value, ty: match_pair.pattern.ty, range }
4141
}
4242

4343
TestCase::Range(range) => {
@@ -144,7 +144,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
144144
self.cfg.terminate(block, self.source_info(match_start_span), terminator);
145145
}
146146

147-
TestKind::Eq { value, ref range, ty } => {
147+
TestKind::Eq { value, range, ty } => {
148148
let tcx = self.tcx;
149149
let success_block = target_block(TestBranch::Success);
150150
let fail_block = target_block(TestBranch::Failure);
@@ -182,6 +182,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
182182
);
183183
} else if !ty.is_scalar() {
184184
let (place, block) = if let Some(range) = range {
185+
// TODO: range handling
185186
assert_eq!(range.start, 0);
186187
let target_block = self.cfg.start_new_block();
187188
let subslice = self.subslice(

compiler/rustc_mir_build/src/builder/matches/util.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::ops;
2+
13
use rustc_data_structures::fx::FxIndexMap;
24
use rustc_middle::mir::*;
35
use rustc_middle::ty::Ty;
@@ -229,3 +231,24 @@ pub(crate) fn ref_pat_borrow_kind(ref_mutability: Mutability) -> BorrowKind {
229231
Mutability::Not => BorrowKind::Shared,
230232
}
231233
}
234+
235+
#[derive(Copy, Clone, PartialEq, Debug)]
236+
pub(super) struct Range {
237+
pub(crate) start: u64,
238+
pub(crate) end: u64,
239+
pub(crate) from_end: bool,
240+
}
241+
242+
impl Range {
243+
pub(crate) fn from_start(range: ops::Range<u64>) -> Self {
244+
Range { start: range.start, end: range.end, from_end: false }
245+
}
246+
247+
pub(crate) fn from_end(range: ops::Range<u64>) -> Self {
248+
Range { start: range.end, end: range.start, from_end: true }
249+
}
250+
251+
pub(crate) fn len(&self) -> u64 {
252+
todo!()
253+
}
254+
}

0 commit comments

Comments
 (0)