Skip to content

Commit 012a458

Browse files
author
Gurinder Singh
committed
Suggest removing unused tuple fields if they are the last fields
1 parent 47314eb commit 012a458

File tree

5 files changed

+109
-45
lines changed

5 files changed

+109
-45
lines changed

compiler/rustc_passes/messages.ftl

+9
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,15 @@ passes_pass_by_value =
597597
598598
passes_proc_macro_bad_sig = {$kind} has incorrect signature
599599
600+
passes_remove_fields =
601+
consider removing { $num ->
602+
[one] this
603+
*[other] these
604+
} { $num ->
605+
[one] field
606+
*[other] fields
607+
}
608+
600609
passes_repr_conflicting =
601610
conflicting representation hints
602611

compiler/rustc_passes/src/dead.rs

+45-13
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ use rustc_target::abi::FieldIdx;
2323
use std::mem;
2424

2525
use crate::errors::{
26-
ChangeFieldsToBeOfUnitType, IgnoredDerivedImpls, MultipleDeadCodes, ParentInfo,
27-
UselessAssignment,
26+
ChangeFields, IgnoredDerivedImpls, MultipleDeadCodes, ParentInfo, UselessAssignment,
2827
};
2928

3029
// Any local node that may call something in its body block should be
@@ -993,17 +992,50 @@ impl<'tcx> DeadVisitor<'tcx> {
993992
};
994993

