Skip to content

Commit

Permalink
Rollup merge of #70916 - Centril:track-caller-ffi, r=eddyb
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Centril committed Apr 9, 2020
2 parents ecc4e2a + 45589b5 commit 4f00396
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 45 deletions.
2 changes: 1 addition & 1 deletion src/librustc_error_codes/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,6 @@ E0734: include_str!("./error_codes/E0734.md"),
E0735: include_str!("./error_codes/E0735.md"),
E0736: include_str!("./error_codes/E0736.md"),
E0737: include_str!("./error_codes/E0737.md"),
E0738: include_str!("./error_codes/E0738.md"),
E0739: include_str!("./error_codes/E0739.md"),
E0740: include_str!("./error_codes/E0740.md"),
E0741: include_str!("./error_codes/E0741.md"),
Expand Down Expand Up @@ -614,4 +613,5 @@ E0751: include_str!("./error_codes/E0751.md"),
E0722, // Malformed `#[optimize]` attribute
E0724, // `#[ffi_returns_twice]` is only allowed in foreign functions
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
}
11 changes: 0 additions & 11 deletions src/librustc_error_codes/error_codes/E0738.md

This file was deleted.

14 changes: 2 additions & 12 deletions src/librustc_passes/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ impl CheckAttrVisitor<'tcx> {
target: Target,
) -> bool {
match target {
Target::Fn if attr::contains_name(attrs, sym::naked) => {
_ if attr::contains_name(attrs, sym::naked) => {
struct_span_err!(
self.tcx.sess,
*attr_span,
Expand All @@ -151,17 +151,7 @@ impl CheckAttrVisitor<'tcx> {
.emit();
false
}
Target::ForeignFn => {
struct_span_err!(
self.tcx.sess,
*attr_span,
E0738,
"`#[track_caller]` is not supported on foreign functions",
)
.emit();
false
}
Target::Fn | Target::Method(..) => true,
Target::Fn | Target::Method(..) | Target::ForeignFn => true,
_ => {
struct_span_err!(
self.tcx.sess,
Expand Down
9 changes: 0 additions & 9 deletions src/test/ui/rfc-2091-track-caller/error-extern-fn.rs

This file was deleted.

9 changes: 0 additions & 9 deletions src/test/ui/rfc-2091-track-caller/error-extern-fn.stderr

This file was deleted.

17 changes: 15 additions & 2 deletions src/test/ui/rfc-2091-track-caller/error-with-naked.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
#![feature(naked_functions, track_caller)]

#[track_caller]
#[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
#[naked]
fn f() {}
//~^^^ ERROR cannot use `#[track_caller]` with `#[naked]`

struct S;

impl S {
#[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
#[naked]
fn g() {}
}

extern "Rust" {
#[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
#[naked]
fn h();
}

fn main() {}
14 changes: 13 additions & 1 deletion src/test/ui/rfc-2091-track-caller/error-with-naked.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ error[E0736]: cannot use `#[track_caller]` with `#[naked]`
LL | #[track_caller]
| ^^^^^^^^^^^^^^^

error: aborting due to previous error
error[E0736]: cannot use `#[track_caller]` with `#[naked]`
--> $DIR/error-with-naked.rs:16:5
|
LL | #[track_caller]
| ^^^^^^^^^^^^^^^

error[E0736]: cannot use `#[track_caller]` with `#[naked]`
--> $DIR/error-with-naked.rs:10:5
|
LL | #[track_caller]
| ^^^^^^^^^^^^^^^

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0736`.
50 changes: 50 additions & 0 deletions src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// run-pass

#![feature(track_caller)]

use std::panic::Location;

extern "Rust" {
#[track_caller]
fn rust_track_caller_ffi_test_tracked() -> &'static Location<'static>;
fn rust_track_caller_ffi_test_untracked() -> &'static Location<'static>;
}

fn rust_track_caller_ffi_test_nested_tracked() -> &'static Location<'static> {
unsafe { rust_track_caller_ffi_test_tracked() }
}

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()
}
#[no_mangle]
fn rust_track_caller_ffi_test_untracked() -> &'static Location<'static> {
Location::caller()
}
}

fn main() {
let location = Location::caller();
assert_eq!(location.file(), file!());
assert_eq!(location.line(), 31);
assert_eq!(location.column(), 20);

let tracked = unsafe { rust_track_caller_ffi_test_tracked() };
assert_eq!(tracked.file(), file!());
assert_eq!(tracked.line(), 36);
assert_eq!(tracked.column(), 28);

let untracked = unsafe { rust_track_caller_ffi_test_untracked() };
assert_eq!(untracked.file(), file!());
assert_eq!(untracked.line(), 26);
assert_eq!(untracked.column(), 9);

let contained = rust_track_caller_ffi_test_nested_tracked();
assert_eq!(contained.file(), file!());
assert_eq!(contained.line(), 14);
assert_eq!(contained.column(), 14);
}

0 comments on commit 4f00396

Please sign in to comment.