diff options
| author | bors <bors@rust-lang.org> | 2018-06-03 20:13:09 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-06-03 20:13:09 +0000 |
| commit | 29f48ccf396be031ee8a54e74a3a4e81866c8872 (patch) | |
| tree | 2f33ba908db3f5cf869d2be0cb8e1bd98a683543 /src/libstd | |
| parent | be5f17ccff09569c2dd22df9330364a92fec2295 (diff) | |
| parent | 8ad15dea3f9ac9b0fcfad4a61a70aa47ecc4d938 (diff) | |
| download | rust-29f48ccf396be031ee8a54e74a3a4e81866c8872.tar.gz rust-29f48ccf396be031ee8a54e74a3a4e81866c8872.zip | |
Auto merge of #50338 - japaric:panic-impl, r=alexcrichton
implement #[panic_implementation] This implements the `#[panic_implementation]` attribute as instructed in https://github.com/rust-lang/rust/issues/44489#issuecomment-381324623 I haven't run the full test suite yet but at least all the compile-fail tests pass. r? @nagisa
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/lib.rs | 2 | ||||
| -rw-r--r-- | src/libstd/panicking.rs | 102 |
2 files changed, 77 insertions, 27 deletions
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index f7d06852f27..c576245edb7 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -317,6 +317,8 @@ #![cfg_attr(windows, feature(used))] #![feature(doc_alias)] #![feature(float_internals)] +#![feature(panic_info_message)] +#![cfg_attr(not(stage0), feature(panic_implementation))] #![default_lib_allocator] diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 403056240bf..0808efa2ece 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -319,8 +319,8 @@ pub fn panicking() -> bool { /// Entry point of panic from the libcore crate. #[cfg(not(test))] +#[cfg(stage0)] #[lang = "panic_fmt"] -#[unwind(allowed)] pub extern fn rust_begin_panic(msg: fmt::Arguments, file: &'static str, line: u32, @@ -328,59 +328,107 @@ pub extern fn rust_begin_panic(msg: fmt::Arguments, begin_panic_fmt(&msg, &(file, line, col)) } +/// Entry point of panic from the libcore crate. +#[cfg(not(test))] +#[cfg(not(stage0))] +#[panic_implementation] +#[unwind(allowed)] +pub fn rust_begin_panic(info: &PanicInfo) -> ! { + continue_panic_fmt(&info) +} + /// The entry point for panicking with a formatted message. /// /// This is designed to reduce the amount of code required at the call /// site as much as possible (so that `panic!()` has as low an impact /// on (e.g.) the inlining of other functions as possible), by moving /// the actual formatting into this shared place. +#[cfg(stage0)] #[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "0")] #[inline(never)] #[cold] pub fn begin_panic_fmt(msg: &fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! { - use fmt::Write; - // We do two allocations here, unfortunately. But (a) they're // required with the current scheme, and (b) we don't handle // panic + OOM properly anyway (see comment in begin_panic // below). rust_panic_with_hook(&mut PanicPayload::new(msg), Some(msg), file_line_col); +} + +// NOTE(stage0) move into `continue_panic_fmt` on next stage0 update +struct PanicPayload<'a> { + inner: &'a fmt::Arguments<'a>, + string: Option<String>, +} - struct PanicPayload<'a> { - inner: &'a fmt::Arguments<'a>, - string: Option<String>, +impl<'a> PanicPayload<'a> { + fn new(inner: &'a fmt::Arguments<'a>) -> PanicPayload<'a> { + PanicPayload { inner, string: None } } - impl<'a> PanicPayload<'a> { - fn new(inner: &'a fmt::Arguments<'a>) -> PanicPayload<'a> { - PanicPayload { inner, string: None } - } + fn fill(&mut self) -> &mut String { + use fmt::Write; - fn fill(&mut self) -> &mut String { - let inner = self.inner; - self.string.get_or_insert_with(|| { - let mut s = String::new(); - drop(s.write_fmt(*inner)); - s - }) - } + let inner = self.inner; + self.string.get_or_insert_with(|| { + let mut s = String::new(); + drop(s.write_fmt(*inner)); + s + }) } +} - unsafe impl<'a> BoxMeUp for PanicPayload<'a> { - fn box_me_up(&mut self) -> *mut (Any + Send) { - let contents = mem::replace(self.fill(), String::new()); - Box::into_raw(Box::new(contents)) - } +unsafe impl<'a> BoxMeUp for PanicPayload<'a> { + fn box_me_up(&mut self) -> *mut (Any + Send) { + let contents = mem::replace(self.fill(), String::new()); + Box::into_raw(Box::new(contents)) + } - fn get(&mut self) -> &(Any + Send) { - self.fill() - } + fn get(&mut self) -> &(Any + Send) { + self.fill() } } +/// The entry point for panicking with a formatted message. +/// +/// This is designed to reduce the amount of code required at the call +/// site as much as possible (so that `panic!()` has as low an impact +/// on (e.g.) the inlining of other functions as possible), by moving +/// the actual formatting into this shared place. +#[cfg(not(stage0))] +#[unstable(feature = "libstd_sys_internals", + reason = "used by the panic! macro", + issue = "0")] +#[inline(never)] #[cold] +pub fn begin_panic_fmt(msg: &fmt::Arguments, + file_line_col: &(&'static str, u32, u32)) -> ! { + let (file, line, col) = *file_line_col; + let info = PanicInfo::internal_constructor( + Some(msg), + Location::internal_constructor(file, line, col), + ); + continue_panic_fmt(&info) +} + +#[cfg(not(stage0))] +fn continue_panic_fmt(info: &PanicInfo) -> ! { + // We do two allocations here, unfortunately. But (a) they're + // required with the current scheme, and (b) we don't handle + // panic + OOM properly anyway (see comment in begin_panic + // below). + + let loc = info.location().unwrap(); // The current implementation always returns Some + let msg = info.message().unwrap(); // The current implementation always returns Some + let file_line_col = (loc.file(), loc.line(), loc.column()); + rust_panic_with_hook( + &mut PanicPayload::new(msg), + info.message(), + &file_line_col); +} + /// This is the entry point of panicking for panic!() and assert!(). #[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", @@ -431,7 +479,7 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3 /// abort or unwind. fn rust_panic_with_hook(payload: &mut BoxMeUp, message: Option<&fmt::Arguments>, - file_line_col: &(&'static str, u32, u32)) -> ! { + file_line_col: &(&str, u32, u32)) -> ! { let (file, line, col) = *file_line_col; let panics = update_panic_count(1); |
