Skip to content

Commit 07194ff

Browse files
committed
Auto merge of #79804 - tmiasko:improper-ctypes-no-niche, r=pnkfelix
Types with a hidden niche are not known to be non-null Fixes #79787.
2 parents 218bf8d + 8fc2462 commit 07194ff

File tree

5 files changed

+154
-47
lines changed

5 files changed

+154
-47
lines changed

Diff for: compiler/rustc_lint/src/types.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ pub fn transparent_newtype_field<'a, 'tcx>(
672672
}
673673

674674
/// Is type known to be non-null?
675-
crate fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKind) -> bool {
675+
fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKind) -> bool {
676676
let tcx = cx.tcx;
677677
match ty.kind() {
678678
ty::FnPtr(_) => true,
@@ -685,6 +685,12 @@ crate fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: C
685685
return true;
686686
}
687687

688+
// Types with a `#[repr(no_niche)]` attribute have their niche hidden.
689+
// The attribute is used by the UnsafeCell for example (the only use so far).
690+
if def.repr.hide_niche() {
691+
return false;
692+
}
693+
688694
for variant in &def.variants {
689695
if let Some(field) = transparent_newtype_field(cx.tcx, variant) {
690696
if ty_is_known_nonnull(cx, field.ty(tcx, substs), mode) {

Diff for: src/test/ui/lint/clashing-extern-fn.rs

+34
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// check-pass
22
// aux-build:external_extern_fn.rs
33
#![crate_type = "lib"]
4+
#![feature(no_niche)]
45
#![warn(clashing_extern_declarations)]
56

67
mod redeclared_different_signature {
@@ -383,3 +384,36 @@ mod unknown_layout {
383384
}
384385
}
385386
}
387+
388+
mod hidden_niche {
389+
mod a {
390+
extern "C" {
391+
fn hidden_niche_transparent() -> usize;
392+
fn hidden_niche_transparent_no_niche() -> usize;
393+
fn hidden_niche_unsafe_cell() -> usize;
394+
}
395+
}
396+
mod b {
397+
use std::cell::UnsafeCell;
398+
use std::num::NonZeroUsize;
399+
400+
#[repr(transparent)]
401+
struct Transparent { x: NonZeroUsize }
402+
403+
#[repr(no_niche)]
404+
#[repr(transparent)]
405+
struct TransparentNoNiche { y: NonZeroUsize }
406+
407+
extern "C" {
408+
fn hidden_niche_transparent() -> Option<Transparent>;
409+
410+
fn hidden_niche_transparent_no_niche() -> Option<TransparentNoNiche>;
411+
//~^ WARN redeclared with a different signature
412+
//~| WARN block uses type `Option<TransparentNoNiche>`, which is not FFI-safe
413+
414+
fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZeroUsize>>;
415+
//~^ WARN redeclared with a different signature
416+
//~| WARN block uses type `Option<UnsafeCell<NonZeroUsize>>`, which is not FFI-safe
417+
}
418+
}
419+
}

Diff for: src/test/ui/lint/clashing-extern-fn.stderr

+60-17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
warning: `clash` redeclared with a different signature
2-
--> $DIR/clashing-extern-fn.rs:14:13
2+
--> $DIR/clashing-extern-fn.rs:15:13
33
|
44
LL | fn clash(x: u8);
55
| ---------------- `clash` previously declared here
@@ -8,15 +8,15 @@ LL | fn clash(x: u64);
88
| ^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
99
|
1010
note: the lint level is defined here
11-
--> $DIR/clashing-extern-fn.rs:4:9
11+
--> $DIR/clashing-extern-fn.rs:5:9
1212
|
1313
LL | #![warn(clashing_extern_declarations)]
1414
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1515
= note: expected `unsafe extern "C" fn(u8)`
1616
found `unsafe extern "C" fn(u64)`
1717

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

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

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

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

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

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

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

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

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

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

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

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

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

180180
warning: `option_non_null_ptr_incorrect` redeclared with a different signature
181-
--> $DIR/clashing-extern-fn.rs:358:13
181+
--> $DIR/clashing-extern-fn.rs:359:13
182182
|
183183
LL | fn option_non_null_ptr_incorrect() -> *const usize;
184184
| --------------------------------------------------- `option_non_null_ptr_incorrect` previously declared here
@@ -189,5 +189,48 @@ LL | fn option_non_null_ptr_incorrect() -> *const isize;
189189
= note: expected `unsafe extern "C" fn() -> *const usize`
190190
found `unsafe extern "C" fn() -> *const isize`
191191

192-
warning: 15 warnings emitted
192+
warning: `hidden_niche_transparent_no_niche` redeclared with a different signature
193+
--> $DIR/clashing-extern-fn.rs:410:13
194+
|
195+
LL | fn hidden_niche_transparent_no_niche() -> usize;
196+
| ------------------------------------------------ `hidden_niche_transparent_no_niche` previously declared here
197+
...
198+
LL | fn hidden_niche_transparent_no_niche() -> Option<TransparentNoNiche>;
199+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
200+
|
201+
= note: expected `unsafe extern "C" fn() -> usize`
202+
found `unsafe extern "C" fn() -> Option<TransparentNoNiche>`
203+
204+
warning: `hidden_niche_unsafe_cell` redeclared with a different signature
205+
--> $DIR/clashing-extern-fn.rs:414:13
206+
|
207+
LL | fn hidden_niche_unsafe_cell() -> usize;
208+
| --------------------------------------- `hidden_niche_unsafe_cell` previously declared here
209+
...
210+
LL | fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZeroUsize>>;
211+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
212+
|
213+
= note: expected `unsafe extern "C" fn() -> usize`
214+
found `unsafe extern "C" fn() -> Option<UnsafeCell<NonZeroUsize>>`
215+
216+
warning: `extern` block uses type `Option<TransparentNoNiche>`, which is not FFI-safe
217+
--> $DIR/clashing-extern-fn.rs:410:55
218+
|
219+
LL | fn hidden_niche_transparent_no_niche() -> Option<TransparentNoNiche>;
220+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
221+
|
222+
= note: `#[warn(improper_ctypes)]` on by default
223+
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
224+
= note: enum has no representation hint
225+
226+
warning: `extern` block uses type `Option<UnsafeCell<NonZeroUsize>>`, which is not FFI-safe
227+
--> $DIR/clashing-extern-fn.rs:414:46
228+
|
229+
LL | fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZeroUsize>>;
230+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
231+
|
232+
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
233+
= note: enum has no representation hint
234+
235+
warning: 19 warnings emitted
193236

Diff for: src/test/ui/lint/lint-ctypes.rs

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
extern crate libc;
77

8+
use std::cell::UnsafeCell;
89
use std::marker::PhantomData;
910

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

74+
pub fn no_niche_a(a: Option<UnsafeCell<extern fn()>>);
75+
//~^ ERROR: uses type `Option<UnsafeCell<extern "C" fn()>>`
76+
pub fn no_niche_b(b: Option<UnsafeCell<&i32>>);
77+
//~^ ERROR: uses type `Option<UnsafeCell<&i32>>`
78+
7379
pub static static_u128_type: u128; //~ ERROR: uses type `u128`
7480
pub static static_u128_array_type: [u128; 16]; //~ ERROR: uses type `u128`
7581

0 commit comments

Comments
 (0)