Skip to content

Commit 4f00396

Browse files
authored
Rollup merge of #70916 - Centril:track-caller-ffi, r=eddyb
Support `#[track_caller]` on functions in `extern "Rust" { ... }` Fixes #70830 which is the follow-up to @eddyb's suggestion in #69251 (comment) to allow `#[track_caller]` on `fn`s in FFI imports, that is, on functions in `extern "Rust" { ... }` blocks. This requires that the other side, the FFI export, also have the `#[track_caller]` attribute. Otherwise, undefined behavior is triggered and the blame lies, as usual, with the `unsafe { ... }` block which called the FFI imported function. After this PR, all forms of `fn` items with the right ABI (`"Rust"`) support `#[track_caller]`. As a drive-by, the PR also hardens the check rejecting `#[naked] #[track_caller]` such that methods and other forms of `fn` items are also considered. r? @eddyb cc @rust-lang/lang
2 parents ecc4e2a + 45589b5 commit 4f00396

File tree

8 files changed

+81
-45
lines changed

8 files changed

+81
-45
lines changed

src/librustc_error_codes/error_codes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,6 @@ E0734: include_str!("./error_codes/E0734.md"),
416416
E0735: include_str!("./error_codes/E0735.md"),
417417
E0736: include_str!("./error_codes/E0736.md"),
418418
E0737: include_str!("./error_codes/E0737.md"),
419-
E0738: include_str!("./error_codes/E0738.md"),
420419
E0739: include_str!("./error_codes/E0739.md"),
421420
E0740: include_str!("./error_codes/E0740.md"),
422421
E0741: include_str!("./error_codes/E0741.md"),
@@ -614,4 +613,5 @@ E0751: include_str!("./error_codes/E0751.md"),
614613
E0722, // Malformed `#[optimize]` attribute
615614
E0724, // `#[ffi_returns_twice]` is only allowed in foreign functions
616615
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
616+
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
617617
}

src/librustc_error_codes/error_codes/E0738.md

-11
This file was deleted.

src/librustc_passes/check_attr.rs

+2-12
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ impl CheckAttrVisitor<'tcx> {
141141
target: Target,
142142
) -> bool {
143143
match target {
144-
Target::Fn if attr::contains_name(attrs, sym::naked) => {
144+
_ if attr::contains_name(attrs, sym::naked) => {
145145
struct_span_err!(
146146
self.tcx.sess,
147147
*attr_span,
@@ -151,17 +151,7 @@ impl CheckAttrVisitor<'tcx> {
151151
.emit();
152152
false
153153
}
154-
Target::ForeignFn => {
155-
struct_span_err!(
156-
self.tcx.sess,
157-
*attr_span,
158-
E0738,
159-
"`#[track_caller]` is not supported on foreign functions",
160-
)
161-
.emit();
162-
false
163-
}
164-
Target::Fn | Target::Method(..) => true,
154+
Target::Fn | Target::Method(..) | Target::ForeignFn => true,
165155
_ => {
166156
struct_span_err!(
167157
self.tcx.sess,

src/test/ui/rfc-2091-track-caller/error-extern-fn.rs

-9
This file was deleted.

src/test/ui/rfc-2091-track-caller/error-extern-fn.stderr

-9
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
11
#![feature(naked_functions, track_caller)]
22

3-
#[track_caller]
3+
#[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
44
#[naked]
55
fn f() {}
6-
//~^^^ ERROR cannot use `#[track_caller]` with `#[naked]`
6+
7+
struct S;
8+
9+
impl S {
10+
#[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
11+
#[naked]
12+
fn g() {}
13+
}
14+
15+
extern "Rust" {
16+
#[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
17+
#[naked]
18+
fn h();
19+
}
720

821
fn main() {}

src/test/ui/rfc-2091-track-caller/error-with-naked.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@ error[E0736]: cannot use `#[track_caller]` with `#[naked]`
44
LL | #[track_caller]
55
| ^^^^^^^^^^^^^^^
66

7-
error: aborting due to previous error
7+
error[E0736]: cannot use `#[track_caller]` with `#[naked]`
8+
--> $DIR/error-with-naked.rs:16:5
9+
|
10+
LL | #[track_caller]
11+
| ^^^^^^^^^^^^^^^
12+
13+
error[E0736]: cannot use `#[track_caller]` with `#[naked]`
14+
--> $DIR/error-with-naked.rs:10:5
15+
|
16+
LL | #[track_caller]
17+
| ^^^^^^^^^^^^^^^
18+
19+
error: aborting due to 3 previous errors
820

921
For more information about this error, try `rustc --explain E0736`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// run-pass
2+
3+
#![feature(track_caller)]
4+
5+
use std::panic::Location;
6+
7+
extern "Rust" {
8+
#[track_caller]
9+
fn rust_track_caller_ffi_test_tracked() -> &'static Location<'static>;
10+
fn rust_track_caller_ffi_test_untracked() -> &'static Location<'static>;
11+
}
12+
13+
fn rust_track_caller_ffi_test_nested_tracked() -> &'static Location<'static> {
14+
unsafe { rust_track_caller_ffi_test_tracked() }
15+
}
16+
17+
mod provides {
18+
use std::panic::Location;
19+
#[track_caller] // UB if we did not have this!
20+
#[no_mangle]
21+
fn rust_track_caller_ffi_test_tracked() -> &'static Location<'static> {
22+
Location::caller()
23+
}
24+
#[no_mangle]
25+
fn rust_track_caller_ffi_test_untracked() -> &'static Location<'static> {
26+
Location::caller()
27+
}
28+
}
29+
30+
fn main() {
31+
let location = Location::caller();
32+
assert_eq!(location.file(), file!());
33+
assert_eq!(location.line(), 31);
34+
assert_eq!(location.column(), 20);
35+
36+
let tracked = unsafe { rust_track_caller_ffi_test_tracked() };
37+
assert_eq!(tracked.file(), file!());
38+
assert_eq!(tracked.line(), 36);
39+
assert_eq!(tracked.column(), 28);
40+
41+
let untracked = unsafe { rust_track_caller_ffi_test_untracked() };
42+
assert_eq!(untracked.file(), file!());
43+
assert_eq!(untracked.line(), 26);
44+
assert_eq!(untracked.column(), 9);
45+
46+
let contained = rust_track_caller_ffi_test_nested_tracked();
47+
assert_eq!(contained.file(), file!());
48+
assert_eq!(contained.line(), 14);
49+
assert_eq!(contained.column(), 14);
50+
}

0 commit comments

Comments
 (0)