Skip to content

Commit 4728d66

Browse files
authored
Rollup merge of #65664 - anp:panic-location, r=eddyb
`std::panic::Location` is a lang_item, add `core::intrinsics::caller_location` (RFC 2091 3/N) [Tracking issue](#47809) [RFC text](https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md) @eddyb suggested doing this intrinsic implementation ahead of actually implementing the `#[track_caller]` attribute so that there's an easily tested intermediate step between adding the shim and wiring up the attribute.
2 parents c8eefdf + 86e55b1 commit 4728d66

File tree

25 files changed

+331
-145
lines changed

25 files changed

+331
-145
lines changed

src/libcore/intrinsics.rs

+4
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,10 @@ extern "rust-intrinsic" {
696696
/// This will statically either panic, or do nothing.
697697
pub fn panic_if_uninhabited<T>();
698698

699+
/// Gets a reference to a static `Location` indicating where it was called.
700+
#[cfg(not(bootstrap))]
701+
pub fn caller_location() -> &'static crate::panic::Location<'static>;
702+
699703
/// Creates a value initialized to zero.
700704
///
701705
/// `init` is unsafe because it returns a zeroed-out datum,

src/libcore/macros.rs

+34-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
/// Panics the current thread.
22
///
33
/// For details, see `std::macros`.
4+
#[cfg(bootstrap)]
45
#[macro_export]
5-
#[allow_internal_unstable(core_panic)]
6+
#[allow_internal_unstable(core_panic, panic_internals)]
67
#[stable(feature = "core", since = "1.6.0")]
78
macro_rules! panic {
89
() => (
@@ -20,6 +21,38 @@ macro_rules! panic {
2021
});
2122
}
2223

24+
/// Panics the current thread.
25+
///
26+
/// For details, see `std::macros`.
27+
#[cfg(not(bootstrap))]
28+
#[macro_export]
29+
#[allow_internal_unstable(core_panic, panic_internals)]
30+
#[stable(feature = "core", since = "1.6.0")]
31+
macro_rules! panic {
32+
() => (
33+
$crate::panic!("explicit panic")
34+
);
35+
($msg:expr) => ({
36+
const LOC: &$crate::panic::Location<'_> = &$crate::panic::Location::internal_constructor(
37+
$crate::file!(),
38+
$crate::line!(),
39+
$crate::column!(),
40+
);
41+
$crate::panicking::panic($msg, LOC)
42+
});
43+
($msg:expr,) => (
44+
$crate::panic!($msg)
45+
);
46+
($fmt:expr, $($arg:tt)+) => ({
47+
const LOC: &$crate::panic::Location<'_> = &$crate::panic::Location::internal_constructor(
48+
$crate::file!(),
49+
$crate::line!(),
50+
$crate::column!(),
51+
);
52+
$crate::panicking::panic_fmt($crate::format_args!($fmt, $($arg)+), LOC)
53+
});
54+
}
55+
2356
/// Asserts that two expressions are equal to each other (using [`PartialEq`]).
2457
///
2558
/// On panic, this macro will print the values of the expressions with their

src/libcore/panic.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use crate::fmt;
3535
pub struct PanicInfo<'a> {
3636
payload: &'a (dyn Any + Send),
3737
message: Option<&'a fmt::Arguments<'a>>,
38-
location: Location<'a>,
38+
location: &'a Location<'a>,
3939
}
4040

