Skip to content

Commit 54c33d3

Browse files
Don't complain on a single non-exhaustive 1-zst
1 parent 10b88f8 commit 54c33d3

File tree

3 files changed

+87
-20
lines changed

3 files changed

+87
-20
lines changed

compiler/rustc_hir_analysis/src/check/check.rs

+29-19
Original file line numberDiff line numberDiff line change
@@ -1201,25 +1201,35 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
12011201
);
12021202
return;
12031203
}
1204-
for (span, _trivial, non_exhaustive) in field_infos {
1205-
if let Some((descr, def_id, args, non_exhaustive)) = non_exhaustive {
1206-
tcx.struct_span_lint_hir(
1207-
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
1208-
tcx.hir().local_def_id_to_hir_id(adt.did().expect_local()),
1209-
span,
1210-
"zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types",
1211-
|lint| {
1212-
let note = if non_exhaustive {
1213-
"is marked with `#[non_exhaustive]`"
1214-
} else {
1215-
"contains private fields"
1216-
};
1217-
let field_ty = tcx.def_path_str_with_args(def_id, args);
1218-
lint
1219-
.note(format!("this {descr} contains `{field_ty}`, which {note}, \
1220-
and makes it not a breaking change to become non-zero-sized in the future."))
1221-
},
1222-
)
1204+
let mut prev_non_exhaustive_1zst = false;
1205+
for (span, _trivial, non_exhaustive_1zst) in field_infos {
1206+
if let Some((descr, def_id, args, non_exhaustive)) = non_exhaustive_1zst {
1207+
// If there are any non-trivial fields, then there can be no non-exhaustive 1-zsts.
1208+
// Otherwise, it's only an issue if there's >1 non-exhaustive 1-zst.
1209+
if non_trivial_count > 0 || prev_non_exhaustive_1zst {
1210+
tcx.struct_span_lint_hir(
1211+
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
1212+
tcx.hir().local_def_id_to_hir_id(adt.did().expect_local()),
1213+
span,
1214+
"zero-sized fields in `repr(transparent)` cannot \
1215+
contain external non-exhaustive types",
1216+
|lint| {
1217+
let note = if non_exhaustive {
1218+
"is marked with `#[non_exhaustive]`"
1219+
} else {
1220+
"contains private fields"
1221+
};
1222+
let field_ty = tcx.def_path_str_with_args(def_id, args);
1223+
lint.note(format!(
1224+
"this {descr} contains `{field_ty}`, which {note}, \
1225+
and makes it not a breaking change to become \
1226+
non-zero-sized in the future."
1227+
))
1228+
},
1229+
)
1230+
} else {
1231+
prev_non_exhaustive_1zst = true;
1232+
}
12231233
}
12241234
}
12251235
}

tests/ui/repr/repr-transparent-non-exhaustive.rs

+27
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,31 @@ pub struct T16(Sized, ExternalIndirection<NonExhaustiveVariant>);
9393
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
9494
//~| WARN this was previously accepted by the compiler
9595

96+
#[repr(transparent)]
97+
pub struct T17(NonExhaustive, Sized);
98+
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
99+
//~| WARN this was previously accepted by the compiler
100+
101+
#[repr(transparent)]
102+
pub struct T18(NonExhaustive, NonExhaustive);
103+
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
104+
//~| WARN this was previously accepted by the compiler
105+
106+
#[repr(transparent)]
107+
pub struct T19(NonExhaustive, Private);
108+
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
109+
//~| WARN this was previously accepted by the compiler
110+
111+
#[repr(transparent)]
112+
pub struct T20(NonExhaustive);
113+
// Okay, since it's the only field.
114+
115+
#[repr(transparent)]
116+
pub struct T21(NonExhaustive, InternalNonExhaustive);
117+
// Okay, since there's only 1 foreign non-exhaustive type.
118+
119+
#[repr(transparent)]
120+
pub struct T22(NonExhaustive, InternalPrivate);
121+
// Okay, since there's only 1 foreign non-exhaustive type.
122+
96123
fn main() {}

tests/ui/repr/repr-transparent-non-exhaustive.stderr

+31-1
Original file line numberDiff line numberDiff line change
@@ -123,5 +123,35 @@ LL | pub struct T16(Sized, ExternalIndirection<NonExhaustiveVariant>);
123123
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
124124
= note: this enum contains `NonExhaustiveVariant`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future.
125125

126-
error: aborting due to 12 previous errors
126+
error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
127+
--> $DIR/repr-transparent-non-exhaustive.rs:97:16
128+
|
129+
LL | pub struct T17(NonExhaustive, Sized);
130+
| ^^^^^^^^^^^^^
131+
|
132+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
133+
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
134+
= note: this struct contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future.
135+
136+
error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
137+
--> $DIR/repr-transparent-non-exhaustive.rs:102:31
138+
|
139+
LL | pub struct T18(NonExhaustive, NonExhaustive);
140+
| ^^^^^^^^^^^^^
141+
|
142+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
143+
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
144+
= note: this struct contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future.
145+
146+
error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
147+
--> $DIR/repr-transparent-non-exhaustive.rs:107:31
148+
|
149+
LL | pub struct T19(NonExhaustive, Private);
150+
| ^^^^^^^
151+
|
152+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
153+
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
154+
= note: this struct contains `Private`, which contains private fields, and makes it not a breaking change to become non-zero-sized in the future.
155+
156+
error: aborting due to 15 previous errors
127157

0 commit comments

Comments
 (0)