Skip to content

Commit 52cf5fc

Browse files
committed
bugfix 1/2
1 parent 8fdddf6 commit 52cf5fc

File tree

2 files changed

+67
-83
lines changed

2 files changed

+67
-83
lines changed

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

Lines changed: 44 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use either::Either;
22
use rustc_middle::mir::*;
33
use rustc_middle::thir::{self, *};
44
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
5+
use std::ops;
56

67
use crate::builder::Builder;
78
use crate::builder::expr::as_place::{PlaceBase, PlaceBuilder};
@@ -35,7 +36,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
3536
/// Used internally by [`MatchPairTree::for_pattern`].
3637
fn prefix_slice_suffix<'pat>(
3738
&mut self,
38-
src_path: &'pat Pat<'tcx>,
39+
top_pattern: &'pat Pat<'tcx>,
3940
match_pairs: &mut Vec<MatchPairTree<'pat, 'tcx>>,
4041
place: &PlaceBuilder<'tcx>,
4142
prefix: &'pat [Box<Pat<'tcx>>],
@@ -57,28 +58,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
5758
((prefix.len() + suffix.len()).try_into().unwrap(), false)
5859
};
5960

60-
if self.should_optimize_subslice(prefix) {
61-
let elem_ty = prefix[0].ty;
62-
let prefix_valtree = self.simplify_const_pattern_slice_into_valtree(prefix);
63-
let match_pair = self.valtree_to_match_pair(
64-
src_path,
65-
prefix_valtree,
66-
place.clone(),
67-
elem_ty,
68-
Range::from_start(0..prefix.len() as u64),
69-
opt_slice.is_some() || !suffix.is_empty(),
70-
);
71-
72-
match_pairs.push(match_pair);
73-
} else {
74-
match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| {
75-
let elem = ProjectionElem::ConstantIndex {
76-
offset: idx as u64,
77-
min_length,
78-
from_end: false,
79-
};
80-
MatchPairTree::for_pattern(place.clone_project(elem), subpattern, self)
81-
}));
61+
tracing::warn!("Builder::prefix_slice_suffix: min_length: {}, exact_size: {} -> {:?}", min_length, exact_size, top_pattern);
62+
tracing::warn!("prefix: {:?}, suffix: {:?}", prefix.len(), suffix.len());
63+
64+
if !prefix.is_empty() {
65+
let bounds = Range::from_start(0..prefix.len() as u64);
66+
let subpattern = bounds.apply(prefix);
67+
for pair in self.build_slice_branch(bounds, place, top_pattern, subpattern) {
68+
match_pairs.push(pair);
69+
}
8270
}
8371

8472
if let Some(subslice_pat) = opt_slice {
@@ -91,61 +79,38 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
9179
match_pairs.push(MatchPairTree::for_pattern(subslice, subslice_pat, self));
9280
}
9381

94-
if self.should_optimize_subslice(suffix) {
95-
let elem_ty = suffix[0].ty;
96-
let suffix_valtree = self.simplify_const_pattern_slice_into_valtree(suffix);
97-
let match_pair = self.valtree_to_match_pair(
98-
src_path,
99-
suffix_valtree,
100-
place.clone(),
101-
elem_ty,
102-
Range::from_end(0..suffix.len() as u64),
103-
true,
104-
);
105-
106-
match_pairs.push(match_pair);
107-
} else {
108-
match_pairs.extend(suffix.iter().rev().enumerate().map(|(idx, subpattern)| {
109-
let end_offset = (idx + 1) as u64;
110-
let elem = ProjectionElem::ConstantIndex {
111-
offset: if exact_size { min_length - end_offset } else { end_offset },
112-
min_length,
113-
from_end: !exact_size,
114-
};
115-
let place = place.clone_project(elem);
116-
MatchPairTree::for_pattern(place, subpattern, self)
117-
}));
82+
if !suffix.is_empty() {
83+
let bounds = Range::from_end(0..suffix.len() as u64);
84+
let subpattern = bounds.apply(suffix);
85+
for pair in self.build_slice_branch(bounds, place, top_pattern, subpattern) {
86+
match_pairs.push(pair);
87+
}
11888
}
11989
}
12090

121-
fn build_slice_branch<'pat>(
122-
&'pat mut self,
123-
place: &'pat PlaceBuilder<'tcx>,
91+
fn build_slice_branch<'pat, 'b>(
92+
&'b mut self,
93+
bounds: Range,
94+
place: &'b PlaceBuilder<'tcx>,
12495
top_pattern: &'pat Pat<'tcx>,
12596
pattern: &'pat [Box<Pat<'tcx>>],
126-
) -> impl Iterator<Item = MatchPairTree<'pat, 'tcx>> + use<'pat, 'tcx, 'a> {
97+
) -> impl Iterator<Item = MatchPairTree<'pat, 'tcx>> + use<'a, 'tcx, 'pat, 'b> {
12798
let entries = self.find_const_groups(pattern);
128-
let solo = entries.len() == 1;
129-
130-
let maybe_project = move |base: &PlaceBuilder<'tcx>, elem| {
131-
if solo { base.clone_project(elem) } else { base.clone() }
132-
};
13399

