about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_lint/src/types.rs44
-rw-r--r--library/core/src/num/nonzero.rs1
-rw-r--r--tests/ui/lint/clashing-extern-fn.stderr67
-rw-r--r--tests/ui/lint/lint-ctypes-enum.stderr120
4 files changed, 35 insertions, 197 deletions
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 5d36a8b3d0e..500efefbb11 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -984,7 +984,14 @@ pub fn transparent_newtype_field<'a, 'tcx>(
 }
 
 /// Is type known to be non-null?
-fn ty_is_known_nonnull<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, mode: CItemKind) -> bool {
+fn ty_is_known_nonnull<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    ty: Ty<'tcx>,
+    mode: CItemKind,
+) -> bool {
+    let ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty);
+
     match ty.kind() {
         ty::FnPtr(_) => true,
         ty::Ref(..) => true,
@@ -1004,7 +1011,7 @@ fn ty_is_known_nonnull<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, mode: CItemKind) -
             def.variants()
                 .iter()
                 .filter_map(|variant| transparent_newtype_field(tcx, variant))
-                .any(|field| ty_is_known_nonnull(tcx, field.ty(tcx, args), mode))
+                .any(|field| ty_is_known_nonnull(tcx, param_env, field.ty(tcx, args), mode))
         }
         _ => false,
     }
@@ -1012,7 +1019,13 @@ fn ty_is_known_nonnull<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, mode: CItemKind) -
 
 /// Given a non-null scalar (or transparent) type `ty`, return the nullable version of that type.
 /// If the type passed in was not scalar, returns None.
