diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2020-04-09 05:29:45 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-04-09 05:29:45 +0200 |
| commit | 4f00396f149713b920a74055419f5ab3a8d6a066 (patch) | |
| tree | 62bd6d3e2cc2cd653b3a176d4f84a11d8cdd4a60 | |
| parent | ecc4e2a647533ddabb7a1b69f6ab1385c3f4003c (diff) | |
| parent | 45589b52fe215b7090bf88683927716c25197203 (diff) | |
| download | rust-4f00396f149713b920a74055419f5ab3a8d6a066.tar.gz rust-4f00396f149713b920a74055419f5ab3a8d6a066.zip | |
Rollup merge of #70916 - Centril:track-caller-ffi, r=eddyb
Support `#[track_caller]` on functions in `extern "Rust" { ... }`
Fixes https://github.com/rust-lang/rust/issues/70830 which is the follow-up to @eddyb's suggestion in https://github.com/rust-lang/rust/pull/69251#discussion_r380791634 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
| -rw-r--r-- | src/librustc_error_codes/error_codes.rs | 2 | ||||
| -rw-r--r-- | src/librustc_error_codes/error_codes/E0738.md | 11 | ||||
| -rw-r--r-- | src/librustc_passes/check_attr.rs | 14 | ||||
| -rw-r--r-- | src/test/ui/rfc-2091-track-caller/error-extern-fn.rs | 9 | ||||
| -rw-r--r-- | src/test/ui/rfc-2091-track-caller/error-extern-fn.stderr | 9 | ||||
| -rw-r--r-- | src/test/ui/rfc-2091-track-caller/error-with-naked.rs | 17 | ||||
| -rw-r--r-- | src/test/ui/rfc-2091-track-caller/error-with-naked.stderr | 14 | ||||
| -rw-r--r-- | src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs | 50 |
8 files changed, 81 insertions, 45 deletions
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 6e690655f60..8d9982131c3 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -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"), @@ -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" { ... }`. } diff --git a/src/librustc_error_codes/error_codes/E0738.md b/src/librustc_error_codes/error_codes/E0738.md deleted file mode 100644 index 8f31b701e49..00000000000 --- a/src/librustc_error_codes/error_codes/E0738.md +++ /dev/null @@ -1,11 +0,0 @@ -`#[track_caller]` cannot be used to annotate foreign functions. - -Erroneous example: - -```compile_fail,E0738 -#![feature(track_caller)] -extern "Rust" { - #[track_caller] - fn bar(); -} -``` diff --git a/src/librustc_passes/check_attr.rs b/src/librustc_passes/check_attr.rs index 619a8c6f229..3f2c02f6c46 100644 --- a/src/librustc_passes/check_attr.rs +++ b/src/librustc_passes/check_attr.rs @@ -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, @@ -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, diff --git a/src/test/ui/rfc-2091-track-caller/error-extern-fn.rs b/src/test/ui/rfc-2091-track-caller/error-extern-fn.rs deleted file mode 100644 index 9f6a69a51c0..00000000000 --- a/src/test/ui/rfc-2091-track-caller/error-extern-fn.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(track_caller)] -#![allow(dead_code)] - -extern "Rust" { - #[track_caller] //~ ERROR: `#[track_caller]` is not supported on foreign functions - fn bar(); -} - -fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-extern-fn.stderr b/src/test/ui/rfc-2091-track-caller/error-extern-fn.stderr deleted file mode 100644 index b03f5fbbdb2..00000000000 --- a/src/test/ui/rfc-2091-track-caller/error-extern-fn.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0738]: `#[track_caller]` is not supported on foreign functions - --> $DIR/error-extern-fn.rs:5:5 - | -LL | #[track_caller] - | ^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0738`. diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs index dd9e5d04135..f4573848333 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs +++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs @@ -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() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr index 2f5003cfdb7..1249d1df071 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr @@ -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`. diff --git a/src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs b/src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs new file mode 100644 index 00000000000..23c17d743c4 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs @@ -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); +} |
