Skip to content

Commit d0e156d

Browse files
committed
WIP
1 parent 4d45f69 commit d0e156d

File tree

7 files changed

+275
-162
lines changed

7 files changed

+275
-162
lines changed

compiler/rustc_hir/src/lang_items.rs

+4
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,10 @@ language_item_table! {
271271
// libstd panic entry point. Necessary for const eval to be able to catch it
272272
BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn;
273273

274+
BacktraceEnabled, sym::backtrace_enabled, backtrace_enabled, Target::Fn;
275+
BacktraceCreate, sym::backtrace_create, backtrace_create, Target::Fn;
276+
BacktraceStatus, sym::backtrace_status, backtrace_status, Target::Fn;
277+
274278
ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn;
275279
BoxFree, sym::box_free, box_free_fn, Target::Fn;
276280
DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn;

compiler/rustc_hir/src/weak_lang_items.rs

+3
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,7 @@ weak_lang_items! {
4848
eh_personality, EhPersonality, rust_eh_personality;
4949
eh_catch_typeinfo, EhCatchTypeinfo, rust_eh_catch_typeinfo;
5050
oom, Oom, rust_oom;
51+
backtrace_create, BacktraceCreate, rust_backtrace_create;
52+
backtrace_enabled, BacktraceEnabled, rust_backtrace_enabled;
53+
backtrace_status, BacktraceStatus, rust_backtrace_status;
5154
}

compiler/rustc_span/src/symbol.rs

+6
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,9 @@ symbols! {
289289
automatically_derived,
290290
avx512_target_feature,
291291
await_macro,
292+
backtrace_create,
293+
backtrace_enabled,
294+
backtrace_status,
292295
bang,
293296
begin_panic,
294297
bench,
@@ -931,6 +934,9 @@ symbols! {
931934
rust_2015_preview,
932935
rust_2018_preview,
933936
rust_2021_preview,
937+
rust_backtrace_create,
938+
rust_backtrace_enabled,
939+
rust_backtrace_status,
934940
rust_begin_unwind,
935941
rust_eh_catch_typeinfo,
936942
rust_eh_personality,

library/core/src/backtrace.rs

+168-14
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,200 @@
11
//! hi
2-
#![unstable(feature = "core_backtrace", issue = "74465")]
3-
use crate::fmt;
2+
#![unstable(feature = "backtrace", issue = "74465")]
3+
use crate::{fmt, ptr};
4+
5+
/// The current status of a backtrace, indicating whether it was captured or
6+
/// whether it is empty for some other reason.
7+
#[non_exhaustive]
8+
#[derive(Debug, PartialEq, Eq)]
9+
pub enum BacktraceStatus {
10+
/// Capturing a backtrace is not supported, likely because it's not
11+
/// implemented for the current platform.
12+
Unsupported,
13+
/// Capturing a backtrace has been disabled through either the
14+
/// `RUST_LIB_BACKTRACE` or `RUST_BACKTRACE` environment variables.
15+
Disabled,
16+
/// A backtrace has been captured and the `Backtrace` should print
17+
/// reasonable information when rendered.
18+
Captured,
19+
}
420

521
// perma(?)-unstable
6-
#[unstable(feature = "core_backtrace", issue = "74465")]
22+
#[unstable(feature = "backtrace", issue = "74465")]
723
///
8-
pub trait RawBacktraceImpl: fmt::Debug + fmt::Display + 'static {
24+
pub trait RawBacktrace: fmt::Debug + fmt::Display + 'static {
925
///
1026
unsafe fn drop_and_free(self: *mut Self);
1127
}
1228

13-
#[unstable(feature = "core_backtrace", issue = "74465")]
29+
struct UnsupportedBacktrace;
30+
31+
impl UnsupportedBacktrace {
32+
#[allow(dead_code)]
33+
const fn create() -> Backtrace {
34+
// don't add members to Self
35+
let _ = Self {};
36+
37+
Backtrace {
38+
inner: ptr::NonNull::<Self>::dangling().as_ptr(),
39+
}
40+
}
41+
}
42+
43+
impl RawBacktrace for UnsupportedBacktrace {
44+
unsafe fn drop_and_free(self: *mut Self) {}
45+
}
46+
47+
impl fmt::Display for UnsupportedBacktrace {
48+
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
49+
fmt.write_str("unsupported backtrace")
50+
}
51+
}
52+
53+
impl fmt::Debug for UnsupportedBacktrace {
54+
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
55+
fmt.write_str("<unsupported>")
56+
}
57+
}
58+
struct DisabledBacktrace;
59+
60+
impl DisabledBacktrace {
61+
const fn create() -> Backtrace {
62+
// don't add members to Self
63+
let _ = Self {};
64+
65+
Backtrace {
66+
inner: ptr::NonNull::<Self>::dangling().as_ptr(),
67+
}
68+
}
69+
}
70+
71+
impl RawBacktrace for DisabledBacktrace {
72+
unsafe fn drop_and_free(self: *mut Self) {}
73+
}
74+
75+
impl fmt::Display for DisabledBacktrace {
76+
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
77+
fmt.write_str("disabled backtrace")
78+
}
79+
}
80+
81+
impl fmt::Debug for DisabledBacktrace {
82+
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
83+
fmt.write_str("<disabled>")
84+
}
85+
}
86+
87+
#[unstable(feature = "backtrace", issue = "74465")]
1488
///
1589
pub struct Backtrace {
16-
inner: *mut dyn RawBacktraceImpl,
90+
///
91+
inner: *mut dyn RawBacktrace,
92+
}
93+
94+
/// Global implementation of backtrace functionality. Called to create
95+
/// `RawBacktrace` trait objects.
96+
extern "Rust" {
97+
#[lang = "backtrace_create"]
98+
fn backtrace_create(ip: usize) -> *mut dyn RawBacktrace;
99+
100+
#[lang = "backtrace_enabled"]
101+
fn backtrace_enabled() -> bool;
102+
103+
#[lang = "backtrace_status"]
104+
fn backtrace_status(raw: *mut dyn RawBacktrace) -> BacktraceStatus;
105+
}
106+
107+
impl Backtrace {
108+
fn create(ip: usize) -> Backtrace {
109+
let inner = unsafe { backtrace_create(ip) };
110+
Backtrace { inner }
111+
}
112+
113+
/// Returns whether backtrace captures are enabled through environment
114+
/// variables.
115+
fn enabled() -> bool {
116+
unsafe { backtrace_enabled() }
117+
}
118+
119+
/// Capture a stack backtrace of the current thread.
120+
///
121+
/// This function will capture a stack backtrace of the current OS thread of
122+
/// execution, returning a `Backtrace` type which can be later used to print
123+
/// the entire stack trace or render it to a string.
124+
///
125+
/// This function will be a noop if the `RUST_BACKTRACE` or
126+
/// `RUST_LIB_BACKTRACE` backtrace variables are both not set. If either
127+
/// environment variable is set and enabled then this function will actually
128+
/// capture a backtrace. Capturing a backtrace can be both memory intensive
129+
/// and slow, so these environment variables allow liberally using
130+
/// `Backtrace::capture` and only incurring a slowdown when the environment
131+
/// variables are set.
132+
///
133+
/// To forcibly capture a backtrace regardless of environment variables, use
134+
/// the `Backtrace::force_capture` function.
135+
#[inline(never)] // want to make sure there's a frame here to remove
136+
pub fn capture() -> Backtrace {
137+
if !Backtrace::enabled() {
138+
return Backtrace::disabled();
139+
}
140+
141+
Self::create(Backtrace::capture as usize)
142+
}
143+
144+
/// Forcibly captures a full backtrace, regardless of environment variable
145+
/// configuration.
146+
///
147+
/// This function behaves the same as `capture` except that it ignores the
148+
/// values of the `RUST_BACKTRACE` and `RUST_LIB_BACKTRACE` environment
149+
/// variables, always capturing a backtrace.
150+
///
151+
/// Note that capturing a backtrace can be an expensive operation on some
152+
/// platforms, so this should be used with caution in performance-sensitive
153+
/// parts of code.
154+
#[inline(never)] // want to make sure there's a frame here to remove
155+
pub fn force_capture() -> Backtrace {
156+
Self::create(Backtrace::force_capture as usize)
157+
}
158+
159+
/// Forcibly captures a disabled backtrace, regardless of environment
160+
/// variable configuration.
161+
pub const fn disabled() -> Backtrace {
162+
DisabledBacktrace::create()
163+
}
164+
165+
/// Returns the status of this backtrace, indicating whether this backtrace
166+
/// request was unsupported, disabled, or a stack trace was actually
167+
/// captured.
168+
pub fn status(&self) -> BacktraceStatus {
169+
unsafe { backtrace_status(self.inner) }
170+
}
17171
}
18172