995994
let diag = match report_on {
996-
ReportOn::TupleField => MultipleDeadCodes::UnusedTupleStructFields {
997-
multiple,
998-
num,
999-
descr,
1000-
participle,
1001-
name_list,
1002-
change_fields_suggestion: ChangeFieldsToBeOfUnitType { num, spans: spans.clone() },
1003-
parent_info,
1004-
ignored_derived_impls,
1005-
},
1006-
995+
ReportOn::TupleField => {
996+
let tuple_fields = if let Some(parent_id) = parent_item
997+
&& let node = tcx.hir_node_by_def_id(parent_id)
998+
&& let hir::Node::Item(hir::Item {
999+
kind: hir::ItemKind::Struct(hir::VariantData::Tuple(fields, _, _), _),
1000+
..
1001+
}) = node
1002+
{
1003+
*fields
1004+
} else {
1005+
&[]
1006+
};
1007+
1008+
let trailing_tuple_fields = if tuple_fields.len() >= dead_codes.len() {
1009+
LocalDefIdSet::from_iter(
1010+
tuple_fields
1011+
.iter()
1012+
.skip(tuple_fields.len() - dead_codes.len())
1013+
.map(|f| f.def_id),
1014+
)
1015+
} else {
1016+
LocalDefIdSet::default()
1017+
};
1018+
1019+
let fields_suggestion =
1020+
// Suggest removal if all tuple fields are at the end.
1021+
// Otherwise suggest removal or changing to unit type
1022+
if dead_codes.iter().all(|dc| trailing_tuple_fields.contains(&dc.def_id)) {
1023+
ChangeFields::Remove { num }
1024+
} else {
1025+
ChangeFields::ChangeToUnitTypeOrRemove { num, spans: spans.clone() }
1026+
};
1027+
1028+
MultipleDeadCodes::UnusedTupleStructFields {
1029+
multiple,
1030+
num,
1031+
descr,
1032+
participle,
1033+
name_list,
1034+
change_fields_suggestion: fields_suggestion,
1035+
parent_info,
1036+
ignored_derived_impls,
1037+
}
1038+
}
10071039
ReportOn::NamedField => MultipleDeadCodes::DeadCodes {
10081040
multiple,
10091041
num,

compiler/rustc_passes/src/errors.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -1589,7 +1589,7 @@ pub enum MultipleDeadCodes<'tcx> {
15891589
participle: &'tcx str,
15901590
name_list: DiagSymbolList,
15911591
#[subdiagnostic]
1592-
change_fields_suggestion: ChangeFieldsToBeOfUnitType,
1592+
change_fields_suggestion: ChangeFields,
15931593
#[subdiagnostic]
15941594
parent_info: Option<ParentInfo<'tcx>>,
15951595
#[subdiagnostic]
@@ -1616,11 +1616,18 @@ pub struct IgnoredDerivedImpls {
16161616
}
16171617

16181618
#[derive(Subdiagnostic)]
1619-
#[multipart_suggestion(passes_change_fields_to_be_of_unit_type, applicability = "has-placeholders")]
1620-
pub struct ChangeFieldsToBeOfUnitType {
1621-
pub num: usize,
1622-
#[suggestion_part(code = "()")]
1623-
pub spans: Vec<Span>,
1619+
pub enum ChangeFields {
1620+
#[multipart_suggestion(
1621+
passes_change_fields_to_be_of_unit_type,
1622+
applicability = "has-placeholders"
1623+
)]
1624+
ChangeToUnitTypeOrRemove {
1625+
num: usize,
1626+
#[suggestion_part(code = "()")]
1627+
spans: Vec<Span>,
1628+
},
1629+
#[help(passes_remove_fields)]
1630+
Remove { num: usize },
16241631
}
16251632

16261633
#[derive(Diagnostic)]

tests/ui/lint/dead-code/tuple-struct-field.rs

+20-11
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,20 @@ use std::marker::PhantomData;
55

66
const LEN: usize = 4;
77

8-
struct SingleUnused(i32, [u8; LEN], String);
9-
//~^ ERROR: field `1` is never read
8+
struct UnusedAtTheEnd(i32, f32, [u8; LEN], String, u8);
9+
//~^ ERROR:fields `1`, `2`, `3`, and `4` are never read
10+
//~| NOTE: fields in this struct
11+
//~| HELP: consider removing these fields
12+
13+
struct UnusedJustOneField(i32);
14+
//~^ ERROR: field `0` is never read
1015
//~| NOTE: field in this struct
11-
//~| HELP: consider changing the field to be of unit type
16+
//~| HELP: consider removing this field
1217

13-
struct MultipleUnused(i32, f32, String, u8);
14-
//~^ ERROR: fields `0`, `1`, `2`, and `3` are never read
18+
struct UnusedInTheMiddle(i32, f32, String, u8, u32);
19+
//~^ ERROR: fields `1`, `2`, and `4` are never read
1520
//~| NOTE: fields in this struct
16-
//~| HELP: consider changing the fields to be of unit type
21+
//~| HELP: consider changing the fields to be of unit type to suppress this warning while preserving the field numbering, or remove the fields
1722

1823
struct GoodUnit(());
1924

@@ -23,15 +28,19 @@ struct Void;
2328
struct GoodVoid(Void);
2429

2530
fn main() {
26-
let w = SingleUnused(42, [0, 1, 2, 3], "abc".to_string());
27-
let _ = w.0;
28-
let _ = w.2;
31+
let u1 = UnusedAtTheEnd(42, 3.14, [0, 1, 2, 3], "def".to_string(), 4u8);
32+
let _ = u1.0;
33+
34+
let _ = UnusedJustOneField(42);
35+
36+
let u2 = UnusedInTheMiddle(42, 3.14, "def".to_string(), 4u8, 5);
37+
let _ = u2.0;
38+
let _ = u2.3;
2939

30-
let m = MultipleUnused(42, 3.14, "def".to_string(), 4u8);
3140

3241
let gu = GoodUnit(());
3342
let gp = GoodPhantom(PhantomData);
3443
let gv = GoodVoid(Void);
3544

36-
let _ = (gu, gp, gv, m);
45+
let _ = (gu, gp, gv);
3746
}
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,40 @@
1-
error: field `1` is never read
2-
--> $DIR/tuple-struct-field.rs:8:26
1+
error: fields `1`, `2`, `3`, and `4` are never read
2+
--> $DIR/tuple-struct-field.rs:8:28
33
|
4-
LL | struct SingleUnused(i32, [u8; LEN], String);
5-
| ------------ ^^^^^^^^^
4+
LL | struct UnusedAtTheEnd(i32, f32, [u8; LEN], String, u8);
5+
| -------------- ^^^ ^^^^^^^^^ ^^^^^^ ^^
66
| |
7-
| field in this struct
7+
| fields in this struct
88
|
9+
= help: consider removing these fields
910
note: the lint level is defined here
1011
--> $DIR/tuple-struct-field.rs:1:9
1112
|
1213
LL | #![deny(dead_code)]
1314
| ^^^^^^^^^
14-
help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
15+
16+
error: field `0` is never read
17+
--> $DIR/tuple-struct-field.rs:13:27
18+
|
19+
LL | struct UnusedJustOneField(i32);
20+
| ------------------ ^^^
21+
| |
22+
| field in this struct
1523
|
16-
LL | struct SingleUnused(i32, (), String);
17-
| ~~
24+
= help: consider removing this field
1825

19-
error: fields `0`, `1`, `2`, and `3` are never read
20-
--> $DIR/tuple-struct-field.rs:13:23
26+
error: fields `1`, `2`, and `4` are never read
27+
--> $DIR/tuple-struct-field.rs:18:31
2128
|
22-
LL | struct MultipleUnused(i32, f32, String, u8);
23-
| -------------- ^^^ ^^^ ^^^^^^ ^^
29+
LL | struct UnusedInTheMiddle(i32, f32, String, u8, u32);
30+
| ----------------- ^^^ ^^^^^^ ^^^
2431
| |
2532
| fields in this struct
2633
|
2734
help: consider changing the fields to be of unit type to suppress this warning while preserving the field numbering, or remove the fields
2835
|
29-
LL | struct MultipleUnused((), (), (), ());
30-
| ~~ ~~ ~~ ~~
36+
LL | struct UnusedInTheMiddle(i32, (), (), u8, ());
37+
| ~~ ~~ ~~
3138

32-
error: aborting due to 2 previous errors
39+
error: aborting due to 3 previous errors
3340

0 commit comments

Comments
 (0)