Skip to content

Commit

Permalink
Types with a hidden niche are not known to be non-null
Browse files Browse the repository at this point in the history
  • Loading branch information
tmiasko committed Dec 10, 2020
1 parent e413d89 commit 8fc2462
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 47 deletions.
8 changes: 7 additions & 1 deletion compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@ pub fn transparent_newtype_field<'a, 'tcx>(
}

/// Is type known to be non-null?
crate fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKind) -> bool {
fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKind) -> bool {
let tcx = cx.tcx;
match ty.kind() {
ty::FnPtr(_) => true,
Expand All @@ -672,6 +672,12 @@ crate fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: C
return true;
}

// Types with a `#[repr(no_niche)]` attribute have their niche hidden.
// The attribute is used by the UnsafeCell for example (the only use so far).
if def.repr.hide_niche() {
return false;
}

for variant in &def.variants {
if let Some(field) = transparent_newtype_field(cx.tcx, variant) {
if ty_is_known_nonnull(cx, field.ty(tcx, substs), mode) {
Expand Down
34 changes: 34 additions & 0 deletions src/test/ui/lint/clashing-extern-fn.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// check-pass
// aux-build:external_extern_fn.rs
#![crate_type = "lib"]
#![feature(no_niche)]
#![warn(clashing_extern_declarations)]

mod redeclared_different_signature {
Expand Down Expand Up @@ -383,3 +384,36 @@ mod unknown_layout {
}
}
}

mod hidden_niche {
mod a {
extern "C" {
fn hidden_niche_transparent() -> usize;
fn hidden_niche_transparent_no_niche() -> usize;
fn hidden_niche_unsafe_cell() -> usize;
}
}
mod b {
use std::cell::UnsafeCell;
use std::num::NonZeroUsize;

#[repr(transparent)]
struct Transparent { x: NonZeroUsize }

#[repr(no_niche)]
#[repr(transparent)]
struct TransparentNoNiche { y: NonZeroUsize }

extern "C" {
fn hidden_niche_transparent() -> Option<Transparent>;

fn hidden_niche_transparent_no_niche() -> Option<TransparentNoNiche>;
//~^ WARN redeclared with a different signature
//~| WARN block uses type `Option<TransparentNoNiche>`, which is not FFI-safe

fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZeroUsize>>;
//~^ WARN redeclared with a different signature
//~| WARN block uses type `Option<UnsafeCell<NonZeroUsize>>`, which is not FFI-safe
}
}
}
77 changes: 60 additions & 17 deletions src/test/ui/lint/clashing-extern-fn.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
warning: `clash` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:14:13
--> $DIR/clashing-extern-fn.rs:15:13
|
LL | fn clash(x: u8);
| ---------------- `clash` previously declared here
Expand All @@ -8,15 +8,15 @@ LL | fn clash(x: u64);
| ^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
|
note: the lint level is defined here
--> $DIR/clashing-extern-fn.rs:4:9
--> $DIR/clashing-extern-fn.rs:5:9
|
LL | #![warn(clashing_extern_declarations)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `unsafe extern "C" fn(u8)`
found `unsafe extern "C" fn(u64)`

warning: `extern_link_name` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:52:9
--> $DIR/clashing-extern-fn.rs:53:9
|
LL | / #[link_name = "extern_link_name"]
LL | | fn some_new_name(x: i16);
Expand All @@ -29,7 +29,7 @@ LL | fn extern_link_name(x: u32);
found `unsafe extern "C" fn(u32)`

warning: `some_other_extern_link_name` redeclares `some_other_new_name` with a different signature
--> $DIR/clashing-extern-fn.rs:55:9
--> $DIR/clashing-extern-fn.rs:56:9
|
LL | fn some_other_new_name(x: i16);
| ------------------------------- `some_other_new_name` previously declared here
Expand All @@ -43,7 +43,7 @@ LL | | fn some_other_extern_link_name(x: u32);
found `unsafe extern "C" fn(u32)`

warning: `other_both_names_different` redeclares `link_name_same` with a different signature
--> $DIR/clashing-extern-fn.rs:59:9
--> $DIR/clashing-extern-fn.rs:60:9
|
LL | / #[link_name = "link_name_same"]
LL | | fn both_names_different(x: i16);
Expand All @@ -58,7 +58,7 @@ LL | | fn other_both_names_different(x: u32);
found `unsafe extern "C" fn(u32)`

warning: `different_mod` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:72:9
--> $DIR/clashing-extern-fn.rs:73:9
|
LL | fn different_mod(x: u8);
| ------------------------ `different_mod` previously declared here
Expand All @@ -70,7 +70,7 @@ LL | fn different_mod(x: u64);
found `unsafe extern "C" fn(u64)`

warning: `variadic_decl` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:82:9
--> $DIR/clashing-extern-fn.rs:83:9
|
LL | fn variadic_decl(x: u8, ...);
| ----------------------------- `variadic_decl` previously declared here
Expand All @@ -82,7 +82,7 @@ LL | fn variadic_decl(x: u8);
found `unsafe extern "C" fn(u8)`

warning: `weigh_banana` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:142:13
--> $DIR/clashing-extern-fn.rs:143:13
|
LL | fn weigh_banana(count: *const Banana) -> u64;
| --------------------------------------------- `weigh_banana` previously declared here
Expand All @@ -94,7 +94,7 @@ LL | fn weigh_banana(count: *const Banana) -> u64;
found `unsafe extern "C" fn(*const three::Banana) -> u64`

warning: `draw_point` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:171:13
--> $DIR/clashing-extern-fn.rs:172:13
|
LL | fn draw_point(p: Point);
| ------------------------ `draw_point` previously declared here
Expand All @@ -106,7 +106,7 @@ LL | fn draw_point(p: Point);
found `unsafe extern "C" fn(sameish_members::b::Point)`

warning: `origin` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:197:13
--> $DIR/clashing-extern-fn.rs:198:13
|
LL | fn origin() -> Point3;
| ---------------------- `origin` previously declared here
Expand All @@ -118,7 +118,7 @@ LL | fn origin() -> Point3;
found `unsafe extern "C" fn() -> same_sized_members_clash::b::Point3`

warning: `transparent_incorrect` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:220:13
--> $DIR/clashing-extern-fn.rs:221:13
|
LL | fn transparent_incorrect() -> T;
| -------------------------------- `transparent_incorrect` previously declared here
Expand All @@ -130,7 +130,7 @@ LL | fn transparent_incorrect() -> isize;
found `unsafe extern "C" fn() -> isize`

warning: `missing_return_type` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:238:13
--> $DIR/clashing-extern-fn.rs:239:13
|
LL | fn missing_return_type() -> usize;
| ---------------------------------- `missing_return_type` previously declared here
Expand All @@ -142,7 +142,7 @@ LL | fn missing_return_type();
found `unsafe extern "C" fn()`

warning: `non_zero_usize` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:256:13
--> $DIR/clashing-extern-fn.rs:257:13
|
LL | fn non_zero_usize() -> core::num::NonZeroUsize;
| ----------------------------------------------- `non_zero_usize` previously declared here
Expand All @@ -154,7 +154,7 @@ LL | fn non_zero_usize() -> usize;
found `unsafe extern "C" fn() -> usize`

warning: `non_null_ptr` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:258:13
--> $DIR/clashing-extern-fn.rs:259:13
|
LL | fn non_null_ptr() -> core::ptr::NonNull<usize>;
| ----------------------------------------------- `non_null_ptr` previously declared here
Expand All @@ -166,7 +166,7 @@ LL | fn non_null_ptr() -> *const usize;
found `unsafe extern "C" fn() -> *const usize`

warning: `option_non_zero_usize_incorrect` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:356:13
--> $DIR/clashing-extern-fn.rs:357:13
|
LL | fn option_non_zero_usize_incorrect() -> usize;
| ---------------------------------------------- `option_non_zero_usize_incorrect` previously declared here
Expand All @@ -178,7 +178,7 @@ LL | fn option_non_zero_usize_incorrect() -> isize;
found `unsafe extern "C" fn() -> isize`

warning: `option_non_null_ptr_incorrect` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:358:13
--> $DIR/clashing-extern-fn.rs:359:13
|
LL | fn option_non_null_ptr_incorrect() -> *const usize;
| --------------------------------------------------- `option_non_null_ptr_incorrect` previously declared here
Expand All @@ -189,5 +189,48 @@ 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: 15 warnings emitted
warning: `hidden_niche_transparent_no_niche` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:410:13
|
LL | fn hidden_niche_transparent_no_niche() -> usize;
| ------------------------------------------------ `hidden_niche_transparent_no_niche` previously declared here
...
LL | fn hidden_niche_transparent_no_niche() -> Option<TransparentNoNiche>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
|
= note: expected `unsafe extern "C" fn() -> usize`
found `unsafe extern "C" fn() -> Option<TransparentNoNiche>`

warning: `hidden_niche_unsafe_cell` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:414:13
|
LL | fn hidden_niche_unsafe_cell() -> usize;
| --------------------------------------- `hidden_niche_unsafe_cell` previously declared here
...
LL | fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZeroUsize>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
|
= note: expected `unsafe extern "C" fn() -> usize`
found `unsafe extern "C" fn() -> Option<UnsafeCell<NonZeroUsize>>`

warning: `extern` block uses type `Option<TransparentNoNiche>`, which is not FFI-safe
--> $DIR/clashing-extern-fn.rs:410:55
|
LL | fn hidden_niche_transparent_no_niche() -> Option<TransparentNoNiche>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
= note: `#[warn(improper_ctypes)]` on by default
= 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<UnsafeCell<NonZeroUsize>>`, which is not FFI-safe
--> $DIR/clashing-extern-fn.rs:414:46
|
LL | fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZeroUsize>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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: 19 warnings emitted

6 changes: 6 additions & 0 deletions src/test/ui/lint/lint-ctypes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

extern crate libc;

use std::cell::UnsafeCell;
use std::marker::PhantomData;

trait Bar { }
Expand Down Expand Up @@ -70,6 +71,11 @@ extern {
pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: uses type `Box<u32>`
pub fn raw_array(arr: [u8; 8]); //~ ERROR: uses type `[u8; 8]`

pub fn no_niche_a(a: Option<UnsafeCell<extern fn()>>);
//~^ ERROR: uses type `Option<UnsafeCell<extern "C" fn()>>`
pub fn no_niche_b(b: Option<UnsafeCell<&i32>>);
//~^ ERROR: uses type `Option<UnsafeCell<&i32>>`

pub static static_u128_type: u128; //~ ERROR: uses type `u128`
pub static static_u128_array_type: [u128; 16]; //~ ERROR: uses type `u128`

Expand Down
Loading

0 comments on commit 8fc2462

Please sign in to comment.