mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 13:33:31 +00:00
Fix missing terminator for slice pattern
This commit is contained in:
parent
0408af6453
commit
b4907a531f
2 changed files with 70 additions and 45 deletions
|
@ -206,56 +206,60 @@ impl MirLowerCtx<'_> {
|
||||||
(current, current_else)
|
(current, current_else)
|
||||||
}
|
}
|
||||||
Pat::Slice { prefix, slice, suffix } => {
|
Pat::Slice { prefix, slice, suffix } => {
|
||||||
if let TyKind::Slice(_) = self.infer[pattern].kind(Interner) {
|
if mode == MatchingMode::Check {
|
||||||
let pattern_len = prefix.len() + suffix.len();
|
// emit runtime length check for slice
|
||||||
let place_len: Place =
|
if let TyKind::Slice(_) = self.infer[pattern].kind(Interner) {
|
||||||
self.temp(TyBuilder::usize(), current, pattern.into())?.into();
|
let pattern_len = prefix.len() + suffix.len();
|
||||||
self.push_assignment(
|
let place_len: Place =
|
||||||
current,
|
self.temp(TyBuilder::usize(), current, pattern.into())?.into();
|
||||||
place_len.clone(),
|
|
||||||
Rvalue::Len((&mut cond_place).clone()),
|
|
||||||
pattern.into(),
|
|
||||||
);
|
|
||||||
let else_target = *current_else.get_or_insert_with(|| self.new_basic_block());
|
|
||||||
let next = self.new_basic_block();
|
|
||||||
if slice.is_none() {
|
|
||||||
self.set_terminator(
|
|
||||||
current,
|
|
||||||
TerminatorKind::SwitchInt {
|
|
||||||
discr: Operand::Copy(place_len),
|
|
||||||
targets: SwitchTargets::static_if(
|
|
||||||
pattern_len as u128,
|
|
||||||
next,
|
|
||||||
else_target,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
pattern.into(),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
let c = Operand::from_concrete_const(
|
|
||||||
pattern_len.to_le_bytes().to_vec(),
|
|
||||||
MemoryMap::default(),
|
|
||||||
TyBuilder::usize(),
|
|
||||||
);
|
|
||||||
let discr: Place =
|
|
||||||
self.temp(TyBuilder::bool(), current, pattern.into())?.into();
|
|
||||||
self.push_assignment(
|
self.push_assignment(
|
||||||
current,
|
current,
|
||||||
discr.clone(),
|
place_len.clone(),
|
||||||
Rvalue::CheckedBinaryOp(BinOp::Le, c, Operand::Copy(place_len)),
|
Rvalue::Len((&mut cond_place).clone()),
|
||||||
pattern.into(),
|
|
||||||
);
|
|
||||||
let discr = Operand::Copy(discr);
|
|
||||||
self.set_terminator(
|
|
||||||
current,
|
|
||||||
TerminatorKind::SwitchInt {
|
|
||||||
discr,
|
|
||||||
targets: SwitchTargets::static_if(1, next, else_target),
|
|
||||||
},
|
|
||||||
pattern.into(),
|
pattern.into(),
|
||||||
);
|
);
|
||||||
|
let else_target =
|
||||||
|
*current_else.get_or_insert_with(|| self.new_basic_block());
|
||||||
|
let next = self.new_basic_block();
|
||||||
|
if slice.is_none() {
|
||||||
|
self.set_terminator(
|
||||||
|
current,
|
||||||
|
TerminatorKind::SwitchInt {
|
||||||
|
discr: Operand::Copy(place_len),
|
||||||
|
targets: SwitchTargets::static_if(
|
||||||
|
pattern_len as u128,
|
||||||
|
next,
|
||||||
|
else_target,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
pattern.into(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let c = Operand::from_concrete_const(
|
||||||
|
pattern_len.to_le_bytes().to_vec(),
|
||||||
|
MemoryMap::default(),
|
||||||
|
TyBuilder::usize(),
|
||||||
|
);
|
||||||
|
let discr: Place =
|
||||||
|
self.temp(TyBuilder::bool(), current, pattern.into())?.into();
|
||||||
|
self.push_assignment(
|
||||||
|
current,
|
||||||
|
discr.clone(),
|
||||||
|
Rvalue::CheckedBinaryOp(BinOp::Le, c, Operand::Copy(place_len)),
|
||||||
|
pattern.into(),
|
||||||
|
);
|
||||||
|
let discr = Operand::Copy(discr);
|
||||||
|
self.set_terminator(
|
||||||
|
current,
|
||||||
|
TerminatorKind::SwitchInt {
|
||||||
|
discr,
|
||||||
|
targets: SwitchTargets::static_if(1, next, else_target),
|
||||||
|
},
|
||||||
|
pattern.into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
current = next;
|
||||||
}
|
}
|
||||||
current = next;
|
|
||||||
}
|
}
|
||||||
for (i, &pat) in prefix.iter().enumerate() {
|
for (i, &pat) in prefix.iter().enumerate() {
|
||||||
let next_place = (&mut cond_place).project(ProjectionElem::ConstantIndex {
|
let next_place = (&mut cond_place).project(ProjectionElem::ConstantIndex {
|
||||||
|
|
|
@ -993,6 +993,27 @@ fn f() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn slice_pattern() {
|
||||||
|
check_diagnostics(
|
||||||
|
r#"
|
||||||
|
//- minicore: coerce_unsized, deref_mut, slice, copy
|
||||||
|
fn x(t: &[u8]) {
|
||||||
|
match t {
|
||||||
|
&[a, mut b] | &[a, _, mut b] => {
|
||||||
|
//^^^^^ 💡 weak: variable does not need to be mutable
|
||||||
|
|
||||||
|
a = 2;
|
||||||
|
//^^^^^ 💡 error: cannot mutate immutable variable `a`
|
||||||
|
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn boxes() {
|
fn boxes() {
|
||||||
check_diagnostics(
|
check_diagnostics(
|
||||||
|
|
Loading…
Reference in a new issue