-fn get_nullable_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
+fn get_nullable_type<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    ty: Ty<'tcx>,
+) -> Option<Ty<'tcx>> {
+    let ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty);
+
     Some(match *ty.kind() {
         ty::Adt(field_def, field_args) => {
             let inner_field_ty = {
@@ -1028,22 +1041,19 @@ fn get_nullable_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>>
                     .expect("No non-zst fields in transparent type.")
                     .ty(tcx, field_args)
             };
-            return get_nullable_type(tcx, inner_field_ty);
+            return get_nullable_type(tcx, param_env, inner_field_ty);
         }
         ty::Int(ty) => Ty::new_int(tcx, ty),
         ty::Uint(ty) => Ty::new_uint(tcx, ty),
         ty::RawPtr(ty_mut) => Ty::new_ptr(tcx, ty_mut),
         // As these types are always non-null, the nullable equivalent of
-        // Option<T> of these types are their raw pointer counterparts.
+        // `Option<T>` of these types are their raw pointer counterparts.
         ty::Ref(_region, ty, mutbl) => Ty::new_ptr(tcx, ty::TypeAndMut { ty, mutbl }),
-        ty::FnPtr(..) => {
-            // There is no nullable equivalent for Rust's function pointers -- you
-            // must use an Option<fn(..) -> _> to represent it.
-            ty
-        }
-
-        // We should only ever reach this case if ty_is_known_nonnull is extended
-        // to other types.
+        // There is no nullable equivalent for Rust's function pointers,
+        // you must use an `Option<fn(..) -> _>` to represent it.
+        ty::FnPtr(..) => ty,
+        // We should only ever reach this case if `ty_is_known_nonnull` is
+        // extended to other types.
         ref unhandled => {
             debug!(
                 "get_nullable_type: Unhandled scalar kind: {:?} while checking {:?}",
@@ -1056,7 +1066,7 @@ fn get_nullable_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>>
 
 /// Check if this enum can be safely exported based on the "nullable pointer optimization". If it
 /// can, return the type that `ty` can be safely converted to, otherwise return `None`.
-/// Currently restricted to function pointers, boxes, references, `core::num::NonZero*`,
+/// Currently restricted to function pointers, boxes, references, `core::num::NonZero`,
 /// `core::ptr::NonNull`, and `#[repr(transparent)]` newtypes.
 /// FIXME: This duplicates code in codegen.
 pub(crate) fn repr_nullable_ptr<'tcx>(
@@ -1075,7 +1085,7 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
             _ => return None,
         };
 
-        if !ty_is_known_nonnull(tcx, field_ty, ckind) {
+        if !ty_is_known_nonnull(tcx, param_env, field_ty, ckind) {
             return None;
         }
 
@@ -1099,10 +1109,10 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
                 WrappingRange { start: 0, end }
                     if end == field_ty_scalar.size(&tcx).unsigned_int_max() - 1 =>
                 {
-                    return Some(get_nullable_type(tcx, field_ty).unwrap());
+                    return Some(get_nullable_type(tcx, param_env, field_ty).unwrap());
                 }
                 WrappingRange { start: 1, .. } => {
-                    return Some(get_nullable_type(tcx, field_ty).unwrap());
+                    return Some(get_nullable_type(tcx, param_env, field_ty).unwrap());
                 }
                 WrappingRange { start, end } => {
                     unreachable!("Unhandled start and end range: ({}, {})", start, end)
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index b853771b9ea..89d2b4f7dc1 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -103,6 +103,7 @@ impl_zeroable_primitive!(
 /// ```
 #[unstable(feature = "generic_nonzero", issue = "120257")]
 #[repr(transparent)]
+#[rustc_nonnull_optimization_guaranteed]
 #[rustc_diagnostic_item = "NonZero"]
 pub struct NonZero<T: ZeroablePrimitive>(T::NonZeroInner);
 
diff --git a/tests/ui/lint/clashing-extern-fn.stderr b/tests/ui/lint/clashing-extern-fn.stderr
index 22d9b4d76f1..86ee789aeb2 100644
--- a/tests/ui/lint/clashing-extern-fn.stderr
+++ b/tests/ui/lint/clashing-extern-fn.stderr
@@ -1,31 +1,3 @@
-warning: `extern` block uses type `Option<NonZero<usize>>`, which is not FFI-safe
-  --> $DIR/clashing-extern-fn.rs:369:43
-   |
-LL |             fn option_non_zero_usize() -> Option<core::num::NonZero<usize>>;
-   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
-   |
-   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
-   = note: enum has no representation hint
-   = note: `#[warn(improper_ctypes)]` on by default
-
-warning: `extern` block uses type `Option<NonZero<isize>>`, which is not FFI-safe
-  --> $DIR/clashing-extern-fn.rs:370:43
-   |
-LL |             fn option_non_zero_isize() -> Option<core::num::NonZero<isize>>;
-   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
-   |
-   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
-   = note: enum has no representation hint
-
-warning: `extern` block uses type `Option<Transparent>`, which is not FFI-safe
-  --> $DIR/clashing-extern-fn.rs:428:46
-   |
-LL |             fn hidden_niche_transparent() -> Option<Transparent>;
-   |                                              ^^^^^^^^^^^^^^^^^^^ not FFI-safe
-   |
-   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
-   = note: enum has no representation hint
-
 warning: `extern` block uses type `Option<TransparentNoNiche>`, which is not FFI-safe
   --> $DIR/clashing-extern-fn.rs:430:55
    |
@@ -34,6 +6,7 @@ LL |             fn hidden_niche_transparent_no_niche() -> Option<TransparentNoN
    |
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
+   = note: `#[warn(improper_ctypes)]` on by default
 
 warning: `extern` block uses type `Option<UnsafeCell<NonZero<usize>>>`, which is not FFI-safe
   --> $DIR/clashing-extern-fn.rs:434:46
@@ -205,30 +178,6 @@ LL |             fn non_null_ptr() -> *const usize;
    = note: expected `unsafe extern "C" fn() -> NonNull<usize>`
               found `unsafe extern "C" fn() -> *const usize`
 
-warning: `option_non_zero_usize` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:369:13
-   |
-LL |             fn option_non_zero_usize() -> usize;
-   |             ----------------------------------- `option_non_zero_usize` previously declared here
-...
-LL |             fn option_non_zero_usize() -> Option<core::num::NonZero<usize>>;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
-   |
-   = note: expected `unsafe extern "C" fn() -> usize`
-              found `unsafe extern "C" fn() -> Option<NonZero<usize>>`
-
-warning: `option_non_zero_isize` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:370:13
-   |
-LL |             fn option_non_zero_isize() -> isize;
-   |             ----------------------------------- `option_non_zero_isize` previously declared here
-...
-LL |             fn option_non_zero_isize() -> Option<core::num::NonZero<isize>>;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
-   |
-   = note: expected `unsafe extern "C" fn() -> isize`
-              found `unsafe extern "C" fn() -> Option<NonZero<isize>>`
-
 warning: `option_non_zero_usize_incorrect` redeclared with a different signature
   --> $DIR/clashing-extern-fn.rs:374:13
    |
@@ -253,18 +202,6 @@ LL |             fn option_non_null_ptr_incorrect() -> *const isize;
    = note: expected `unsafe extern "C" fn() -> *const usize`
               found `unsafe extern "C" fn() -> *const isize`
 
-warning: `hidden_niche_transparent` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:428:13
-   |
-LL |             fn hidden_niche_transparent() -> usize;
-   |             -------------------------------------- `hidden_niche_transparent` previously declared here
-...
-LL |             fn hidden_niche_transparent() -> Option<Transparent>;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
-   |
-   = note: expected `unsafe extern "C" fn() -> usize`
-              found `unsafe extern "C" fn() -> Option<Transparent>`
-
 warning: `hidden_niche_transparent_no_niche` redeclared with a different signature
   --> $DIR/clashing-extern-fn.rs:430:13
    |
@@ -289,5 +226,5 @@ LL |             fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZero<usiz
    = note: expected `unsafe extern "C" fn() -> usize`
               found `unsafe extern "C" fn() -> Option<UnsafeCell<NonZero<usize>>>`
 
-warning: 25 warnings emitted
+warning: 19 warnings emitted
 
diff --git a/tests/ui/lint/lint-ctypes-enum.stderr b/tests/ui/lint/lint-ctypes-enum.stderr
index b1bacbeceda..48be3eb5a56 100644
--- a/tests/ui/lint/lint-ctypes-enum.stderr
+++ b/tests/ui/lint/lint-ctypes-enum.stderr
@@ -45,131 +45,21 @@ note: the type is defined here
 LL | enum T {
    | ^^^^^^
 
-error: `extern` block uses type `Option<NonZero<u8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:71:21
-   |
-LL |    fn nonzero_u8(x: Option<num::NonZero<u8>>);
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
-   |
-   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
-   = note: enum has no representation hint
-
-error: `extern` block uses type `Option<NonZero<u16>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:72:22
-   |
-LL |    fn nonzero_u16(x: Option<num::NonZero<u16>>);
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
-   |
-   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
-   = note: enum has no representation hint
-
-error: `extern` block uses type `Option<NonZero<u32>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:73:22
-   |
-LL |    fn nonzero_u32(x: Option<num::NonZero<u32>>);
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
-   |
-   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
-   = note: enum has no representation hint
-
-error: `extern` block uses type `Option<NonZero<u64>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:74:22
-   |
-LL |    fn nonzero_u64(x: Option<num::NonZero<u64>>);
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
-   |
-   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
-   = note: enum has no representation hint
-
-error: `extern` block uses type `Option<NonZero<u128>>`, which is not FFI-safe
+error: `extern` block uses type `u128`, which is not FFI-safe
   --> $DIR/lint-ctypes-enum.rs:75:23
    |
 LL |    fn nonzero_u128(x: Option<num::NonZero<u128>>);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
    |
-   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
-   = note: enum has no representation hint
-
-error: `extern` block uses type `Option<NonZero<usize>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:77:24
-   |
-LL |    fn nonzero_usize(x: Option<num::NonZero<usize>>);
-   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
-   |
-   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
-   = note: enum has no representation hint
-
-error: `extern` block uses type `Option<NonZero<i8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:78:21
-   |
-LL |    fn nonzero_i8(x: Option<num::NonZero<i8>>);
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
-   |
-   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
-   = note: enum has no representation hint
-
-error: `extern` block uses type `Option<NonZero<i16>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:79:22
-   |
-LL |    fn nonzero_i16(x: Option<num::NonZero<i16>>);
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
-   |
-   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
-   = note: enum has no representation hint
-
-error: `extern` block uses type `Option<NonZero<i32>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:80:22
-   |
-LL |    fn nonzero_i32(x: Option<num::NonZero<i32>>);
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
-   |
-   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
-   = note: enum has no representation hint
-
-error: `extern` block uses type `Option<NonZero<i64>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:81:22
-   |
-LL |    fn nonzero_i64(x: Option<num::NonZero<i64>>);
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
-   |
-   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
-   = note: enum has no representation hint
+   = note: 128-bit integers don't currently have a known stable ABI
 
-error: `extern` block uses type `Option<NonZero<i128>>`, which is not FFI-safe
+error: `extern` block uses type `i128`, which is not FFI-safe
   --> $DIR/lint-ctypes-enum.rs:82:23
    |
 LL |    fn nonzero_i128(x: Option<num::NonZero<i128>>);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
    |
-   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
-   = note: enum has no representation hint
-
-error: `extern` block uses type `Option<NonZero<isize>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:84:24
-   |
-LL |    fn nonzero_isize(x: Option<num::NonZero<isize>>);
-   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
-   |
-   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
-   = note: enum has no representation hint
-
-error: `extern` block uses type `Option<TransparentStruct<NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:85:29
-   |
-LL |    fn transparent_struct(x: Option<TransparentStruct<num::NonZero<u8>>>);
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
-   |
-   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
-   = note: enum has no representation hint
-
-error: `extern` block uses type `Option<TransparentEnum<NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:86:27
-   |
-LL |    fn transparent_enum(x: Option<TransparentEnum<num::NonZero<u8>>>);
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
-   |
-   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
-   = note: enum has no representation hint
+   = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `Option<TransparentUnion<NonZero<u8>>>`, which is not FFI-safe
   --> $DIR/lint-ctypes-enum.rs:87:28
@@ -198,5 +88,5 @@ LL |    fn no_result(x: Result<(), num::NonZero<i32>>);
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 
-error: aborting due to 20 previous errors
+error: aborting due to 8 previous errors