19-
#[unstable(feature = "core_backtrace", issue = "74465")]
173+
#[unstable(feature = "backtrace", issue = "74465")]
20174
unsafe impl Send for Backtrace {}
21175

22-
#[unstable(feature = "core_backtrace", issue = "74465")]
176+
#[unstable(feature = "backtrace", issue = "74465")]
23177
unsafe impl Sync for Backtrace {}
24178

25-
#[unstable(feature = "core_backtrace", issue = "74465")]
179+
#[unstable(feature = "backtrace", issue = "74465")]
26180
impl Drop for Backtrace {
27181
fn drop(&mut self) {
28-
unsafe { RawBacktraceImpl::drop_and_free(self.inner) }
182+
unsafe { RawBacktrace::drop_and_free(self.inner) }
29183
}
30184
}
31185

32-
#[unstable(feature = "core_backtrace", issue = "74465")]
186+
#[unstable(feature = "backtrace", issue = "74465")]
33187
impl fmt::Debug for Backtrace {
34188
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
35-
let imp: &dyn RawBacktraceImpl = unsafe { &*self.inner };
189+
let imp: &dyn RawBacktrace = unsafe { &*self.inner };
36190
fmt::Debug::fmt(imp, fmt)
37191
}
38192
}
39193

40-
#[unstable(feature = "core_backtrace", issue = "74465")]
194+
#[unstable(feature = "backtrace", issue = "74465")]
41195
impl fmt::Display for Backtrace {
42196
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
43-
let imp: &dyn RawBacktraceImpl = unsafe { &*self.inner };
197+
let imp: &dyn RawBacktrace = unsafe { &*self.inner };
44198
fmt::Display::fmt(imp, fmt)
45199
}
46200
}

library/core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@
116116
#![feature(fundamental)]
117117
#![feature(intrinsics)]
118118
#![feature(lang_items)]
119+
#![feature(linkage)]
119120
#![feature(link_llvm_intrinsics)]
120121
#![feature(llvm_asm)]
121122
#![feature(negative_impls)]

0 commit comments

Comments
 (0)