From b4907a531f596b54ed6fe66d0f208b76179f5e06 Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Sun, 4 Jun 2023 20:59:27 +0330 Subject: [PATCH] Fix missing terminator for slice pattern --- .../hir-ty/src/mir/lower/pattern_matching.rs | 94 ++++++++++--------- .../src/handlers/mutability_errors.rs | 21 +++++ 2 files changed, 70 insertions(+), 45 deletions(-) diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs index 5cd1be6842..ff43c64a9e 100644 --- a/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -206,56 +206,60 @@ impl MirLowerCtx<'_> { (current, current_else) } Pat::Slice { prefix, slice, suffix } => { - if let TyKind::Slice(_) = self.infer[pattern].kind(Interner) { - let pattern_len = prefix.len() + suffix.len(); - let place_len: Place = - self.temp(TyBuilder::usize(), current, pattern.into())?.into(); - self.push_assignment( - current, - 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(); + if mode == MatchingMode::Check { + // emit runtime length check for slice + if let TyKind::Slice(_) = self.infer[pattern].kind(Interner) { + let pattern_len = prefix.len() + suffix.len(); + let place_len: Place = + self.temp(TyBuilder::usize(), 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), - }, + 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( + 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() { let next_place = (&mut cond_place).project(ProjectionElem::ConstantIndex { diff --git a/crates/ide-diagnostics/src/handlers/mutability_errors.rs b/crates/ide-diagnostics/src/handlers/mutability_errors.rs index 8795afc2d9..f61460e317 100644 --- a/crates/ide-diagnostics/src/handlers/mutability_errors.rs +++ b/crates/ide-diagnostics/src/handlers/mutability_errors.rs @@ -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] fn boxes() { check_diagnostics(