134100
entries.into_iter().map(move |entry| {
135-
let pattern_len = pattern.len() as u64;
136101
let mut build_single = |idx| {
137102
let subpattern = &pattern[idx as usize];
138-
let place = maybe_project(place, ProjectionElem::ConstantIndex {
139-
offset: idx,
140-
min_length: pattern_len,
141-
from_end: false,
103+
let place = place.clone_project(ProjectionElem::ConstantIndex {
104+
offset: bounds.shift_idx(idx),
105+
min_length: pattern.len() as u64,
106+
from_end: bounds.from_end,
142107
});
143108

144109
MatchPairTree::for_pattern(place, subpattern, self)
145110
};
146111

147112
match entry {
148-
Either::Right(range) if range.len() > 1 => {
113+
Either::Right(range) if range.end-range.start > 1 => {
149114
assert!(
150115
(range.start..range.end)
151116
.all(|idx| self.is_constant_pattern(&pattern[idx as usize]))
@@ -154,14 +119,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
154119
let subpattern = &pattern[range.start as usize..range.end as usize];
155120
let elem_ty = subpattern[0].ty;
156121

157-
let place = maybe_project(place, PlaceElem::Subslice {
158-
from: range.start,
159-
to: pattern.len() as u64 - range.end,
160-
from_end: true,
161-
});
162-
163122
let valtree = self.simplify_const_pattern_slice_into_valtree(subpattern);
164-
self.valtree_to_match_pair(top_pattern, valtree, place, elem_ty, range, false)
123+
self.valtree_to_match_pair(
124+
top_pattern,
125+
valtree,
126+
place.clone(),
127+
elem_ty,
128+
bounds.shift_range(range),
129+
true, // TODO: set false if only branch and only entry
130+
)
165131
}
166132
Either::Right(range) => {
167133
let tree = build_single(range.start);
@@ -173,15 +139,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
173139
})
174140
}
175141

176-
fn find_const_groups(&self, pattern: &[Box<Pat<'tcx>>]) -> Vec<Either<u64, Range>> {
142+
fn find_const_groups(&self, pattern: &[Box<Pat<'tcx>>]) -> Vec<Either<u64, ops::Range<u64>>> {
177143
let mut entries = Vec::new();
178144
let mut current_seq_start = None;
179145

180-
let mut apply = |state: &mut _, idx| {
146+
let mut apply = |state: &mut _, idx, b: bool| {
181147
if let Some(start) = *state {
182148
*state = None;
183-
entries.push(Either::Right(Range::from_start(start..idx)));
184-
} else {
149+
entries.push(Either::Right(start..idx));
150+
} else if !b {
185151
entries.push(Either::Left(idx));
186152
}
187153
};
@@ -192,18 +158,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
192158
current_seq_start = Some(idx as u64);
193159
}
194160
} else {
195-
apply(&mut current_seq_start, idx as u64);
161+
apply(&mut current_seq_start, idx as u64, false);
196162
}
197163
}
198164

199-
apply(&mut current_seq_start, pattern.len() as u64);
165+
apply(&mut current_seq_start, pattern.len() as u64, true);
200166
entries
201167
}
202168

203-
fn should_optimize_subslice(&self, subslice: &[Box<Pat<'tcx>>]) -> bool {
204-
subslice.len() > 1 && subslice.iter().all(|p| self.is_constant_pattern(p))
205-
}
206-
207169
fn is_constant_pattern(&self, pat: &Pat<'tcx>) -> bool {
208170
if let PatKind::Constant { value } = pat.kind
209171
&& let Const::Ty(_, const_) = value
@@ -244,16 +206,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
244206
place: PlaceBuilder<'tcx>,
245207
elem_ty: Ty<'tcx>,
246208
range: Range,
247-
do_own_slice: bool,
209+
do_slice: bool,
248210
) -> MatchPairTree<'pat, 'tcx> {
249211
let tcx = self.tcx;
250212
let const_ty =
251213
Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, Ty::new_array(tcx, elem_ty, range.len()));
252214

253-
let pat_ty = if do_own_slice { Ty::new_slice(tcx, elem_ty) } else { source_pattern.ty };
215+
let pat_ty = if do_slice { Ty::new_slice(tcx, elem_ty) } else { source_pattern.ty };
254216
let ty_const = ty::Const::new(tcx, ty::ConstKind::Value(const_ty, valtree));
255217
let value = Const::Ty(const_ty, ty_const);
256-
let test_case = TestCase::Constant { value, range: do_own_slice.then_some(range) };
218+
let test_case = TestCase::Constant { value, range: do_slice.then_some(range) };
257219
let pattern = tcx.arena.alloc(Pat {
258220
ty: pat_ty,
259221
span: source_pattern.span,

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

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,29 @@ impl Range {
248248
Range { start: range.end, end: range.start, from_end: true }
249249
}
250250

251-
pub(crate) fn len(&self) -> u64 {
251+
pub(crate) fn len(self) -> u64 {
252252
if !self.from_end { self.end - self.start } else { self.start - self.end }
253253
}
254+
255+
pub(crate) fn apply<T>(self, slice: &[T]) -> &[T] {
256+
if !self.from_end {
257+
&slice[self.start as usize..self.end as usize]
258+
} else {
259+
&slice[..self.start as usize - self.end as usize]
260+
}
261+
}
262+
263+
pub(crate) fn shift_idx(self, idx: u64) -> u64 {
264+
if !self.from_end { self.start + idx } else { self.start - idx }
265+
}
266+
267+
pub(crate) fn shift_range(self, range_within: ops::Range<u64>) -> Self {
268+
if !self.from_end {
269+
Self::from_start(self.start+range_within.start..self.start+range_within.end)
270+
} else {
271+
let range_within_start = range_within.end;
272+
let range_within_end = range_within.start;
273+
Self::from_end(self.start-range_within_start..self.start-range_within_end)
274+
}
275+
}
254276
}

0 commit comments

Comments
 (0)