2 // aux-build:external_extern_fn.rs
4 #![warn(clashing_extern_declarations)]
6 mod redeclared_different_signature {
14 fn clash(x: u64); //~ WARN `clash` redeclared with a different signature
19 mod redeclared_same_signature {
32 extern crate external_extern_fn;
34 // Should not clash with external_extern_fn::extern_fn.
41 fn some_other_new_name(x: i16);
43 #[link_name = "extern_link_name"]
44 fn some_new_name(x: i16);
46 #[link_name = "link_name_same"]
47 fn both_names_different(x: i16);
50 fn link_name_clash() {
52 fn extern_link_name(x: u32);
53 //~^ WARN `extern_link_name` redeclared with a different signature
55 #[link_name = "some_other_new_name"]
56 //~^ WARN `some_other_extern_link_name` redeclares `some_other_new_name` with a different
57 fn some_other_extern_link_name(x: u32);
59 #[link_name = "link_name_same"]
60 //~^ WARN `other_both_names_different` redeclares `link_name_same` with a different
61 fn other_both_names_different(x: u32);
67 fn different_mod(x: u8);
72 fn different_mod(x: u64); //~ WARN `different_mod` redeclared with a different signature
77 fn variadic_decl(x: u8, ...);
82 fn variadic_decl(x: u8); //~ WARN `variadic_decl` redeclared with a different signature
87 fn no_mangle_name(x: u8) {}
90 #[link_name = "unique_link_name"]
91 fn link_name_specified(x: u8);
94 fn tricky_no_clash() {
96 // Shouldn't warn, because the declaration above actually declares a different symbol (and
97 // Rust's name resolution rules around shadowing will handle this gracefully).
98 fn link_name_specified() -> u32;
100 // The case of a no_mangle name colliding with an extern decl (see #28179) is related but
101 // shouldn't be reported by ClashingExternDeclarations, because this is an example of
102 // unmangled name clash causing bad behaviour in functions with a defined body.
103 fn no_mangle_name() -> u32;
115 fn weigh_banana(count: *const Banana) -> u64;
124 } // note: distinct type
125 // This should not trigger the lint because two::Banana is structurally equivalent to
128 fn weigh_banana(count: *const Banana) -> u64;
133 // This _should_ trigger the lint, because repr(packed) should generate a struct that has a
140 #[allow(improper_ctypes)]
142 fn weigh_banana(count: *const Banana) -> u64;
143 //~^ WARN `weigh_banana` redeclared with a different signature
148 mod sameish_members {
157 fn draw_point(p: Point);
163 coordinates: [i16; 2],
166 // It's possible we are overconservative for this case, as accessing the elements of the
167 // coordinates array might end up correctly accessing `.x` and `.y`. However, this may not
168 // always be the case, for every architecture and situation. This is also a really odd
169 // thing to do anyway.
171 fn draw_point(p: Point);
172 //~^ WARN `draw_point` redeclared with a different signature
177 mod same_sized_members_clash {
185 extern "C" { fn origin() -> Point3; }
192 z: i32, // NOTE: Incorrectly redeclared as i32
194 extern "C" { fn origin() -> Point3; }
195 //~^ WARN `origin` redeclared with a different signature
205 fn transparent() -> T;
206 fn transparent_incorrect() -> T;
212 // Shouldn't warn here, because repr(transparent) guarantees that T's layout is the
213 // same as just the usize.
214 fn transparent() -> usize;
216 // Should warn, because there's a signedness conversion here:
217 fn transparent_incorrect() -> isize;
218 //~^ WARN `transparent_incorrect` redeclared with a different signature
223 mod missing_return_type {
226 fn missing_return_type() -> usize;
232 // This should output a warning because we can't assume that the first declaration is
233 // the correct one -- if this one is the correct one, then calling the usize-returning
234 // version would allow reads into uninitialised memory.
235 fn missing_return_type();
236 //~^ WARN `missing_return_type` redeclared with a different signature
241 mod non_zero_and_non_null {
244 fn non_zero_usize() -> core::num::NonZeroUsize;
245 fn non_null_ptr() -> core::ptr::NonNull<usize>;
250 // If there's a clash in either of these cases you're either gaining an incorrect
251 // invariant that the value is non-zero, or you're missing out on that invariant. Both
252 // cases are warning for, from both a caller-convenience and optimisation perspective.
253 fn non_zero_usize() -> usize;
254 //~^ WARN `non_zero_usize` redeclared with a different signature
255 fn non_null_ptr() -> *const usize;
256 //~^ WARN `non_null_ptr` redeclared with a different signature
261 mod null_optimised_enums {
264 fn option_non_zero_usize() -> usize;
265 fn option_non_zero_isize() -> isize;
266 fn option_non_null_ptr() -> *const usize;
268 fn option_non_zero_usize_incorrect() -> usize;
269 fn option_non_null_ptr_incorrect() -> *const usize;
274 // This should be allowed, because these conversions are guaranteed to be FFI-safe (see
276 fn option_non_zero_usize() -> Option<core::num::NonZeroUsize>;
277 fn option_non_zero_isize() -> Option<core::num::NonZeroIsize>;
278 fn option_non_null_ptr() -> Option<core::ptr::NonNull<usize>>;
280 // However, these should be incorrect (note isize instead of usize)
281 fn option_non_zero_usize_incorrect() -> isize;
282 //~^ WARN `option_non_zero_usize_incorrect` redeclared with a different signature
283 fn option_non_null_ptr_incorrect() -> *const isize;
284 //~^ WARN `option_non_null_ptr_incorrect` redeclared with a different signature