Skip to content

Commit b142623

Browse files
committed
make it a lint again
1 parent 44cb9b1 commit b142623

File tree

8 files changed

+134
-46
lines changed

8 files changed

+134
-46
lines changed

compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ use rustc_hir::def::{CtorKind, DefKind};
1212
use rustc_hir::{LangItem, Node, attrs, find_attr, intravisit};
1313
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
1414
use rustc_infer::traits::{Obligation, ObligationCauseCode, WellFormedLoc};
15-
use rustc_lint_defs::builtin::UNSUPPORTED_CALLING_CONVENTIONS;
15+
use rustc_lint_defs::builtin::{
16+
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_CALLING_CONVENTIONS,
17+
};
1618
use rustc_middle::hir::nested_filter;
1719
use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
1820
use rustc_middle::middle::stability::EvalResult;
@@ -1510,7 +1512,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
15101512

15111513
// For each field, figure out if it has "trivial" layout (i.e., is a 1-ZST).
15121514
// Even some 1-ZST fields are not allowed though, if they have `non_exhaustive` or private
1513-
// fields or `repr(C)`. We call those fields "unsuited".
1515+
// fields or `repr(C)` or uninhabited. We call those fields "unsuited".
15141516
struct FieldInfo<'tcx> {
15151517
span: Span,
15161518
trivial: bool,
@@ -1539,6 +1541,16 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
15391541
// No need to even compute `unsuited`.
15401542
return FieldInfo { span, trivial, unsuited: None };
15411543
}
1544+
if layout.unwrap().is_uninhabited() {
1545+
// Uninhabited types aren't really "trivial"...
1546+
// See <https://github.com/rust-lang/rust/issues/135802> for some of the trouble
1547+
// this case used to cause.
1548+
return FieldInfo {
1549+
span,
1550+
trivial,
1551+
unsuited: Some(UnsuitedInfo { ty, reason: UnsuitedReason::Uninhabited }),
1552+
};
1553+
}
15421554

15431555
fn check_unsuited<'tcx>(
15441556
tcx: TyCtxt<'tcx>,
@@ -1586,15 +1598,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
15861598
}
15871599
}
15881600

1589-
FieldInfo {
1590-
span,
1591-
trivial,
1592-
unsuited: check_unsuited(tcx, adt.did(), ty).break_value().or_else(|| {
1593-
// We don't need to check this recursively, a single top-level check suffices.
1594-
let uninhabited = layout.is_ok_and(|layout| layout.is_uninhabited());
1595-
uninhabited.then_some(UnsuitedInfo { ty, reason: UnsuitedReason::Uninhabited })
1596-
}),
1597-
}
1601+
FieldInfo { span, trivial, unsuited: check_unsuited(tcx, adt.did(), ty).break_value() }
15981602
});
15991603

