Skip to content

Commit 0d80e12

Browse files
committed
lint ImproperCTypes: misc. changes due to review
- relaxed the uninhabited types allowed on function return
1 parent 02d8c95 commit 0d80e12

File tree

4 files changed

+21
-96
lines changed

4 files changed

+21
-96
lines changed

compiler/rustc_lint/messages.ftl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -432,10 +432,7 @@ lint_improper_ctypes_tuple_help = consider using a struct instead
432432
lint_improper_ctypes_tuple_reason = tuples have unspecified layout
433433
434434
lint_improper_ctypes_uninhabited_enum = zero-variant enums and other uninhabited types are not allowed in function arguments and static variables
435-
lint_improper_ctypes_uninhabited_enum_deep = zero-variant enums and other uninhabited types are only allowed in function returns if used directly
436435
lint_improper_ctypes_uninhabited_never = the never type (`!`) and other uninhabited types are not allowed in function arguments and static variables
437-
lint_improper_ctypes_uninhabited_never_deep = the never type (`!`) and other uninhabited types are only allowed in function returns if used directly
438-
lint_improper_ctypes_uninhabited_use_direct = if you meant to have a function that never returns, consider setting its return type to the never type (`!`) or a zero-variant enum
439436
440437
lint_improper_ctypes_union_consider_transparent = `{$ty}` has exactly one non-zero-sized field, consider making it `#[repr(transparent)]` instead
441438
lint_improper_ctypes_union_fieldless_help = consider adding a member to this union

compiler/rustc_lint/src/types/improper_ctypes.rs

Lines changed: 16 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -581,40 +581,16 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
581581
}
582582

