diff options
| author | Arthur Carcano <arthur.carcano@ocamlpro.com> | 2023-01-10 11:38:53 +0100 |
|---|---|---|
| committer | Arthur Carcano <arthur.carcano@ocamlpro.com> | 2023-01-12 12:21:35 +0100 |
| commit | 797f2479974bfe0d759f4a2bd51dfef95b8d75cf (patch) | |
| tree | 3867900fa0d1270dde151fc089accebb1a04bebe /compiler/rustc_lint/src | |
| parent | 2b8590ef3bd1221830ec8a4131ea9d02b1636746 (diff) | |
| download | rust-797f2479974bfe0d759f4a2bd51dfef95b8d75cf.tar.gz rust-797f2479974bfe0d759f4a2bd51dfef95b8d75cf.zip | |
Mark ZST as FFI-safe if all its fields are PhantomData
Modify the linting behavior and add the corresponding regression test
Diffstat (limited to 'compiler/rustc_lint/src')
| -rw-r--r-- | compiler/rustc_lint/src/types.rs | 46 |
1 files changed, 23 insertions, 23 deletions
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index fa415243ba0..8bceae08a03 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -878,39 +878,39 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ) -> FfiResult<'tcx> { use FfiResult::*; - if def.repr().transparent() { + let transparent_safety = def.repr().transparent().then(|| { // Can assume that at most one field is not a ZST, so only check // that field's type for FFI-safety. if let Some(field) = transparent_newtype_field(self.cx.tcx, variant) { - self.check_field_type_for_ffi(cache, field, substs) + return self.check_field_type_for_ffi(cache, field, substs); } else { // All fields are ZSTs; this means that the type should behave - // like (), which is FFI-unsafe + // like (), which is FFI-unsafe... except if all fields are PhantomData, + // which is tested for below FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_struct_zst, help: None } } - } else { - // We can't completely trust repr(C) markings; make sure the fields are - // actually safe. - let mut all_phantom = !variant.fields.is_empty(); - for field in &variant.fields { - match self.check_field_type_for_ffi(cache, &field, substs) { - FfiSafe => { - all_phantom = false; - } - FfiPhantom(..) if def.is_enum() => { - return FfiUnsafe { - ty, - reason: fluent::lint_improper_ctypes_enum_phantomdata, - help: None, - }; - } - FfiPhantom(..) => {} - r => return r, + }); + // We can't completely trust repr(C) markings; make sure the fields are + // actually safe. + let mut all_phantom = !variant.fields.is_empty(); + for field in &variant.fields { + match self.check_field_type_for_ffi(cache, &field, substs) { + FfiSafe => { + all_phantom = false; } + FfiPhantom(..) if !def.repr().transparent() && def.is_enum() => { + return FfiUnsafe { + ty, + reason: fluent::lint_improper_ctypes_enum_phantomdata, + help: None, + }; + } + FfiPhantom(..) => {} + r => return transparent_safety.unwrap_or(r), } - - if all_phantom { FfiPhantom(ty) } else { FfiSafe } } + + if all_phantom { FfiPhantom(ty) } else { transparent_safety.unwrap_or(FfiSafe) } } /// Checks if the given type is "ffi-safe" (has a stable, well-defined |