4141
impl<'a> PanicInfo<'a> {
@@ -45,11 +45,16 @@ impl<'a> PanicInfo<'a> {
4545
issue = "0")]
4646
#[doc(hidden)]
4747
#[inline]
48-
pub fn internal_constructor(message: Option<&'a fmt::Arguments<'a>>,
49-
location: Location<'a>)
50-
-> Self {
48+
pub fn internal_constructor(
49+
message: Option<&'a fmt::Arguments<'a>>,
50+
location: &'a Location<'a>,
51+
) -> Self {
5152
struct NoPayload;
52-
PanicInfo { payload: &NoPayload, location, message }
53+
PanicInfo {
54+
location,
55+
message,
56+
payload: &NoPayload,
57+
}
5358
}
5459

5560
#[doc(hidden)]
@@ -162,6 +167,7 @@ impl fmt::Display for PanicInfo<'_> {
162167
///
163168
/// panic!("Normal panic");
164169
/// ```
170+
#[cfg_attr(not(bootstrap), lang = "panic_location")]
165171
#[derive(Debug)]
166172
#[stable(feature = "panic_hooks", since = "1.10.0")]
167173
pub struct Location<'a> {
@@ -176,7 +182,7 @@ impl<'a> Location<'a> {
176182
and related macros",
177183
issue = "0")]
178184
#[doc(hidden)]
179-
pub fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self {
185+
pub const fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self {
180186
Location { file, line, col }
181187
}
182188

src/libcore/panicking.rs

+59-4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
use crate::fmt;
3030
use crate::panic::{Location, PanicInfo};
3131

32+
#[cfg(bootstrap)]
3233
#[cold]
3334
// never inline unless panic_immediate_abort to avoid code
3435
// bloat at the call sites as much as possible
@@ -49,6 +50,27 @@ pub fn panic(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! {
4950
panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line, col))
5051
}
5152

53+
#[cfg(not(bootstrap))]
54+
#[cold]
55+
// never inline unless panic_immediate_abort to avoid code
56+
// bloat at the call sites as much as possible
57+
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
58+
#[lang = "panic"]
59+
pub fn panic(expr: &str, location: &Location<'_>) -> ! {
60+
if cfg!(feature = "panic_immediate_abort") {
61+
unsafe { super::intrinsics::abort() }
62+
}
63+
64+
// Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially
65+
// reduce size overhead. The format_args! macro uses str's Display trait to
66+
// write expr, which calls Formatter::pad, which must accommodate string
67+
// truncation and padding (even though none is used here). Using
68+
// Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
69+
// output binary, saving up to a few kilobytes.
70+
panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), location)
71+
}
72+
73+
#[cfg(bootstrap)]
5274
#[cold]
5375
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
5476
#[lang = "panic_bounds_check"]
@@ -62,6 +84,22 @@ fn panic_bounds_check(file_line_col: &(&'static str, u32, u32),
6284
len, index), file_line_col)
6385
}
6486

87+
#[cfg(not(bootstrap))]
88+
#[cold]
89+
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
90+
#[lang = "panic_bounds_check"]
91+
fn panic_bounds_check(location: &Location<'_>, index: usize, len: usize) -> ! {
92+
if cfg!(feature = "panic_immediate_abort") {
93+
unsafe { super::intrinsics::abort() }
94+
}
95+
96+
panic_fmt(
97+
format_args!("index out of bounds: the len is {} but the index is {}", len, index),
98+
location
99+
)
100+
}
101+
102+
#[cfg(bootstrap)]
65103
#[cold]
66104
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
67105
#[cfg_attr( feature="panic_immediate_abort" ,inline)]
@@ -77,9 +115,26 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>, file_line_col: &(&'static str, u32, u3
77115
}
78116

79117
let (file, line, col) = *file_line_col;
80-
let pi = PanicInfo::internal_constructor(
81-
Some(&fmt),
82-
Location::internal_constructor(file, line, col),
83-
);
118+
let location = Location::internal_constructor(file, line, col);
119+
let pi = PanicInfo::internal_constructor(Some(&fmt), &location);
120+
unsafe { panic_impl(&pi) }
121+
}
122+
123+
#[cfg(not(bootstrap))]
124+
#[cold]
125+
#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))]
126+
#[cfg_attr( feature="panic_immediate_abort" ,inline)]
127+
pub fn panic_fmt(fmt: fmt::Arguments<'_>, location: &Location<'_>) -> ! {
128+
if cfg!(feature = "panic_immediate_abort") {
129+
unsafe { super::intrinsics::abort() }
130+
}
131+
132+
// NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
133+
extern "Rust" {
134+
#[lang = "panic_impl"]
135+
fn panic_impl(pi: &PanicInfo<'_>) -> !;
136+
}
137+
138+
let pi = PanicInfo::internal_constructor(Some(&fmt), location);
84139
unsafe { panic_impl(&pi) }
85140
}

src/librustc/middle/lang_items.rs

+1
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ language_item_table! {
370370
PanicFnLangItem, "panic", panic_fn, Target::Fn;
371371
PanicBoundsCheckFnLangItem, "panic_bounds_check", panic_bounds_check_fn, Target::Fn;
372372
PanicInfoLangItem, "panic_info", panic_info, Target::Struct;
373+
PanicLocationLangItem, "panic_location", panic_location, Target::Struct;
373374
PanicImplLangItem, "panic_impl", panic_impl, Target::Fn;
374375
// Libstd panic entry point. Necessary for const eval to be able to catch it
375376
BeginPanicFnLangItem, "begin_panic", begin_panic_fn, Target::Fn;

src/librustc/query/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,12 @@ rustc_queries! {
466466
no_force
467467
desc { "extract field of const" }
468468
}
469+
470+
query const_caller_location(key: (syntax_pos::Symbol, u32, u32)) -> &'tcx ty::Const<'tcx> {
471+
eval_always
472+
no_force
473+
desc { "get a &core::panic::Location referring to a span" }
474+
}
469475
}
470476

471477
TypeChecking {

src/librustc/ty/query/keys.rs

+10
Original file line numberDiff line numberDiff line change
@@ -208,3 +208,13 @@ impl<'tcx, T> Key for Canonical<'tcx, T> {
208208
DUMMY_SP
209209
}
210210
}
211+
212+
impl Key for (Symbol, u32, u32) {
213+
fn query_crate(&self) -> CrateNum {
214+
LOCAL_CRATE
215+
}
216+
217+
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
218+
DUMMY_SP
219+
}
220+
}

