Skip to content

Commit 591d058

Browse files
committed
wip tree solver
1 parent 72d5810 commit 591d058

File tree

1 file changed

+79
-3
lines changed

1 file changed

+79
-3
lines changed

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

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use either::Either;
12
use rustc_middle::mir::*;
23
use rustc_middle::thir::{self, *};
34
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
@@ -117,6 +118,81 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
117118
}
118119
}
119120

121+
fn build_slice_branch<'pat>(
122+
&'pat mut self,
123+
place: &'pat PlaceBuilder<'tcx>,
124+
top_pattern: &'pat Pat<'tcx>,
125+
pattern: &'pat [Box<Pat<'tcx>>],
126+
) -> impl Iterator<Item = MatchPairTree<'pat, 'tcx>> + use<'pat, 'tcx, 'a> {
127+
self.find_const_groups(pattern).into_iter().map(move |entry| {
128+
let pattern_len = pattern.len() as u64;
129+
let mut build_single = |idx| {
130+
let subpattern = &pattern[idx as usize];
131+
let place = place.clone_project(ProjectionElem::ConstantIndex {
132+
offset: idx,
133+
min_length: pattern_len,
134+
from_end: false,
135+
});
136+
137+
MatchPairTree::for_pattern(place, subpattern, self)
138+
};
139+
140+
match entry {
141+
Either::Right(range) if range.len() > 1 => {
142+
assert!(
143+
(range.start..range.end)
144+
.all(|idx| self.is_constant_pattern(&pattern[idx as usize]))
145+
);
146+
147+
let subpattern = &pattern[range.start as usize..range.end as usize];
148+
let elem_ty = subpattern[0].ty;
149+
150+
let place = place.clone_project(PlaceElem::Subslice {
151+
from: range.start,
152+
to: pattern.len() as u64 - range.end,
153+
from_end: true,
154+
});
155+
156+
let valtree = self.simplify_const_pattern_slice_into_valtree(subpattern);
157+
self.valtree_to_match_pair(top_pattern, valtree, place, elem_ty, range, false)
158+
}
159+
Either::Right(range) => {
160+
let tree = build_single(range.start);
161+
assert!(self.is_constant_pattern(&pattern[range.start as usize]));
162+
tree
163+
}
164+
Either::Left(idx) => build_single(idx),
165+
}
166+
})
167+
}
168+
169+
fn find_const_groups(&self, pattern: &[Box<Pat<'tcx>>]) -> Vec<Either<u64, Range>> {
170+
let mut entries = Vec::new();
171+
let mut current_seq_start = None;
172+
173+
let mut apply = |state: &mut _, idx| {
174+
if let Some(start) = *state {
175+
*state = None;
176+
entries.push(Either::Right(Range::from_start(start..idx)));
177+
} else {
178+
entries.push(Either::Left(idx));
179+
}
180+
};
181+
182+
for (idx, pat) in pattern.iter().enumerate() {
183+
if self.is_constant_pattern(pat) {
184+
if current_seq_start.is_none() {
185+
current_seq_start = Some(idx as u64);
186+
}
187+
} else {
188+
apply(&mut current_seq_start, idx as u64);
189+
}
190+
}
191+
192+
apply(&mut current_seq_start, pattern.len() as u64);
193+
entries
194+
}
195+
120196
fn should_optimize_subslice(&self, subslice: &[Box<Pat<'tcx>>]) -> bool {
121197
subslice.len() > 1 && subslice.iter().all(|p| self.is_constant_pattern(p))
122198
}
@@ -161,16 +237,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
161237
place: PlaceBuilder<'tcx>,
162238
elem_ty: Ty<'tcx>,
163239
range: Range,
164-
subsliced: bool,
240+
do_own_slice: bool,
165241
) -> MatchPairTree<'pat, 'tcx> {
166242
let tcx = self.tcx;
167243
let const_ty =
168244
Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, Ty::new_array(tcx, elem_ty, range.len()));
169245

170-
let pat_ty = if subsliced { Ty::new_slice(tcx, elem_ty) } else { source_pattern.ty };
246+
let pat_ty = if do_own_slice { Ty::new_slice(tcx, elem_ty) } else { source_pattern.ty };
171247
let ty_const = ty::Const::new(tcx, ty::ConstKind::Value(const_ty, valtree));
172248
let value = Const::Ty(const_ty, ty_const);
173-
let test_case = TestCase::Constant { value, range: subsliced.then_some(range) };
249+
let test_case = TestCase::Constant { value, range: do_own_slice.then_some(range) };
174250
let pattern = tcx.arena.alloc(Pat {
175251
ty: pat_ty,
176252
span: source_pattern.span,

0 commit comments

Comments
 (0)