Skip to content

Commit 5545961

Browse files
committed
Auto merge of rust-lang#14976 - HKalbasi:mir-fix, r=HKalbasi
Fix missing terminator for slice pattern
2 parents 1742683 + b4907a5 commit 5545961

File tree

2 files changed

+70
-45
lines changed

2 files changed

+70
-45
lines changed

crates/hir-ty/src/mir/lower/pattern_matching.rs

+49-45
Original file line numberDiff line numberDiff line change
@@ -206,56 +206,60 @@ impl MirLowerCtx<'_> {
206206
(current, current_else)
207207
}
208208
Pat::Slice { prefix, slice, suffix } => {
209-
if let TyKind::Slice(_) = self.infer[pattern].kind(Interner) {
210-
let pattern_len = prefix.len() + suffix.len();
211-
let place_len: Place =
212-
self.temp(TyBuilder::usize(), current, pattern.into())?.into();
213-
self.push_assignment(
214-
current,
215-
place_len.clone(),
216-
Rvalue::Len((&mut cond_place).clone()),
217-
pattern.into(),
218-
);
219-
let else_target = *current_else.get_or_insert_with(|| self.new_basic_block());
220-
let next = self.new_basic_block();
221-
if slice.is_none() {
222-
self.set_terminator(
223-
current,
224-
TerminatorKind::SwitchInt {
225-
discr: Operand::Copy(place_len),
226-
targets: SwitchTargets::static_if(
227-
pattern_len as u128,
228-
next,
229-
else_target,
230-
),
231-
},
232-
pattern.into(),
233-
);
234-
} else {
235-
let c = Operand::from_concrete_const(
236-
pattern_len.to_le_bytes().to_vec(),
237-
MemoryMap::default(),
238-
TyBuilder::usize(),
239-
);
240-
let discr: Place =
241-
self.temp(TyBuilder::bool(), current, pattern.into())?.into();
209+
if mode == MatchingMode::Check {
210+
// emit runtime length check for slice
211+
if let TyKind::Slice(_) = self.infer[pattern].kind(Interner) {
212+
let pattern_len = prefix.len() + suffix.len();
213+
let place_len: Place =
214+
self.temp(TyBuilder::usize(), current, pattern.into())?.into();
242215
self.push_assignment(
243216
current,
244-
discr.clone(),
245-
Rvalue::CheckedBinaryOp(BinOp::Le, c, Operand::Copy(place_len)),
246-
pattern.into(),
247-
);
248-
let discr = Operand::Copy(discr);
249-
self.set_terminator(
250-
current,
251-
TerminatorKind::SwitchInt {
252-
discr,
253-
targets: SwitchTargets::static_if(1, next, else_target),
254-
},
217+
place_len.clone(),
218+
Rvalue::Len((&mut cond_place).clone()),
255219
pattern.into(),
256220
);
221+
let else_target =
222+
*current_else.get_or_insert_with(|| self.new_basic_block());
223+
let next = self.new_basic_block();
224+
if slice.is_none() {
225+
self.set_terminator(
226+
current,
227+
TerminatorKind::SwitchInt {
228+
discr: Operand::Copy(place_len),
229+
targets: SwitchTargets::static_if(
230+
pattern_len as u128,
231+
next,
232+
else_target,
233+
),
234+
},
235+
pattern.into(),
236+
);
237+
} else {
238+
let c = Operand::from_concrete_const(
239+
pattern_len.to_le_bytes().to_vec(),
240+
MemoryMap::default(),
241+
TyBuilder::usize(),
242+
);
243+
let discr: Place =
244+
self.temp(TyBuilder::bool(), current, pattern.into())?.into();
245+
self.push_assignment(
246+
current,
247+
discr.clone(),
248+
Rvalue::CheckedBinaryOp(BinOp::Le, c, Operand::Copy(place_len)),
249+
pattern.into(),
250+
);
251+
let discr = Operand::Copy(discr);
252+
self.set_terminator(
253+
current,
254+
TerminatorKind::SwitchInt {
255+
discr,
256+
targets: SwitchTargets::static_if(1, next, else_target),
257+
},
258+
pattern.into(),
259+
);
260+
}
261+
current = next;
257262
}
258-
current = next;
259263
}
260264
for (i, &pat) in prefix.iter().enumerate() {
261265
let next_place = (&mut cond_place).project(ProjectionElem::ConstantIndex {

crates/ide-diagnostics/src/handlers/mutability_errors.rs

+21
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,27 @@ fn f() {
993993
);
994994
}
995995

996+
#[test]
997+
fn slice_pattern() {
998+
check_diagnostics(
999+
r#"
1000+
//- minicore: coerce_unsized, deref_mut, slice, copy
1001+
fn x(t: &[u8]) {
1002+
match t {
1003+
&[a, mut b] | &[a, _, mut b] => {
1004+
//^^^^^ 💡 weak: variable does not need to be mutable
1005+
1006+
a = 2;
1007+
//^^^^^ 💡 error: cannot mutate immutable variable `a`
1008+
1009+
}
1010+
_ => {}
1011+
}
1012+
}
1013+
"#,
1014+
);
1015+
}
1016+
9961017
#[test]
9971018
fn boxes() {
9981019
check_diagnostics(

0 commit comments

Comments
 (0)