Skip to content

Commit

Permalink
WIP Support #[track_caller] on closures.Closes rust-lang#74042.
Browse files Browse the repository at this point in the history
  • Loading branch information
anp committed Jul 19, 2020
1 parent 7d31ffc commit 3d39b9c
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 7 deletions.
11 changes: 6 additions & 5 deletions src/librustc_codegen_ssa/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -808,11 +808,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let needs_location =
instance.map_or(false, |i| i.def.requires_caller_location(self.cx.tcx()));
if needs_location {
assert_eq!(
fn_abi.args.len(),
args.len() + 1,
"#[track_caller] fn's must have 1 more argument in their ABI than in their MIR",
);
// FIXME figure out the right number of args for closures
// assert_eq!(
// fn_abi.args.len(),
// args.len() + 1,
// "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR",
// );
let location = self.get_caller_location(&mut bx, fn_span);
debug!(
"codegen_call_terminator({:?}): location={:?} (fn_span {:?})",
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_passes/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ impl CheckAttrVisitor<'tcx> {
.emit();
false
}
Target::Fn | Target::Method(..) | Target::ForeignFn => true,
Target::Closure | Target::Fn | Target::ForeignFn | Target::Method(..) => true,
_ => {
struct_span_err!(
self.tcx.sess,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2413,7 +2413,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
} else if attr.check_name(sym::thread_local) {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
} else if attr.check_name(sym::track_caller) {
if tcx.is_closure(id) || tcx.fn_sig(id).abi() != abi::Abi::Rust {
if !tcx.is_closure(id) && tcx.fn_sig(id).abi() != abi::Abi::Rust {
struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
.emit();
}
Expand Down
54 changes: 54 additions & 0 deletions src/test/ui/rfc-2091-track-caller/track-caller-closure.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// run-pass

#![feature(stmt_expr_attributes)]

use std::panic::Location;

#[track_caller]
fn tracked() -> &'static Location<'static> {
let get_location = #[track_caller] || Location::caller();
get_location()
}

fn untracked_wrapper() -> (&'static Location<'static>, u32) {
let get_location = #[track_caller] || Location::caller();
(get_location(), line!())
}

fn nested_tracked() -> (&'static Location<'static>, u32) {
(tracked(), line!())
}

fn main() {
let get_location = #[track_caller] || Location::caller();
let (location, line) = (get_location(), line!());
assert_eq!(location.file(), file!());
assert_eq!(location.line(), line);

let (tracked, tracked_line) = (tracked(), line!());
assert_eq!(tracked.file(), file!());
assert_eq!(tracked.line(), tracked_line);

let (nested, nested_line) = untracked_wrapper();
assert_eq!(nested.file(), file!());
assert_eq!(nested.line(), nested_line);

let (contained, contained_line) = nested_tracked();
assert_eq!(contained.file(), file!());
assert_eq!(contained.line(), contained_line);

fn pass_to_ptr_call<T, R>(f: fn(T) -> R, x: T) -> R {
f(x)
}

let (get_location_w_n, line_from_shim) = (#[track_caller] |_| Location::caller(), line!());

let (location_with_arg, line_with_arg) = (get_location_w_n(3), line!());
assert_eq!(location_with_arg.file(), file!());
assert_eq!(location_with_arg.line(), line_with_arg);

let location_with_shim = pass_to_ptr_call(get_location_w_n, 5);
// FIXME make the closure's "def site" point to this file
assert_eq!(location_with_shim.file(), file!());
assert_eq!(location_with_shim.line(), line_from_shim);
}

0 comments on commit 3d39b9c

Please sign in to comment.