From: Simon Sapin Date: Tue, 23 Jan 2018 15:31:53 +0000 (+0100) Subject: Move PanicInfo and Location to libcore X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=2f98f4b12b8fd5d93ffff3d7b98931b3f1f2b07a;p=rust.git Move PanicInfo and Location to libcore Per https://rust-lang.github.io/rfcs/2070-panic-implementation.html --- diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index d5190b65863..11476a05dd3 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -158,6 +158,7 @@ pub mod sync; pub mod cell; pub mod char; +pub mod panic; pub mod panicking; pub mod iter; pub mod option; diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs new file mode 100644 index 00000000000..dbfe531063b --- /dev/null +++ b/src/libcore/panic.rs @@ -0,0 +1,213 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Panic support in the standard library. + +#![unstable(feature = "core_panic_info", + reason = "newly available in libcore", + issue = "44489")] + +use any::Any; + +/// A struct providing information about a panic. +/// +/// `PanicInfo` structure is passed to a panic hook set by the [`set_hook`] +/// function. +/// +/// [`set_hook`]: ../../std/panic/fn.set_hook.html +/// +/// # Examples +/// +/// ```should_panic +/// use std::panic; +/// +/// panic::set_hook(Box::new(|panic_info| { +/// println!("panic occurred: {:?}", panic_info.payload().downcast_ref::<&str>().unwrap()); +/// })); +/// +/// panic!("Normal panic"); +/// ``` +#[stable(feature = "panic_hooks", since = "1.10.0")] +#[derive(Debug)] +pub struct PanicInfo<'a> { + payload: &'a (Any + Send), + location: Location<'a>, +} + +impl<'a> PanicInfo<'a> { + #![unstable(feature = "panic_internals", + reason = "internal details of the implementation of the `panic!` \ + and related macros", + issue = "0")] + #[doc(hidden)] + pub fn internal_constructor(payload: &'a (Any + Send), location: Location<'a>,) -> Self { + PanicInfo { payload, location } + } + + /// Returns the payload associated with the panic. + /// + /// This will commonly, but not always, be a `&'static str` or [`String`]. + /// + /// [`String`]: ../../std/string/struct.String.html + /// + /// # Examples + /// + /// ```should_panic + /// use std::panic; + /// + /// panic::set_hook(Box::new(|panic_info| { + /// println!("panic occurred: {:?}", panic_info.payload().downcast_ref::<&str>().unwrap()); + /// })); + /// + /// panic!("Normal panic"); + /// ``` + #[stable(feature = "panic_hooks", since = "1.10.0")] + pub fn payload(&self) -> &(Any + Send) { + self.payload + } + + /// Returns information about the location from which the panic originated, + /// if available. + /// + /// This method will currently always return [`Some`], but this may change + /// in future versions. + /// + /// [`Some`]: ../../std/option/enum.Option.html#variant.Some + /// + /// # Examples + /// + /// ```should_panic + /// use std::panic; + /// + /// panic::set_hook(Box::new(|panic_info| { + /// if let Some(location) = panic_info.location() { + /// println!("panic occurred in file '{}' at line {}", location.file(), + /// location.line()); + /// } else { + /// println!("panic occurred but can't get location information..."); + /// } + /// })); + /// + /// panic!("Normal panic"); + /// ``` + #[stable(feature = "panic_hooks", since = "1.10.0")] + pub fn location(&self) -> Option<&Location> { + // NOTE: If this is changed to sometimes return None, + // deal with that case in std::panicking::default_hook. + Some(&self.location) + } +} + +/// A struct containing information about the location of a panic. +/// +/// This structure is created by the [`location`] method of [`PanicInfo`]. +/// +/// [`location`]: ../../std/panic/struct.PanicInfo.html#method.location +/// [`PanicInfo`]: ../../std/panic/struct.PanicInfo.html +/// +/// # Examples +/// +/// ```should_panic +/// use std::panic; +/// +/// panic::set_hook(Box::new(|panic_info| { +/// if let Some(location) = panic_info.location() { +/// println!("panic occurred in file '{}' at line {}", location.file(), location.line()); +/// } else { +/// println!("panic occurred but can't get location information..."); +/// } +/// })); +/// +/// panic!("Normal panic"); +/// ``` +#[derive(Debug)] +#[stable(feature = "panic_hooks", since = "1.10.0")] +pub struct Location<'a> { + file: &'a str, + line: u32, + col: u32, +} + +impl<'a> Location<'a> { + #![unstable(feature = "panic_internals", + reason = "internal details of the implementation of the `panic!` \ + and related macros", + issue = "0")] + #[doc(hidden)] + pub fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self { + Location { file, line, col } + } + + /// Returns the name of the source file from which the panic originated. + /// + /// # Examples + /// + /// ```should_panic + /// use std::panic; + /// + /// panic::set_hook(Box::new(|panic_info| { + /// if let Some(location) = panic_info.location() { + /// println!("panic occurred in file '{}'", location.file()); + /// } else { + /// println!("panic occurred but can't get location information..."); + /// } + /// })); + /// + /// panic!("Normal panic"); + /// ``` + #[stable(feature = "panic_hooks", since = "1.10.0")] + pub fn file(&self) -> &str { + self.file + } + + /// Returns the line number from which the panic originated. + /// + /// # Examples + /// + /// ```should_panic + /// use std::panic; + /// + /// panic::set_hook(Box::new(|panic_info| { + /// if let Some(location) = panic_info.location() { + /// println!("panic occurred at line {}", location.line()); + /// } else { + /// println!("panic occurred but can't get location information..."); + /// } + /// })); + /// + /// panic!("Normal panic"); + /// ``` + #[stable(feature = "panic_hooks", since = "1.10.0")] + pub fn line(&self) -> u32 { + self.line + } + + /// Returns the column from which the panic originated. + /// + /// # Examples + /// + /// ```should_panic + /// use std::panic; + /// + /// panic::set_hook(Box::new(|panic_info| { + /// if let Some(location) = panic_info.location() { + /// println!("panic occurred at column {}", location.column()); + /// } else { + /// println!("panic occurred but can't get location information..."); + /// } + /// })); + /// + /// panic!("Normal panic"); + /// ``` + #[stable(feature = "panic_col", since = "1.25")] + pub fn column(&self) -> u32 { + self.col + } +} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 91cc6d25cce..4b374dc1407 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -288,6 +288,7 @@ #![feature(on_unimplemented)] #![feature(oom)] #![feature(optin_builtin_traits)] +#![feature(panic_internals)] #![feature(panic_unwind)] #![feature(peek)] #![feature(placement_in_syntax)] diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index 560876006d3..566ef16f295 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -23,7 +23,10 @@ use thread::Result; #[stable(feature = "panic_hooks", since = "1.10.0")] -pub use panicking::{take_hook, set_hook, PanicInfo, Location}; +pub use panicking::{take_hook, set_hook}; + +#[stable(feature = "panic_hooks", since = "1.10.0")] +pub use core::panic::{PanicInfo, Location}; /// A marker trait which represents "panic safe" types in Rust. /// diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index f91eaf433d7..a748c89f9d4 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -21,6 +21,7 @@ use any::Any; use cell::RefCell; +use core::panic::{PanicInfo, Location}; use fmt; use intrinsics; use mem; @@ -158,182 +159,6 @@ pub fn take_hook() -> Box { } } -/// A struct providing information about a panic. -/// -/// `PanicInfo` structure is passed to a panic hook set by the [`set_hook`] -/// function. -/// -/// [`set_hook`]: ../../std/panic/fn.set_hook.html -/// -/// # Examples -/// -/// ```should_panic -/// use std::panic; -/// -/// panic::set_hook(Box::new(|panic_info| { -/// println!("panic occurred: {:?}", panic_info.payload().downcast_ref::<&str>().unwrap()); -/// })); -/// -/// panic!("Normal panic"); -/// ``` -#[stable(feature = "panic_hooks", since = "1.10.0")] -#[derive(Debug)] -pub struct PanicInfo<'a> { - payload: &'a (Any + Send), - location: Location<'a>, -} - -impl<'a> PanicInfo<'a> { - /// Returns the payload associated with the panic. - /// - /// This will commonly, but not always, be a `&'static str` or [`String`]. - /// - /// [`String`]: ../../std/string/struct.String.html - /// - /// # Examples - /// - /// ```should_panic - /// use std::panic; - /// - /// panic::set_hook(Box::new(|panic_info| { - /// println!("panic occurred: {:?}", panic_info.payload().downcast_ref::<&str>().unwrap()); - /// })); - /// - /// panic!("Normal panic"); - /// ``` - #[stable(feature = "panic_hooks", since = "1.10.0")] - pub fn payload(&self) -> &(Any + Send) { - self.payload - } - - /// Returns information about the location from which the panic originated, - /// if available. - /// - /// This method will currently always return [`Some`], but this may change - /// in future versions. - /// - /// [`Some`]: ../../std/option/enum.Option.html#variant.Some - /// - /// # Examples - /// - /// ```should_panic - /// use std::panic; - /// - /// panic::set_hook(Box::new(|panic_info| { - /// if let Some(location) = panic_info.location() { - /// println!("panic occurred in file '{}' at line {}", location.file(), - /// location.line()); - /// } else { - /// println!("panic occurred but can't get location information..."); - /// } - /// })); - /// - /// panic!("Normal panic"); - /// ``` - #[stable(feature = "panic_hooks", since = "1.10.0")] - pub fn location(&self) -> Option<&Location> { - Some(&self.location) - } -} - -/// A struct containing information about the location of a panic. -/// -/// This structure is created by the [`location`] method of [`PanicInfo`]. -/// -/// [`location`]: ../../std/panic/struct.PanicInfo.html#method.location -/// [`PanicInfo`]: ../../std/panic/struct.PanicInfo.html -/// -/// # Examples -/// -/// ```should_panic -/// use std::panic; -/// -/// panic::set_hook(Box::new(|panic_info| { -/// if let Some(location) = panic_info.location() { -/// println!("panic occurred in file '{}' at line {}", location.file(), location.line()); -/// } else { -/// println!("panic occurred but can't get location information..."); -/// } -/// })); -/// -/// panic!("Normal panic"); -/// ``` -#[derive(Debug)] -#[stable(feature = "panic_hooks", since = "1.10.0")] -pub struct Location<'a> { - file: &'a str, - line: u32, - col: u32, -} - -impl<'a> Location<'a> { - /// Returns the name of the source file from which the panic originated. - /// - /// # Examples - /// - /// ```should_panic - /// use std::panic; - /// - /// panic::set_hook(Box::new(|panic_info| { - /// if let Some(location) = panic_info.location() { - /// println!("panic occurred in file '{}'", location.file()); - /// } else { - /// println!("panic occurred but can't get location information..."); - /// } - /// })); - /// - /// panic!("Normal panic"); - /// ``` - #[stable(feature = "panic_hooks", since = "1.10.0")] - pub fn file(&self) -> &str { - self.file - } - - /// Returns the line number from which the panic originated. - /// - /// # Examples - /// - /// ```should_panic - /// use std::panic; - /// - /// panic::set_hook(Box::new(|panic_info| { - /// if let Some(location) = panic_info.location() { - /// println!("panic occurred at line {}", location.line()); - /// } else { - /// println!("panic occurred but can't get location information..."); - /// } - /// })); - /// - /// panic!("Normal panic"); - /// ``` - #[stable(feature = "panic_hooks", since = "1.10.0")] - pub fn line(&self) -> u32 { - self.line - } - - /// Returns the column from which the panic originated. - /// - /// # Examples - /// - /// ```should_panic - /// use std::panic; - /// - /// panic::set_hook(Box::new(|panic_info| { - /// if let Some(location) = panic_info.location() { - /// println!("panic occurred at column {}", location.column()); - /// } else { - /// println!("panic occurred but can't get location information..."); - /// } - /// })); - /// - /// panic!("Normal panic"); - /// ``` - #[stable(feature = "panic_col", since = "1.25")] - pub fn column(&self) -> u32 { - self.col - } -} - fn default_hook(info: &PanicInfo) { #[cfg(feature = "backtrace")] use sys_common::backtrace; @@ -351,13 +176,14 @@ fn default_hook(info: &PanicInfo) { } }; - let file = info.location.file; - let line = info.location.line; - let col = info.location.col; + let location = info.location().unwrap(); // The current implementation always returns Some + let file = location.file(); + let line = location.line(); + let col = location.column(); - let msg = match info.payload.downcast_ref::<&'static str>() { + let msg = match info.payload().downcast_ref::<&'static str>() { Some(s) => *s, - None => match info.payload.downcast_ref::() { + None => match info.payload().downcast_ref::() { Some(s) => &s[..], None => "Box", } @@ -563,14 +389,10 @@ fn rust_panic_with_hook(msg: Box, } unsafe { - let info = PanicInfo { - payload: &*msg, - location: Location { - file, - line, - col, - }, - }; + let info = PanicInfo::internal_constructor( + &*msg, + Location::internal_constructor(file, line, col), + ); HOOK_LOCK.read(); match HOOK { Hook::Default => default_hook(&info),