Skip to content

Commit 60b9c5d

Browse files
authored
Rollup merge of #88871 - FabianWolff:issue-88403, r=jackh726
Fix suggestion for nested struct patterns Fixes #88403, and also a similar problem where the unused binding is in a function parameter pattern.
2 parents eb86098 + 2bff77d commit 60b9c5d

File tree

4 files changed

+75
-8
lines changed

4 files changed

+75
-8
lines changed

compiler/rustc_passes/src/liveness.rs

+15-8
Original file line numberDiff line numberDiff line change
@@ -265,21 +265,24 @@ impl IrMaps<'tcx> {
265265
self.capture_info_map.insert(hir_id, Rc::new(cs));
266266
}
267267

268-
fn add_from_pat(&mut self, pat: &hir::Pat<'tcx>) {
268+
fn collect_shorthand_field_ids(&self, pat: &hir::Pat<'tcx>) -> HirIdSet {
269269
// For struct patterns, take note of which fields used shorthand
270270
// (`x` rather than `x: x`).
271271
let mut shorthand_field_ids = HirIdSet::default();
272272
let mut pats = VecDeque::new();
273273
pats.push_back(pat);
274+
274275
while let Some(pat) = pats.pop_front() {
275276
use rustc_hir::PatKind::*;
276277
match &pat.kind {
277278
Binding(.., inner_pat) => {
278279
pats.extend(inner_pat.iter());
279280
}
280281
Struct(_, fields, _) => {
281-
let ids = fields.iter().filter(|f| f.is_shorthand).map(|f| f.pat.hir_id);
282-
shorthand_field_ids.extend(ids);
282+
let (short, not_short): (Vec<&_>, Vec<&_>) =
283+
fields.iter().partition(|f| f.is_shorthand);
284+
shorthand_field_ids.extend(short.iter().map(|f| f.pat.hir_id));
285+
pats.extend(not_short.iter().map(|f| f.pat));
283286
}
284287
Ref(inner_pat, _) | Box(inner_pat) => {
285288
pats.push_back(inner_pat);
@@ -296,6 +299,12 @@ impl IrMaps<'tcx> {
296299
}
297300
}
298301

302+
return shorthand_field_ids;
303+
}
304+
305+
fn add_from_pat(&mut self, pat: &hir::Pat<'tcx>) {
306+
let shorthand_field_ids = self.collect_shorthand_field_ids(pat);
307+
299308
pat.each_binding(|_, hir_id, _, ident| {
300309
self.add_live_node_for_node(hir_id, VarDefNode(ident.span, hir_id));
301310
self.add_variable(Local(LocalInfo {
@@ -373,15 +382,13 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
373382
}
374383

375384
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
385+
let shorthand_field_ids = self.collect_shorthand_field_ids(param.pat);
376386
param.pat.each_binding(|_bm, hir_id, _x, ident| {
377387
let var = match param.pat.kind {
378-
rustc_hir::PatKind::Struct(_, fields, _) => Local(LocalInfo {
388+
rustc_hir::PatKind::Struct(..) => Local(LocalInfo {
379389
id: hir_id,
380390
name: ident.name,
381-
is_shorthand: fields
382-
.iter()
383-
.find(|f| f.ident == ident)
384-
.map_or(false, |f| f.is_shorthand),
391+
is_shorthand: shorthand_field_ids.contains(&hir_id),
385392
}),
386393
_ => Param(hir_id, ident.name),
387394
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Regression test for #88403, where prefixing with an underscore was
2+
// erroneously suggested for a nested shorthand struct field binding.
3+
4+
// run-rustfix
5+
#![allow(unused)]
6+
#![forbid(unused_variables)]
7+
8+
struct Inner { i: i32 }
9+
struct Outer { o: Inner }
10+
11+
fn foo(Outer { o: Inner { i: _ } }: Outer) {}
12+
//~^ ERROR: unused variable: `i`
13+
//~| HELP: try ignoring the field
14+
15+
fn main() {
16+
let s = Outer { o: Inner { i: 42 } };
17+
let Outer { o: Inner { i: _ } } = s;
18+
//~^ ERROR: unused variable: `i`
19+
//~| HELP: try ignoring the field
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Regression test for #88403, where prefixing with an underscore was
2+
// erroneously suggested for a nested shorthand struct field binding.
3+
4+
// run-rustfix
5+
#![allow(unused)]
6+
#![forbid(unused_variables)]
7+
8+
struct Inner { i: i32 }
9+
struct Outer { o: Inner }
10+
11+
fn foo(Outer { o: Inner { i } }: Outer) {}
12+
//~^ ERROR: unused variable: `i`
13+
//~| HELP: try ignoring the field
14+
15+
fn main() {
16+
let s = Outer { o: Inner { i: 42 } };
17+
let Outer { o: Inner { i } } = s;
18+
//~^ ERROR: unused variable: `i`
19+
//~| HELP: try ignoring the field
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: unused variable: `i`
2+
--> $DIR/ignore-nested-field-binding.rs:11:27
3+
|
4+
LL | fn foo(Outer { o: Inner { i } }: Outer) {}
5+
| ^ help: try ignoring the field: `i: _`
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/ignore-nested-field-binding.rs:6:11
9+
|
10+
LL | #![forbid(unused_variables)]
11+
| ^^^^^^^^^^^^^^^^
12+
13+
error: unused variable: `i`
14+
--> $DIR/ignore-nested-field-binding.rs:17:28
15+
|
16+
LL | let Outer { o: Inner { i } } = s;
17+
| ^ help: try ignoring the field: `i: _`
18+
19+
error: aborting due to 2 previous errors
20+

0 commit comments

Comments
 (0)