the `#[track_caller]` shim should not inherit `#[no_mangle]`
fixes https://github.com/rust-lang/rust/issues/143162
builds on https://github.com/rust-lang/rust/pull/143293 which introduced a mechanism to strip attributes from shims.
cc `@Jules-Bertholet` `@workingjubilee` `@bjorn3`
---
Summary:
This PR fixes an interaction between `#[track_caller]`, `#[no_mangle]`, and casting to a function pointer.
A function annotated with `#[track_caller]` internally has a hidden extra argument for the panic location. The `#[track_caller]` attribute is only allowed on `extern "Rust"` functions. When a function is annotated with both `#[no_mangle]` and `#[track_caller]`, the exported symbol has the signature that includes the extra panic location argument. This works on stable rust today:
```rust
extern "Rust" {
#[track_caller]
fn rust_track_caller_ffi_test_tracked() -> &'static Location<'static>;
}
mod provides {
use std::panic::Location;
#[track_caller] // UB if we did not have this!
#[no_mangle]
fn rust_track_caller_ffi_test_tracked() -> &'static Location<'static> {
Location::caller()
}
}
```
When a `#[track_caller]` function is converted to a function pointer, a shim is added to drop the additional argument. So this is a valid program:
```rust
#[track_caller]
fn foo() {}
fn main() {
let f = foo as fn();
f();
}
```
The issue arises when `foo` is additionally annotated with `#[no_mangle]`, the generated shim currently inherits this attribute, also exporting a symbol named `foo`, but one without the hidden panic location argument. The linker rightfully complains about a duplicate symbol.
The solution of this PR is to have the generated shim drop the `#[no_mangle]` attribute.