Skip to content

Commit 23d37e3

Browse files
committed
Not lint pub structs without pub constructors if containing fields of unit, never type, PhantomData and positional ZST
1 parent 73a2281 commit 23d37e3

File tree

4 files changed

+76
-22
lines changed

4 files changed

+76
-22
lines changed

compiler/rustc_passes/src/dead.rs

+17-17
Original file line numberDiff line numberDiff line change
@@ -55,24 +55,24 @@ impl Publicness {
5555
}
5656

5757
fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: DefId) -> bool {
58-
// treat PhantomData and positional ZST as public,
59-
// we don't want to lint types which only have them,
60-
// cause it's a common way to use such types to check things like well-formedness
61-
tcx.adt_def(id).all_fields().all(|field| {
58+
// skip types contain fields of unit and never type,
59+
// it's usually intentional to make the type not constructible
60+
let not_require_constructor = tcx.adt_def(id).all_fields().any(|field| {
6261
let field_type = tcx.type_of(field.did).instantiate_identity();
63-
if field_type.is_phantom_data() {
64-
return true;
65-
}
66-
let is_positional = field.name.as_str().starts_with(|c: char| c.is_ascii_digit());
67-
if is_positional
68-
&& tcx
69-
.layout_of(tcx.param_env(field.did).and(field_type))
70-
.map_or(true, |layout| layout.is_zst())
71-
{
72-
return true;
73-
}
74-
field.vis.is_public()
75-
})
62+
field_type.is_unit() || field_type.is_never()
63+
});
64+
65+
not_require_constructor
66+
|| tcx.adt_def(id).all_fields().all(|field| {
67+
let field_type = tcx.type_of(field.did).instantiate_identity();
68+
// skip fields of PhantomData,
69+
// cause it's a common way to check things like well-formedness
70+
if field_type.is_phantom_data() {
71+
return true;
72+
}
73+
74+
field.vis.is_public()
75+
})
7676
}
7777

7878
/// check struct and its fields are public or not,

tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#![forbid(dead_code)]
22

33
#[derive(Debug)]
4-
pub struct Whatever { //~ ERROR struct `Whatever` is never constructed
4+
pub struct Whatever {
55
pub field0: (),
6-
field1: (),
6+
field1: (), //~ ERROR fields `field1`, `field2`, `field3`, and `field4` are never read
77
field2: (),
88
field3: (),
99
field4: (),

tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
1-
error: struct `Whatever` is never constructed
2-
--> $DIR/clone-debug-dead-code-in-the-same-struct.rs:4:12
1+
error: fields `field1`, `field2`, `field3`, and `field4` are never read
2+
--> $DIR/clone-debug-dead-code-in-the-same-struct.rs:6:5
33
|
44
LL | pub struct Whatever {
5-
| ^^^^^^^^
5+
| -------- fields in this struct
6+
LL | pub field0: (),
7+
LL | field1: (),
8+
| ^^^^^^
9+
LL | field2: (),
10+
| ^^^^^^
11+
LL | field3: (),
12+
| ^^^^^^
13+
LL | field4: (),
14+
| ^^^^^^
615
|
16+
= note: `Whatever` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
717
note: the lint level is defined here
818
--> $DIR/clone-debug-dead-code-in-the-same-struct.rs:1:11
919
|
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//@ check-pass
2+
3+
#![feature(never_type)]
4+
5+
pub struct T1(!);
6+
7+
pub struct T2(!, i32);
8+
9+
pub struct T3(());
10+
11+
pub struct T4((), i32);
12+
13+
pub struct T5<X>(std::marker::PhantomData<X>);
14+
15+
pub struct T6<X>(std::marker::PhantomData<X>, i32);
16+
17+
pub struct T7 {
18+
_x: !,
19+
}
20+
21+
pub struct T8<X> {
22+
_x: !,
23+
_y: X,
24+
}
25+
26+
pub struct T9 {
27+
_x: (),
28+
}
29+
30+
pub struct T10<X> {
31+
_x: (),
32+
_y: X,
33+
}
34+
35+
pub struct T11<X> {
36+
_x: std::marker::PhantomData<X>,
37+
}
38+
39+
pub struct T12<X> {
40+
_x: std::marker::PhantomData<X>,
41+
_y: i32,
42+
}
43+
44+
fn main() {}

0 commit comments

Comments
 (0)