src/librustc_codegen_llvm/builder.rs

-31
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use std::ffi::CStr;
2323
use std::ops::{Deref, Range};
2424
use std::ptr;
2525
use std::iter::TrustedLen;
26-
use syntax::symbol::Symbol;
2726

2827
// All Builders must have an llfn associated with them
2928
#[must_use]
@@ -1067,36 +1066,6 @@ impl StaticBuilderMethods for Builder<'a, 'll, 'tcx> {
10671066
// Forward to the `get_static` method of `CodegenCx`
10681067
self.cx().get_static(def_id)
10691068
}
1070-
1071-
fn static_panic_msg(
1072-
&mut self,
1073-
msg: Option<Symbol>,
1074-
filename: Symbol,
1075-
line: Self::Value,
1076-
col: Self::Value,
1077-
kind: &str,
1078-
) -> Self::Value {
1079-
let align = self.tcx.data_layout.aggregate_align.abi
1080-
.max(self.tcx.data_layout.i32_align.abi)
1081-
.max(self.tcx.data_layout.pointer_align.abi);
1082-
1083-
let filename = self.const_str_slice(filename);
1084-
1085-
let with_msg_components;
1086-
let without_msg_components;
1087-
1088-
let components = if let Some(msg) = msg {
1089-
let msg = self.const_str_slice(msg);
1090-
with_msg_components = [msg, filename, line, col];
1091-
&with_msg_components as &[_]
1092-
} else {
1093-
without_msg_components = [filename, line, col];
1094-
&without_msg_components as &[_]
1095-
};
1096-
1097-
let struct_ = self.const_struct(&components, false);
1098-
self.static_addr_of(struct_, align, Some(kind))
1099-
}
11001069
}
11011070

11021071
impl Builder<'a, 'll, 'tcx> {

src/librustc_codegen_llvm/common.rs

+7-18
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
//! Code that is useful in various codegen modules.
44
55
use crate::llvm::{self, True, False, Bool, BasicBlock, OperandBundleDef, ConstantInt};
6-
use crate::abi;
76
use crate::consts;
87
use crate::type_::Type;
98
use crate::type_of::LayoutLlvmExt;
@@ -96,16 +95,6 @@ impl BackendTypes for CodegenCx<'ll, 'tcx> {
9695
}
9796

9897
impl CodegenCx<'ll, 'tcx> {
99-
pub fn const_fat_ptr(
100-
&self,
101-
ptr: &'ll Value,
102-
meta: &'ll Value
103-
) -> &'ll Value {
104-
assert_eq!(abi::FAT_PTR_ADDR, 0);
105-
assert_eq!(abi::FAT_PTR_EXTRA, 1);
106-
self.const_struct(&[ptr, meta], false)
107-
}
108-
10998
pub fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
11099
unsafe {
111100
return llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint);
@@ -150,13 +139,6 @@ impl CodegenCx<'ll, 'tcx> {
150139
}
151140
}
152141

153-
pub fn const_str_slice(&self, s: Symbol) -> &'ll Value {
154-
let len = s.as_str().len();
155-
let cs = consts::ptrcast(self.const_cstr(s, false),
156-
self.type_ptr_to(self.layout_of(self.tcx.mk_str()).llvm_type(self)));
157-
self.const_fat_ptr(cs, self.const_usize(len as u64))
158-
}
159-
160142
pub fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value {
161143
unsafe {
162144
assert_eq!(idx as c_uint as u64, idx);
@@ -237,6 +219,13 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
237219
unsafe { llvm::LLVMConstReal(t, val) }
238220
}
239221

222+
fn const_str(&self, s: Symbol) -> (&'ll Value, &'ll Value) {
223+
let len = s.as_str().len();
224+
let cs = consts::ptrcast(self.const_cstr(s, false),
225+
self.type_ptr_to(self.layout_of(self.tcx.mk_str()).llvm_type(self)));
226+
(cs, self.const_usize(len as u64))
227+
}
228+
240229
fn const_struct(
241230
&self,
242231
elts: &[&'ll Value],

0 commit comments

Comments
 (0)