2 // aux-build:external_extern_fn.rs
5 #![warn(clashing_extern_declarations)]
7 mod redeclared_different_signature {
15 fn clash(x: u64); //~ WARN `clash` redeclared with a different signature
20 mod redeclared_same_signature {
33 extern crate external_extern_fn;
35 // Should not clash with external_extern_fn::extern_fn.
42 fn some_other_new_name(x: i16);
44 #[link_name = "extern_link_name"]
45 fn some_new_name(x: i16);
47 #[link_name = "link_name_same"]
48 fn both_names_different(x: i16);
51 fn link_name_clash() {
53 fn extern_link_name(x: u32);
54 //~^ WARN `extern_link_name` redeclared with a different signature
56 #[link_name = "some_other_new_name"]
57 //~^ WARN `some_other_extern_link_name` redeclares `some_other_new_name` with a different
58 fn some_other_extern_link_name(x: u32);
60 #[link_name = "link_name_same"]
61 //~^ WARN `other_both_names_different` redeclares `link_name_same` with a different
62 fn other_both_names_different(x: u32);
68 fn different_mod(x: u8);
73 fn different_mod(x: u64); //~ WARN `different_mod` redeclared with a different signature
78 fn variadic_decl(x: u8, ...);
83 fn variadic_decl(x: u8); //~ WARN `variadic_decl` redeclared with a different signature
88 fn no_mangle_name(x: u8) {}
91 #[link_name = "unique_link_name"]
92 fn link_name_specified(x: u8);
95 fn tricky_no_clash() {
97 // Shouldn't warn, because the declaration above actually declares a different symbol (and
98 // Rust's name resolution rules around shadowing will handle this gracefully).
99 fn link_name_specified() -> u32;
101 // The case of a no_mangle name colliding with an extern decl (see #28179) is related but
102 // shouldn't be reported by ClashingExternDeclarations, because this is an example of
103 // unmangled name clash causing bad behaviour in functions with a defined body.
104 fn no_mangle_name() -> u32;
116 fn weigh_banana(count: *const Banana) -> u64;
125 } // note: distinct type
126 // This should not trigger the lint because two::Banana is structurally equivalent to
129 fn weigh_banana(count: *const Banana) -> u64;
134 // This _should_ trigger the lint, because repr(packed) should generate a struct that has a
141 #[allow(improper_ctypes)]
143 fn weigh_banana(count: *const Banana) -> u64;
144 //~^ WARN `weigh_banana` redeclared with a different signature
149 mod sameish_members {
158 fn draw_point(p: Point);
164 coordinates: [i16; 2],
167 // It's possible we are overconservative for this case, as accessing the elements of the
168 // coordinates array might end up correctly accessing `.x` and `.y`. However, this may not
169 // always be the case, for every architecture and situation. This is also a really odd
170 // thing to do anyway.
172 fn draw_point(p: Point);
173 //~^ WARN `draw_point` redeclared with a different signature
178 mod same_sized_members_clash {
187 fn origin() -> Point3;
195 z: i32, // NOTE: Incorrectly redeclared as i32
198 fn origin() -> Point3; //~ WARN `origin` redeclared with a different signature
209 fn transparent() -> T;
210 fn transparent_incorrect() -> T;
216 // Shouldn't warn here, because repr(transparent) guarantees that T's layout is the
217 // same as just the usize.
218 fn transparent() -> usize;
220 // Should warn, because there's a signedness conversion here:
221 fn transparent_incorrect() -> isize;
222 //~^ WARN `transparent_incorrect` redeclared with a different signature
227 mod missing_return_type {
230 fn missing_return_type() -> usize;
236 // This should output a warning because we can't assume that the first declaration is
237 // the correct one -- if this one is the correct one, then calling the usize-returning
238 // version would allow reads into uninitialised memory.
239 fn missing_return_type();
240 //~^ WARN `missing_return_type` redeclared with a different signature
245 mod non_zero_and_non_null {
248 fn non_zero_usize() -> core::num::NonZeroUsize;
249 fn non_null_ptr() -> core::ptr::NonNull<usize>;
254 // If there's a clash in either of these cases you're either gaining an incorrect
255 // invariant that the value is non-zero, or you're missing out on that invariant. Both
256 // cases are warning for, from both a caller-convenience and optimisation perspective.
257 fn non_zero_usize() -> usize;
258 //~^ WARN `non_zero_usize` redeclared with a different signature
259 fn non_null_ptr() -> *const usize;
260 //~^ WARN `non_null_ptr` redeclared with a different signature
266 mod non_zero_transparent {
268 use std::num::NonZeroUsize;
270 fn f1() -> NonZeroUsize;
276 struct X(NonZeroUsize);
277 use std::num::NonZeroUsize;
284 use std::num::NonZeroUsize;
286 fn f2() -> NonZeroUsize;
292 struct X1(NonZeroUsize);
297 use std::num::NonZeroUsize;
299 // Same case as above, but with two layers of newtyping.
306 struct X(core::ptr::NonNull<i32>);
308 use std::num::NonZeroUsize;
316 fn f3() -> core::ptr::NonNull<i32>;
323 X(std::num::NonZeroUsize),
332 fn f4() -> std::num::NonZeroUsize;
337 mod null_optimised_enums {
340 fn option_non_zero_usize() -> usize;
341 fn option_non_zero_isize() -> isize;
342 fn option_non_null_ptr() -> *const usize;
344 fn option_non_zero_usize_incorrect() -> usize;
345 fn option_non_null_ptr_incorrect() -> *const usize;
350 // This should be allowed, because these conversions are guaranteed to be FFI-safe (see
352 fn option_non_zero_usize() -> Option<core::num::NonZeroUsize>;
353 fn option_non_zero_isize() -> Option<core::num::NonZeroIsize>;
354 fn option_non_null_ptr() -> Option<core::ptr::NonNull<usize>>;
356 // However, these should be incorrect (note isize instead of usize)
357 fn option_non_zero_usize_incorrect() -> isize;
358 //~^ WARN `option_non_zero_usize_incorrect` redeclared with a different signature
359 fn option_non_null_ptr_incorrect() -> *const isize;
360 //~^ WARN `option_non_null_ptr_incorrect` redeclared with a different signature
365 #[allow(improper_ctypes)]
369 pub fn generic(l: Link<u32>);
373 pub next: *const Link<T>,
379 pub fn generic(l: Link<u32>);
383 pub next: *const Link<T>,
391 fn hidden_niche_transparent() -> usize;
392 fn hidden_niche_transparent_no_niche() -> usize;
393 fn hidden_niche_unsafe_cell() -> usize;
397 use std::cell::UnsafeCell;
398 use std::num::NonZeroUsize;
401 struct Transparent { x: NonZeroUsize }
405 struct TransparentNoNiche { y: NonZeroUsize }
408 fn hidden_niche_transparent() -> Option<Transparent>;
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
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