emit error on #[track_caller] with extern fn

such a function implicitly uses `extern "C"
This commit is contained in:
Folkert de Vries
2026-03-29 18:14:53 +02:00
parent 584d32e3ee
commit 3ce8cfbc58
3 changed files with 45 additions and 13 deletions
+21 -12
View File
@@ -1679,19 +1679,28 @@ fn visit_fn(&mut self, fk: FnKind<'a>, attrs: &AttrVec, span: Span, id: NodeId)
self.check_item_safety(span, safety);
}
if let FnKind::Fn(ctxt, _, fun) = fk
&& let Extern::Explicit(str_lit, extern_abi_span) = fun.sig.header.ext
&& let Ok(abi) = ExternAbi::from_str(str_lit.symbol.as_str())
{
self.check_extern_fn_signature(abi, ctxt, &fun.ident, &fun.sig);
if let FnKind::Fn(ctxt, _, fun) = fk {
let ext = match fun.sig.header.ext {
Extern::None => None,
Extern::Implicit(span) => Some((ExternAbi::FALLBACK, span)),
Extern::Explicit(str_lit, span) => {
ExternAbi::from_str(str_lit.symbol.as_str()).ok().map(|abi| (abi, span))
}
};
if let Some(attr) = attr::find_by_name(attrs, sym::track_caller)
&& abi != ExternAbi::Rust
{
self.dcx().emit_err(errors::RequiresRustAbi {
track_caller_span: attr.span,
extern_abi_span,
});
if let Some((extern_abi, extern_abi_span)) = ext {
// Some ABIs impose special restrictions on the signature.
self.check_extern_fn_signature(extern_abi, ctxt, &fun.ident, &fun.sig);
// #[track_caller] can only be used with the rust ABI.
if let Some(attr) = attr::find_by_name(attrs, sym::track_caller)
&& extern_abi != ExternAbi::Rust
{
self.dcx().emit_err(errors::RequiresRustAbi {
track_caller_span: attr.span,
extern_abi_span,
});
}
}
}
@@ -27,4 +27,10 @@ extern "C" fn c_method() {}
extern "Rust" fn rust_method() {}
}
#[rustfmt::skip] // rustfmt will insert the implicit "C"
#[track_caller]
//~^ ERROR `#[track_caller]` can only be used with the Rust ABI
pub extern fn extern_missing_abi() {}
//~^ WARN `extern` declarations without an explicit ABI are deprecated
fn main() {}
@@ -24,6 +24,23 @@ LL |
LL | extern "C" fn c_method() {}
| ---------- not using the Rust ABI because of this
error: aborting due to 3 previous errors
error[E0737]: `#[track_caller]` can only be used with the Rust ABI
--> $DIR/error-with-invalid-abi.rs:31:1
|
LL | #[track_caller]
| ^^^^^^^^^^^^^^^ using `#[track_caller]` here
LL |
LL | pub extern fn extern_missing_abi() {}
| ------ not using the Rust ABI because of this
warning: `extern` declarations without an explicit ABI are deprecated
--> $DIR/error-with-invalid-abi.rs:33:5
|
LL | pub extern fn extern_missing_abi() {}
| ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
|
= note: `#[warn(missing_abi)]` on by default
error: aborting due to 4 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0737`.