16001604
let non_trivial_fields = field_infos
@@ -1619,24 +1623,29 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
16191623
// If there are any non-trivial fields, then there can be no non-exhaustive 1-zsts.
16201624
// Otherwise, it's only an issue if there's >1 non-exhaustive 1-zst.
16211625
if non_trivial_count > 0 || prev_unsuited_1zst {
1622-
let mut diag = tcx.dcx().struct_span_err(
1626+
tcx.node_span_lint(
1627+
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
1628+
tcx.local_def_id_to_hir_id(adt.did().expect_local()),
16231629
field.span,
1624-
"zero-sized fields in `repr(transparent)` cannot \
1630+
|lint| {
1631+
lint.primary_message(
1632+
"zero-sized fields in `repr(transparent)` cannot \
16251633
contain external non-exhaustive types",
1626-
);
1627-
let note = match unsuited.reason {
1628-
UnsuitedReason::NonExhaustive => "is marked with `#[non_exhaustive]`",
1629-
UnsuitedReason::PrivateField => "contains private fields",
1630-
UnsuitedReason::ReprC => "is marked with `#[repr(C)]`",
1631-
UnsuitedReason::Uninhabited => "is not inhabited",
1632-
};
1633-
diag.note(format!(
1634-
"this field contains `{field_ty}`, which {note}, \
1634+
);
1635+
let note = match unsuited.reason {
1636+
UnsuitedReason::NonExhaustive => "is marked with `#[non_exhaustive]`",
1637+
UnsuitedReason::PrivateField => "contains private fields",
1638+
UnsuitedReason::ReprC => "is marked with `#[repr(C)]`",
1639+
UnsuitedReason::Uninhabited => "is not inhabited",
1640+
};
1641+
lint.note(format!(
1642+
"this field contains `{field_ty}`, which {note}, \
16351643
and makes it not a breaking change to become \
16361644
non-zero-sized in the future.",
1637-
field_ty = unsuited.ty,
1638-
));
1639-
diag.emit();
1645+
field_ty = unsuited.ty,
1646+
));
1647+
},
1648+
);
16401649
} else {
16411650
prev_unsuited_1zst = true;
16421651
}

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,66 +36,82 @@ pub struct T4(Sized, ExternalIndirection<(InternalPrivate, InternalNonExhaustive
3636
#[repr(transparent)]
3737
pub struct T5(Sized, Private);
3838
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
39+
//~| WARN this was previously accepted by the compiler
3940

4041
#[repr(transparent)]
4142
pub struct T6(Sized, NonExhaustive);
4243
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
44+
//~| WARN this was previously accepted by the compiler
4345

4446
#[repr(transparent)]
4547
pub struct T7(Sized, NonExhaustiveEnum);
4648
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
49+
//~| WARN this was previously accepted by the compiler
4750

4851
#[repr(transparent)]
4952
pub struct T8(Sized, NonExhaustiveVariant);
5053
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
54+
//~| WARN this was previously accepted by the compiler
5155

5256
#[repr(transparent)]
5357
pub struct T9(Sized, InternalIndirection<Private>);
5458
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
59+
//~| WARN this was previously accepted by the compiler
5560

5661
#[repr(transparent)]
5762
pub struct T10(Sized, InternalIndirection<NonExhaustive>);
5863
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
64+
//~| WARN this was previously accepted by the compiler
5965

6066
#[repr(transparent)]
6167
pub struct T11(Sized, InternalIndirection<NonExhaustiveEnum>);
6268
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
69+
//~| WARN this was previously accepted by the compiler
6370

6471
#[repr(transparent)]
6572
pub struct T12(Sized, InternalIndirection<NonExhaustiveVariant>);
6673
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
74+
//~| WARN this was previously accepted by the compiler
6775

6876
#[repr(transparent)]
6977
pub struct T13(Sized, ExternalIndirection<Private>);
7078
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
79+
//~| WARN this was previously accepted by the compiler
7180

7281
#[repr(transparent)]
7382
pub struct T14(Sized, ExternalIndirection<NonExhaustive>);
7483
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
84+
//~| WARN this was previously accepted by the compiler
7585

7686
#[repr(transparent)]
7787
pub struct T15(Sized, ExternalIndirection<NonExhaustiveEnum>);
7888
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
89+
//~| WARN this was previously accepted by the compiler
7990

8091
#[repr(transparent)]
8192
pub struct T16(Sized, ExternalIndirection<NonExhaustiveVariant>);
8293
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
94+
//~| WARN this was previously accepted by the compiler
8395

8496
#[repr(transparent)]
8597
pub struct T17(NonExhaustive, Sized);
8698
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
99+
//~| WARN this was previously accepted by the compiler
87100

88101
#[repr(transparent)]
89102
pub struct T18(NonExhaustive, NonExhaustive);
90103
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
104+
//~| WARN this was previously accepted by the compiler
91105

92106
#[repr(transparent)]
93107
pub struct T19(NonExhaustive, Private);
94108
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
109+
//~| WARN this was previously accepted by the compiler
95110

96111
#[repr(transparent)]
97112
pub struct T19Flipped(Private, NonExhaustive);
98113
//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
114+
//~| WARN this was previously accepted by the compiler
99115

100116
#[repr(transparent)]
101117
pub struct T20(NonExhaustive);

0 commit comments

Comments
 (0)