583583
/// Checks whether an uninhabited type (one without valid values) is safe-ish to have here
584-
fn visit_uninhabited(
585-
&self,
586-
state: CTypesVisitorState,
587-
outer_ty: Option<Ty<'tcx>>,
588-
ty: Ty<'tcx>,
589-
) -> FfiResult<'tcx> {
590-
if state.is_in_function_return()
591-
&& matches!(outer_ty.map(|ty| ty.kind()), None | Some(ty::FnPtr(..)))
592-
{
584+
fn visit_uninhabited(&self, state: CTypesVisitorState, ty: Ty<'tcx>) -> FfiResult<'tcx> {
585+
if state.is_in_function_return() {
593586
FfiResult::FfiSafe
594587
} else {
595-
let help = if state.is_in_function_return() {
596-
Some(fluent::lint_improper_ctypes_uninhabited_use_direct)
597-
} else {
598-
None
599-
};
600588
let desc = match ty.kind() {
601-
ty::Adt(..) => {
602-
if state.is_in_function_return() {
603-
fluent::lint_improper_ctypes_uninhabited_enum_deep
604-
} else {
605-
fluent::lint_improper_ctypes_uninhabited_enum
606-
}
607-
}
608-
ty::Never => {
609-
if state.is_in_function_return() {
610-
fluent::lint_improper_ctypes_uninhabited_never_deep
611-
} else {
612-
fluent::lint_improper_ctypes_uninhabited_never
613-
}
614-
}
589+
ty::Adt(..) => fluent::lint_improper_ctypes_uninhabited_enum,
590+
ty::Never => fluent::lint_improper_ctypes_uninhabited_never,
615591
r @ _ => bug!("unexpected ty_kind in uninhabited type handling: {:?}", r),
616592
};
617-
FfiResult::new_with_reason(ty, desc, help)
593+
FfiResult::new_with_reason(ty, desc, None)
618594
}
619595
}
620596

@@ -769,7 +745,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
769745
// determine if there is 0 or 1 non-1ZST field, and which it is.
770746
// (note: for enums, "transparent" means 1-variant)
771747
if ty.is_privately_uninhabited(self.cx.tcx, self.cx.typing_env()) {
772-
// let's consider transparent structs are considered unsafe if uninhabited,
748+
// let's consider transparent structs to be maybe unsafe if uninhabited,
773749
// even if that is because of fields otherwise ignored in FFI-safety checks
774750
// FIXME: and also maybe this should be "!is_inhabited_from" but from where?
775751
ffires_accumulator += variant
@@ -780,9 +756,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
780756
let mut field_res = self.visit_type(state, Some(ty), field_ty);
781757
field_res.take_with_core_note(&[
782758
fluent::lint_improper_ctypes_uninhabited_enum,
783-
fluent::lint_improper_ctypes_uninhabited_enum_deep,
784759
fluent::lint_improper_ctypes_uninhabited_never,
785-
fluent::lint_improper_ctypes_uninhabited_never_deep,
786760
])
787761
})
788762
.reduce(|r1, r2| r1 + r2)
@@ -874,19 +848,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
874848
let help = if non_1zst_count == 1
875849
&& last_non_1zst.map(|field_i| fields_ok_list[field_i]) == Some(true)
876850
{
877-
if ty.is_privately_uninhabited(self.cx.tcx, self.cx.typing_env()) {
878-
// uninhabited types can't be helped by being turned transparent
879-
None
880-
} else {
881-
match def.adt_kind() {
882-
AdtKind::Struct => {
883-
Some(fluent::lint_improper_ctypes_struct_consider_transparent)
884-
}
885-
AdtKind::Union => {
886-
Some(fluent::lint_improper_ctypes_union_consider_transparent)
887-
}
888-
AdtKind::Enum => bug!("cannot suggest an enum to be repr(transparent)"),
851+
match def.adt_kind() {
852+
AdtKind::Struct => {
853+
Some(fluent::lint_improper_ctypes_struct_consider_transparent)
889854
}
855+
AdtKind::Union => {
856+
Some(fluent::lint_improper_ctypes_union_consider_transparent)
857+
}
858+
AdtKind::Enum => bug!("cannot suggest an enum to be repr(transparent)"),
890859
}
891860
} else {
892861
None
@@ -980,7 +949,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
980949
fn visit_enum(
981950
&self,
982951
state: CTypesVisitorState,
983-
outer_ty: Option<Ty<'tcx>>,
984952
ty: Ty<'tcx>,
985953
def: AdtDef<'tcx>,
986954
args: GenericArgsRef<'tcx>,
@@ -990,7 +958,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
990958

991959
if def.variants().is_empty() {
992960
// Empty enums are implicitely handled as the never type:
993-
return self.visit_uninhabited(state, outer_ty, ty);
961+
return self.visit_uninhabited(state, ty);
994962
}
995963
// Check for a repr() attribute to specify the size of the
996964
// discriminant.
@@ -1047,9 +1015,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
10471015
let mut variant_res = self.visit_variant_fields(state, ty, def, variant, args);
10481016
variants_uninhabited_ffires[variant_i] = variant_res.take_with_core_note(&[
10491017
fluent::lint_improper_ctypes_uninhabited_enum,
1050-
fluent::lint_improper_ctypes_uninhabited_enum_deep,
10511018
fluent::lint_improper_ctypes_uninhabited_never,
1052-
fluent::lint_improper_ctypes_uninhabited_never_deep,
10531019
]);
10541020
// FIXME: check that enums allow any (up to all) variants to be phantoms?
10551021
// (previous code says no, but I don't know why? the problem with phantoms is that they're ZSTs, right?)
@@ -1107,7 +1073,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
11071073
}
11081074
self.visit_struct_or_union(state, ty, def, args)
11091075
}
1110-
AdtKind::Enum => self.visit_enum(state, outer_ty, ty, def, args),
1076+
AdtKind::Enum => self.visit_enum(state, ty, def, args),
11111077
}
11121078
}
11131079

@@ -1242,7 +1208,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
12421208

12431209
ty::Foreign(..) => FfiSafe,
12441210

1245-
ty::Never => self.visit_uninhabited(state, outer_ty, ty),
1211+
ty::Never => self.visit_uninhabited(state, ty),
12461212

12471213
// This is only half of the checking-for-opaque-aliases story:
12481214
// since they are liable to vanish on normalisation, we need a specific to find them through

tests/ui/lint/improper_ctypes/lint_uninhabited.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ struct HalfHiddenUninhabited {
3232
extern "C" {
3333

3434
fn bad_entry(e: AlsoUninhabited); //~ ERROR: uses type `AlsoUninhabited`
35-
fn bad_exit()->AlsoUninhabited; //~ ERROR: uses type `AlsoUninhabited`
35+
fn bad_exit()->AlsoUninhabited;
3636

3737
fn bad0_entry(e: Uninhabited); //~ ERROR: uses type `Uninhabited`
3838
fn bad0_exit()->Uninhabited;
@@ -46,7 +46,7 @@ fn never_exit()->!;
4646
}
4747

4848
extern "C" fn impl_bad_entry(e: AlsoUninhabited) {} //~ ERROR: uses type `AlsoUninhabited`
49-
extern "C" fn impl_bad_exit()->AlsoUninhabited { //~ ERROR: uses type `AlsoUninhabited`
49+
extern "C" fn impl_bad_exit()->AlsoUninhabited {
5050
AlsoUninhabited{
5151
a: impl_bad0_exit(),
5252
b: 0,

tests/ui/lint/improper_ctypes/lint_uninhabited.stderr

Lines changed: 3 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ error: `extern` block uses type `AlsoUninhabited`, which is not FFI-safe
44
LL | fn bad_entry(e: AlsoUninhabited);
55
| ^^^^^^^^^^^^^^^ not FFI-safe
66
|
7+
= help: `AlsoUninhabited` has exactly one non-zero-sized field, consider making it `#[repr(transparent)]` instead
78
= note: this struct/enum/union (`AlsoUninhabited`) is FFI-unsafe due to a `Uninhabited` field
89
note: the type is defined here
910
--> $DIR/lint_uninhabited.rs:12:1
@@ -22,26 +23,6 @@ note: the lint level is defined here
2223
LL | #![deny(improper_ctypes)]
2324
| ^^^^^^^^^^^^^^^
2425

25-
error: `extern` block uses type `AlsoUninhabited`, which is not FFI-safe
26-
--> $DIR/lint_uninhabited.rs:35:16
27-
|
28-
LL | fn bad_exit()->AlsoUninhabited;
29-
| ^^^^^^^^^^^^^^^ not FFI-safe
30-
|
31-
= note: this struct/enum/union (`AlsoUninhabited`) is FFI-unsafe due to a `Uninhabited` field
32-
note: the type is defined here
33-
--> $DIR/lint_uninhabited.rs:12:1
34-
|
35-
LL | struct AlsoUninhabited{
36-
| ^^^^^^^^^^^^^^^^^^^^^^
37-
= help: if you meant to have a function that never returns, consider setting its return type to the never type (`!`) or a zero-variant enum
38-
= note: zero-variant enums and other uninhabited types are only allowed in function returns if used directly
39-
note: the type is defined here
40-
--> $DIR/lint_uninhabited.rs:9:1
41-
|
42-
LL | enum Uninhabited{}
43-
| ^^^^^^^^^^^^^^^^
44-
4526
error: `extern` block uses type `Uninhabited`, which is not FFI-safe
4627
--> $DIR/lint_uninhabited.rs:37:18
4728
|
@@ -69,6 +50,7 @@ error: `extern` fn uses type `AlsoUninhabited`, which is not FFI-safe
6950
LL | extern "C" fn impl_bad_entry(e: AlsoUninhabited) {}
7051
| ^^^^^^^^^^^^^^^ not FFI-safe
7152
|
53+
= help: `AlsoUninhabited` has exactly one non-zero-sized field, consider making it `#[repr(transparent)]` instead
7254
= note: this struct/enum/union (`AlsoUninhabited`) is FFI-unsafe due to a `Uninhabited` field
7355
note: the type is defined here
7456
--> $DIR/lint_uninhabited.rs:12:1
@@ -87,26 +69,6 @@ note: the lint level is defined here
8769
LL | #![deny(improper_c_fn_definitions, improper_c_callbacks)]
8870
| ^^^^^^^^^^^^^^^^^^^^^^^^^
8971

90-
error: `extern` fn uses type `AlsoUninhabited`, which is not FFI-safe
91-
--> $DIR/lint_uninhabited.rs:49:32
92-
|
93-
LL | extern "C" fn impl_bad_exit()->AlsoUninhabited {
94-
| ^^^^^^^^^^^^^^^ not FFI-safe
95-
|
96-
= note: this struct/enum/union (`AlsoUninhabited`) is FFI-unsafe due to a `Uninhabited` field
97-
note: the type is defined here
98-
--> $DIR/lint_uninhabited.rs:12:1
99-
|
100-
LL | struct AlsoUninhabited{
101-
| ^^^^^^^^^^^^^^^^^^^^^^
102-
= help: if you meant to have a function that never returns, consider setting its return type to the never type (`!`) or a zero-variant enum
103-
= note: zero-variant enums and other uninhabited types are only allowed in function returns if used directly
104-
note: the type is defined here
105-
--> $DIR/lint_uninhabited.rs:9:1
106-
|
107-
LL | enum Uninhabited{}
108-
| ^^^^^^^^^^^^^^^^
109-
11072
error: `extern` fn uses type `Uninhabited`, which is not FFI-safe
11173
--> $DIR/lint_uninhabited.rs:56:34
11274
|
@@ -155,5 +117,5 @@ LL | struct HalfHiddenUninhabited {
155117
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
156118
= note: the never type (`!`) and other uninhabited types are not allowed in function arguments and static variables
157119

158-
error: aborting due to 9 previous errors; 1 warning emitted
120+
error: aborting due to 7 previous errors; 1 warning emitted
159121

0 commit comments

Comments
 (0)