diff options
| author | David Wood <david.wood@huawei.com> | 2023-07-19 09:42:11 +0100 |
|---|---|---|
| committer | David Wood <david.wood@huawei.com> | 2023-07-19 09:59:04 +0100 |
| commit | 24f90fdd2654e9c5437a684d3a72a4e70826a985 (patch) | |
| tree | 29f98ae7d7ae66b4713a09d543e05e727498c5d9 /compiler | |
| parent | 99b1897cf640d5f6dac74416761c9b3c75e1ef7a (diff) | |
| download | rust-24f90fdd2654e9c5437a684d3a72a4e70826a985.tar.gz rust-24f90fdd2654e9c5437a684d3a72a4e70826a985.zip | |
lint/ctypes: allow `()` within types
Consider `()` within types to be FFI-safe, and `()` to be FFI-safe as a return type (incl. when in a transparent newtype). Signed-off-by: David Wood <david@davidtw.co>
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_lint/src/types.rs | 47 |
1 files changed, 15 insertions, 32 deletions
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 7fef88a5391..85bac7588b0 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -943,30 +943,6 @@ pub(crate) fn repr_nullable_ptr<'tcx>( } impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { - // Returns `true` if `ty` is a `()`, or a `repr(transparent)` type whose only non-ZST field - // is a generic substituted for `()` - in either case, the type is FFI-safe when used as a - // return type. - pub fn is_unit_or_equivalent(&self, ty: Ty<'tcx>) -> bool { - if ty.is_unit() { - return true; - } - - if let ty::Adt(def, substs) = ty.kind() && def.repr().transparent() { - return def.variants() - .iter() - .filter_map(|variant| transparent_newtype_field(self.cx.tcx, variant)) - .all(|field| { - let field_ty = field.ty(self.cx.tcx, substs); - !field_ty.has_opaque_types() && { - let field_ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, field_ty); - self.is_unit_or_equivalent(field_ty) - } - }); - } - - false - } - /// Check if the type is array and emit an unsafe type lint. fn check_for_array_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool { if let ty::Array(..) = ty.kind() { @@ -1010,14 +986,19 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { use FfiResult::*; let transparent_with_all_zst_fields = if def.repr().transparent() { - // Transparent newtypes have at most one non-ZST field which needs to be checked.. if let Some(field) = transparent_newtype_field(self.cx.tcx, variant) { - return self.check_field_type_for_ffi(cache, field, args); - } + // Transparent newtypes have at most one non-ZST field which needs to be checked.. + match self.check_field_type_for_ffi(cache, field, args) { + FfiUnsafe { ty, .. } if ty.is_unit() => (), + r => return r, + } - // ..or have only ZST fields, which is FFI-unsafe (unless those fields are all - // `PhantomData`). - true + false + } else { + // ..or have only ZST fields, which is FFI-unsafe (unless those fields are all + // `PhantomData`). + true + } } else { false }; @@ -1027,6 +1008,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { for field in &variant.fields { all_phantom &= match self.check_field_type_for_ffi(cache, &field, args) { FfiSafe => false, + // `()` fields are FFI-safe! + FfiUnsafe { ty, .. } if ty.is_unit() => false, FfiPhantom(..) => true, r @ FfiUnsafe { .. } => return r, } @@ -1249,7 +1232,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } let ret_ty = sig.output(); - if self.is_unit_or_equivalent(ret_ty) { + if ret_ty.is_unit() { return FfiSafe; } @@ -1374,7 +1357,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // Don't report FFI errors for unit return types. This check exists here, and not in // the caller (where it would make more sense) so that normalization has definitely // happened. - if is_return_type && self.is_unit_or_equivalent(ty) { + if is_return_type && ty.is_unit() { return; } |
