Implement #[track_caller] in const.
This commit is contained in:
parent
234c9f21d9
commit
9ab065dcda
@ -116,6 +116,10 @@ pub fn requires_local(&self, tcx: TyCtxt<'tcx>) -> bool {
|
||||
}
|
||||
tcx.codegen_fn_attrs(self.def_id()).requests_inline()
|
||||
}
|
||||
|
||||
pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
|
||||
tcx.codegen_fn_attrs(self.def_id()).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for Instance<'tcx> {
|
||||
@ -255,11 +259,8 @@ pub fn resolve_for_fn_ptr(
|
||||
) -> Option<Instance<'tcx>> {
|
||||
debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
|
||||
Instance::resolve(tcx, param_env, def_id, substs).map(|mut resolved| {
|
||||
let has_track_caller = |def| tcx.codegen_fn_attrs(def).flags
|
||||
.contains(CodegenFnAttrFlags::TRACK_CALLER);
|
||||
|
||||
match resolved.def {
|
||||
InstanceDef::Item(def_id) if has_track_caller(def_id) => {
|
||||
InstanceDef::Item(def_id) if resolved.def.requires_caller_location(tcx) => {
|
||||
debug!(" => fn pointer created for function with #[track_caller]");
|
||||
resolved.def = InstanceDef::ReifyShim(def_id);
|
||||
}
|
||||
|
@ -112,6 +112,7 @@ pub fn emulate_intrinsic(
|
||||
// `src/librustc/ty/constness.rs`
|
||||
match intrinsic_name {
|
||||
sym::caller_location => {
|
||||
let span = self.find_closest_untracked_caller_location(span);
|
||||
let location = self.alloc_caller_location_for_span(span);
|
||||
self.write_scalar(location.ptr, dest)?;
|
||||
}
|
||||
|
@ -6,6 +6,28 @@
|
||||
use crate::interpret::{Scalar, MemoryKind, MPlaceTy, intrinsics::{InterpCx, Machine}};
|
||||
|
||||
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
/// Walks up the callstack from the intrinsic's callsite, searching for the first frame which is
|
||||
/// not `#[track_caller]`. Returns the (passed) span of the intrinsic's callsite if the first
|
||||
/// frame in the stack is untracked so that we can display the callsite of the intrinsic within
|
||||
/// that function.
|
||||
crate fn find_closest_untracked_caller_location(
|
||||
&self,
|
||||
intrinsic_loc: Span,
|
||||
) -> Span {
|
||||
debug!("finding closest untracked caller relative to {:?}", intrinsic_loc);
|
||||
|
||||
let mut caller_span = intrinsic_loc;
|
||||
for next_caller in self.stack.iter().rev() {
|
||||
if !next_caller.instance.def.requires_caller_location(*self.tcx) {
|
||||
return caller_span;
|
||||
}
|
||||
caller_span = next_caller.span;
|
||||
}
|
||||
|
||||
intrinsic_loc
|
||||
}
|
||||
|
||||
/// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
|
||||
crate fn alloc_caller_location(
|
||||
&mut self,
|
||||
filename: Symbol,
|
||||
|
@ -1,23 +1,41 @@
|
||||
// run-pass
|
||||
|
||||
#![feature(const_fn, core_intrinsics)]
|
||||
#![feature(const_fn, core_intrinsics, track_caller)]
|
||||
|
||||
use std::{intrinsics::caller_location, panic::Location};
|
||||
|
||||
const LOCATION: &Location = caller_location();
|
||||
const NESTED: &Location = {
|
||||
|
||||
const TRACKED: &Location = tracked();
|
||||
#[track_caller]
|
||||
const fn tracked() -> &'static Location <'static> {
|
||||
caller_location()
|
||||
}
|
||||
|
||||
const NESTED: &Location = nested_location();
|
||||
const fn nested_location() -> &'static Location<'static> {
|
||||
caller_location()
|
||||
};
|
||||
nested_location()
|
||||
};
|
||||
}
|
||||
|
||||
const CONTAINED: &Location = contained();
|
||||
const fn contained() -> &'static Location<'static> {
|
||||
tracked()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(LOCATION.file(), file!());
|
||||
assert_eq!(LOCATION.line(), 7);
|
||||
assert_eq!(LOCATION.column(), 29);
|
||||
|
||||
assert_eq!(TRACKED.file(), file!());
|
||||
assert_eq!(TRACKED.line(), 9);
|
||||
assert_eq!(TRACKED.column(), 28);
|
||||
|
||||
assert_eq!(NESTED.file(), file!());
|
||||
assert_eq!(NESTED.line(), 10);
|
||||
assert_eq!(NESTED.column(), 9);
|
||||
assert_eq!(NESTED.line(), 17);
|
||||
assert_eq!(NESTED.column(), 5);
|
||||
|
||||
assert_eq!(CONTAINED.file(), file!());
|
||||
assert_eq!(CONTAINED.line(), 22);
|
||||
assert_eq!(CONTAINED.column(), 5);
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
warning: the feature `track_caller` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/const_caller_location.rs:3:39
|
||||
|
|
||||
LL | #![feature(const_fn, core_intrinsics, track_caller)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
Loading…
Reference in New Issue
Block a user