about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-06-03 20:13:09 +0000
committerbors <bors@rust-lang.org>2018-06-03 20:13:09 +0000
commit29f48ccf396be031ee8a54e74a3a4e81866c8872 (patch)
tree2f33ba908db3f5cf869d2be0cb8e1bd98a683543 /src/libstd
parentbe5f17ccff09569c2dd22df9330364a92fec2295 (diff)
parent8ad15dea3f9ac9b0fcfad4a61a70aa47ecc4d938 (diff)
downloadrust-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.rs2
-rw-r--r--src/libstd/panicking.rs102
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);