Skip to content

Commit 1087295

Browse files
committed
Auto merge of rust-lang#15789 - HKalbasi:unused-var, r=HKalbasi
Store binding mode for each instance of a binding independently fix rust-lang#15787
2 parents 7c11399 + 8b82ea4 commit 1087295

File tree

8 files changed

+53
-9
lines changed

8 files changed

+53
-9
lines changed

crates/hir-ty/src/consteval/tests.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,6 +1159,20 @@ fn pattern_matching_slice() {
11591159
"#,
11601160
33213,
11611161
);
1162+
check_number(
1163+
r#"
1164+
//- minicore: slice, index, coerce_unsized, copy
1165+
const fn f(mut slice: &[u32]) -> usize {
1166+
slice = match slice {
1167+
[0, rest @ ..] | rest => rest,
1168+
};
1169+
slice.len()
1170+
}
1171+
const GOAL: usize = f(&[]) + f(&[10]) + f(&[0, 100])
1172+
+ f(&[1000, 1000, 1000]) + f(&[0, 57, 34, 46, 10000, 10000]);
1173+
"#,
1174+
10,
1175+
);
11621176
}
11631177

11641178
#[test]

crates/hir-ty/src/diagnostics/match_check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ impl<'a> PatCtxt<'a> {
147147
}
148148

149149
hir_def::hir::Pat::Bind { id, subpat, .. } => {
150-
let bm = self.infer.binding_modes[id];
150+
let bm = self.infer.binding_modes[pat];
151151
ty = &self.infer[id];
152152
let name = &self.body.bindings[id].name;
153153
match (bm, ty.kind(Interner)) {

crates/hir-ty/src/infer.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,19 @@ pub struct InferenceResult {
420420
standard_types: InternedStandardTypes,
421421
/// Stores the types which were implicitly dereferenced in pattern binding modes.
422422
pub pat_adjustments: FxHashMap<PatId, Vec<Ty>>,
423-
pub binding_modes: ArenaMap<BindingId, BindingMode>,
423+
/// Stores the binding mode (`ref` in `let ref x = 2`) of bindings.
424+
///
425+
/// This one is tied to the `PatId` instead of `BindingId`, because in some rare cases, a binding in an
426+
/// or pattern can have multiple binding modes. For example:
427+
/// ```
428+
/// fn foo(mut slice: &[u32]) -> usize {
429+
/// slice = match slice {
430+
/// [0, rest @ ..] | rest => rest,
431+
/// };
432+
/// }
433+
/// ```
434+
/// the first `rest` has implicit `ref` binding mode, but the second `rest` binding mode is `move`.
435+
pub binding_modes: ArenaMap<PatId, BindingMode>,
424436
pub expr_adjustments: FxHashMap<ExprId, Vec<Adjustment>>,
425437
pub(crate) closure_info: FxHashMap<ClosureId, (Vec<CapturedItem>, FnTrait)>,
426438
// FIXME: remove this field

crates/hir-ty/src/infer/closure.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ impl InferenceContext<'_> {
679679
| Pat::Range { .. } => {
680680
update_result(CaptureKind::ByRef(BorrowKind::Shared));
681681
}
682-
Pat::Bind { id, .. } => match self.result.binding_modes[*id] {
682+
Pat::Bind { id, .. } => match self.result.binding_modes[p] {
683683
crate::BindingMode::Move => {
684684
if self.is_ty_copy(self.result.type_of_binding[*id].clone()) {
685685
update_result(CaptureKind::ByRef(BorrowKind::Shared));
@@ -838,8 +838,8 @@ impl InferenceContext<'_> {
838838
| Pat::ConstBlock(_)
839839
| Pat::Path(_)
840840
| Pat::Lit(_) => self.consume_place(place, pat.into()),
841-
Pat::Bind { id, subpat: _ } => {
842-
let mode = self.result.binding_modes[*id];
841+
Pat::Bind { id: _, subpat: _ } => {
842+
let mode = self.result.binding_modes[pat];
843843
let capture_kind = match mode {
844844
BindingMode::Move => {
845845
self.consume_place(place, pat.into());

crates/hir-ty/src/infer/pat.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ impl InferenceContext<'_> {
421421
} else {
422422
BindingMode::convert(mode)
423423
};
424-
self.result.binding_modes.insert(binding, mode);
424+
self.result.binding_modes.insert(pat, mode);
425425

426426
let inner_ty = match subpat {
427427
Some(subpat) => self.infer_pat(subpat, &expected, default_bm),

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ impl MirLowerCtx<'_> {
284284
);
285285
(current, current_else) = self.pattern_match_binding(
286286
id,
287+
*slice,
287288
next_place,
288289
(*slice).into(),
289290
current,
@@ -395,6 +396,7 @@ impl MirLowerCtx<'_> {
395396
if mode == MatchingMode::Bind {
396397
self.pattern_match_binding(
397398
*id,
399+
pattern,
398400
cond_place,
399401
pattern.into(),
400402
current,
@@ -431,13 +433,14 @@ impl MirLowerCtx<'_> {
431433
fn pattern_match_binding(
432434
&mut self,
433435
id: BindingId,
436+
pat: PatId,
434437
cond_place: Place,
435438
span: MirSpan,
436439
current: BasicBlockId,
437440
current_else: Option<BasicBlockId>,
438441
) -> Result<(BasicBlockId, Option<BasicBlockId>)> {
439442
let target_place = self.binding_local(id)?;
440-
let mode = self.infer.binding_modes[id];
443+
let mode = self.infer.binding_modes[pat];
441444
self.push_storage_live(id, current)?;
442445
self.push_assignment(
443446
current,

crates/hir/src/source_analyzer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,9 +236,9 @@ impl SourceAnalyzer {
236236
_db: &dyn HirDatabase,
237237
pat: &ast::IdentPat,
238238
) -> Option<BindingMode> {
239-
let binding_id = self.binding_id_of_pat(pat)?;
239+
let id = self.pat_id(&pat.clone().into())?;
240240
let infer = self.infer.as_ref()?;
241-
infer.binding_modes.get(binding_id).map(|bm| match bm {
241+
infer.binding_modes.get(id).map(|bm| match bm {
242242
hir_ty::BindingMode::Move => BindingMode::Move,
243243
hir_ty::BindingMode::Ref(hir_ty::Mutability::Mut) => BindingMode::Ref(Mutability::Mut),
244244
hir_ty::BindingMode::Ref(hir_ty::Mutability::Not) => {

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,4 +175,19 @@ fn main() {
175175
"#,
176176
);
177177
}
178+
179+
#[test]
180+
fn regression_15787() {
181+
check_diagnostics(
182+
r#"
183+
//- minicore: coerce_unsized, slice, copy
184+
fn foo(mut slice: &[u32]) -> usize {
185+
slice = match slice {
186+
[0, rest @ ..] | rest => rest,
187+
};
188+
slice.len()
189+
}
190+
"#,
191+
);
192+
}
178193
}

0 commit comments

Comments
 (0)