mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #126284 - jieyouxu:rollup-nq7bf9k, r=jieyouxu
Rollup of 6 pull requests Successful merges: - #115974 (Split core's PanicInfo and std's PanicInfo) - #125659 (Remove usage of `isize` in example) - #125669 (CI: Update riscv64gc-linux job to Ubuntu 22.04, rename to riscv64gc-gnu) - #125684 (Account for existing bindings when suggesting `pin!()`) - #126055 (Expand list of trait implementers in E0277 when calling rustc with --verbose) - #126174 (Migrate `tests/run-make/prefer-dylib` to `rmake.rs`) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
ebcb862bbb
@ -52,7 +52,7 @@ use std::ffi::OsString;
|
|||||||
use std::fmt::Write as _;
|
use std::fmt::Write as _;
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::{self, IsTerminal, Read, Write};
|
use std::io::{self, IsTerminal, Read, Write};
|
||||||
use std::panic::{self, catch_unwind, PanicInfo};
|
use std::panic::{self, catch_unwind, PanicHookInfo};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::{self, Command, Stdio};
|
use std::process::{self, Command, Stdio};
|
||||||
use std::str;
|
use std::str;
|
||||||
@ -1366,11 +1366,10 @@ pub fn install_ice_hook(
|
|||||||
let using_internal_features = Arc::new(std::sync::atomic::AtomicBool::default());
|
let using_internal_features = Arc::new(std::sync::atomic::AtomicBool::default());
|
||||||
let using_internal_features_hook = using_internal_features.clone();
|
let using_internal_features_hook = using_internal_features.clone();
|
||||||
panic::update_hook(Box::new(
|
panic::update_hook(Box::new(
|
||||||
move |default_hook: &(dyn Fn(&PanicInfo<'_>) + Send + Sync + 'static),
|
move |default_hook: &(dyn Fn(&PanicHookInfo<'_>) + Send + Sync + 'static),
|
||||||
info: &PanicInfo<'_>| {
|
info: &PanicHookInfo<'_>| {
|
||||||
// Lock stderr to prevent interleaving of concurrent panics.
|
// Lock stderr to prevent interleaving of concurrent panics.
|
||||||
let _guard = io::stderr().lock();
|
let _guard = io::stderr().lock();
|
||||||
|
|
||||||
// If the error was caused by a broken pipe then this is not a bug.
|
// If the error was caused by a broken pipe then this is not a bug.
|
||||||
// Write the error and return immediately. See #98700.
|
// Write the error and return immediately. See #98700.
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@ -1431,7 +1430,7 @@ pub fn install_ice_hook(
|
|||||||
/// When `install_ice_hook` is called, this function will be called as the panic
|
/// When `install_ice_hook` is called, this function will be called as the panic
|
||||||
/// hook.
|
/// hook.
|
||||||
fn report_ice(
|
fn report_ice(
|
||||||
info: &panic::PanicInfo<'_>,
|
info: &panic::PanicHookInfo<'_>,
|
||||||
bug_report_url: &str,
|
bug_report_url: &str,
|
||||||
extra_info: fn(&DiagCtxt),
|
extra_info: fn(&DiagCtxt),
|
||||||
using_internal_features: &AtomicBool,
|
using_internal_features: &AtomicBool,
|
||||||
|
@ -3360,14 +3360,66 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
.source_map()
|
.source_map()
|
||||||
.indentation_before(rcvr.span)
|
.indentation_before(rcvr.span)
|
||||||
.unwrap_or_else(|| " ".to_string());
|
.unwrap_or_else(|| " ".to_string());
|
||||||
err.multipart_suggestion(
|
let mut expr = rcvr;
|
||||||
"consider pinning the expression",
|
while let Node::Expr(call_expr) = self.tcx.parent_hir_node(expr.hir_id)
|
||||||
vec![
|
&& let hir::ExprKind::MethodCall(hir::PathSegment { .. }, ..) =
|
||||||
(rcvr.span.shrink_to_lo(), format!("let mut pinned = std::pin::pin!(")),
|
call_expr.kind
|
||||||
(rcvr.span.shrink_to_hi(), format!(");\n{indent}pinned.{pin_call}()")),
|
{
|
||||||
],
|
expr = call_expr;
|
||||||
Applicability::MaybeIncorrect,
|
}
|
||||||
);
|
match self.tcx.parent_hir_node(expr.hir_id) {
|
||||||
|
Node::LetStmt(stmt)
|
||||||
|
if let Some(init) = stmt.init
|
||||||
|
&& let Ok(code) =
|
||||||
|
self.tcx.sess.source_map().span_to_snippet(rcvr.span) =>
|
||||||
|
{
|
||||||
|
// We need to take care to account for the existing binding when we
|
||||||
|
// suggest the code.
|
||||||
|
err.multipart_suggestion(
|
||||||
|
"consider pinning the expression",
|
||||||
|
vec![
|
||||||
|
(
|
||||||
|
stmt.span.shrink_to_lo(),
|
||||||
|
format!(
|
||||||
|
"let mut pinned = std::pin::pin!({code});\n{indent}"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
init.span.until(rcvr.span.shrink_to_hi()),
|
||||||
|
format!("pinned.{pin_call}()"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Node::Block(_) | Node::Stmt(_) => {
|
||||||
|
// There's no binding, so we can provide a slightly nicer looking
|
||||||
|
// suggestion.
|
||||||
|
err.multipart_suggestion(
|
||||||
|
"consider pinning the expression",
|
||||||
|
vec![
|
||||||
|
(
|
||||||
|
rcvr.span.shrink_to_lo(),
|
||||||
|
format!("let mut pinned = std::pin::pin!("),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
rcvr.span.shrink_to_hi(),
|
||||||
|
format!(");\n{indent}pinned.{pin_call}()"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// We don't quite know what the users' code looks like, so we don't
|
||||||
|
// provide a pinning suggestion.
|
||||||
|
err.span_help(
|
||||||
|
rcvr.span,
|
||||||
|
"consider pinning the expression with `std::pin::pin!()` and \
|
||||||
|
assigning that to a new binding",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
// We don't care about the other suggestions.
|
// We don't care about the other suggestions.
|
||||||
alt_rcvr_sugg = true;
|
alt_rcvr_sugg = true;
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,7 @@ declare_lint! {
|
|||||||
/// ```rust,compile_fail
|
/// ```rust,compile_fail
|
||||||
/// #![deny(box_pointers)]
|
/// #![deny(box_pointers)]
|
||||||
/// struct Foo {
|
/// struct Foo {
|
||||||
/// x: Box<isize>,
|
/// x: Box<i32>,
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
@ -2069,12 +2069,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let end = if candidates.len() <= 9 { candidates.len() } else { 8 };
|
let end = if candidates.len() <= 9 || self.tcx.sess.opts.verbose {
|
||||||
|
candidates.len()
|
||||||
|
} else {
|
||||||
|
8
|
||||||
|
};
|
||||||
err.help(format!(
|
err.help(format!(
|
||||||
"the following {other}types implement trait `{}`:{}{}",
|
"the following {other}types implement trait `{}`:{}{}",
|
||||||
trait_ref.print_trait_sugared(),
|
trait_ref.print_trait_sugared(),
|
||||||
candidates[..end].join(""),
|
candidates[..end].join(""),
|
||||||
if candidates.len() > 9 {
|
if candidates.len() > 9 && !self.tcx.sess.opts.verbose {
|
||||||
format!("\nand {} others", candidates.len() - 8)
|
format!("\nand {} others", candidates.len() - 8)
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
|
@ -17,8 +17,8 @@ The following are the primary interfaces of the panic system and the
|
|||||||
responsibilities they cover:
|
responsibilities they cover:
|
||||||
|
|
||||||
* [`panic!`] and [`panic_any`] (Constructing, Propagated automatically)
|
* [`panic!`] and [`panic_any`] (Constructing, Propagated automatically)
|
||||||
* [`PanicInfo`] (Reporting)
|
* [`set_hook`], [`take_hook`], and [`PanicHookInfo`] (Reporting)
|
||||||
* [`set_hook`], [`take_hook`], and [`#[panic_handler]`][panic-handler] (Reporting)
|
* [`#[panic_handler]`][panic-handler] and [`PanicInfo`] (Reporting in no_std)
|
||||||
* [`catch_unwind`] and [`resume_unwind`] (Discarding, Propagating)
|
* [`catch_unwind`] and [`resume_unwind`] (Discarding, Propagating)
|
||||||
|
|
||||||
The following are the primary interfaces of the error system and the
|
The following are the primary interfaces of the error system and the
|
||||||
@ -125,6 +125,7 @@ expect-as-precondition style error messages remember to focus on the word
|
|||||||
should be available and executable by the current user".
|
should be available and executable by the current user".
|
||||||
|
|
||||||
[`panic_any`]: ../../std/panic/fn.panic_any.html
|
[`panic_any`]: ../../std/panic/fn.panic_any.html
|
||||||
|
[`PanicHookInfo`]: ../../std/panic/struct.PanicHookInfo.html
|
||||||
[`PanicInfo`]: crate::panic::PanicInfo
|
[`PanicInfo`]: crate::panic::PanicInfo
|
||||||
[`catch_unwind`]: ../../std/panic/fn.catch_unwind.html
|
[`catch_unwind`]: ../../std/panic/fn.catch_unwind.html
|
||||||
[`resume_unwind`]: ../../std/panic/fn.resume_unwind.html
|
[`resume_unwind`]: ../../std/panic/fn.resume_unwind.html
|
||||||
|
@ -144,7 +144,7 @@ pub macro unreachable_2021 {
|
|||||||
/// use.
|
/// use.
|
||||||
#[unstable(feature = "std_internals", issue = "none")]
|
#[unstable(feature = "std_internals", issue = "none")]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub unsafe trait PanicPayload {
|
pub unsafe trait PanicPayload: crate::fmt::Display {
|
||||||
/// Take full ownership of the contents.
|
/// Take full ownership of the contents.
|
||||||
/// The return type is actually `Box<dyn Any + Send>`, but we cannot use `Box` in core.
|
/// The return type is actually `Box<dyn Any + Send>`, but we cannot use `Box` in core.
|
||||||
///
|
///
|
||||||
@ -157,4 +157,9 @@ pub unsafe trait PanicPayload {
|
|||||||
|
|
||||||
/// Just borrow the contents.
|
/// Just borrow the contents.
|
||||||
fn get(&mut self) -> &(dyn Any + Send);
|
fn get(&mut self) -> &(dyn Any + Send);
|
||||||
|
|
||||||
|
/// Try to borrow the contents as `&str`, if possible without doing any allocations.
|
||||||
|
fn as_str(&mut self) -> Option<&str> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,10 @@ use crate::fmt;
|
|||||||
|
|
||||||
/// A struct containing information about the location of a panic.
|
/// A struct containing information about the location of a panic.
|
||||||
///
|
///
|
||||||
/// This structure is created by [`PanicInfo::location()`].
|
/// This structure is created by [`PanicHookInfo::location()`] and [`PanicInfo::location()`].
|
||||||
///
|
///
|
||||||
/// [`PanicInfo::location()`]: crate::panic::PanicInfo::location
|
/// [`PanicInfo::location()`]: crate::panic::PanicInfo::location
|
||||||
|
/// [`PanicHookInfo::location()`]: ../../std/panic/struct.PanicHookInfo.html#method.location
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -1,90 +1,32 @@
|
|||||||
use crate::any::Any;
|
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::panic::Location;
|
use crate::panic::Location;
|
||||||
|
|
||||||
/// A struct providing information about a panic.
|
/// A struct providing information about a panic.
|
||||||
///
|
///
|
||||||
/// `PanicInfo` structure is passed to a panic hook set by the [`set_hook`]
|
/// A `PanicInfo` structure is passed to the panic handler defined by `#[panic_handler]`.
|
||||||
/// function.
|
|
||||||
///
|
///
|
||||||
/// [`set_hook`]: ../../std/panic/fn.set_hook.html
|
/// For the type used by the panic hook mechanism in `std`, see [`std::panic::PanicHookInfo`].
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// [`std::panic::PanicHookInfo`]: ../../std/panic/struct.PanicHookInfo.html
|
||||||
///
|
|
||||||
/// ```should_panic
|
|
||||||
/// use std::panic;
|
|
||||||
///
|
|
||||||
/// panic::set_hook(Box::new(|panic_info| {
|
|
||||||
/// println!("panic occurred: {panic_info}");
|
|
||||||
/// }));
|
|
||||||
///
|
|
||||||
/// panic!("critical system failure");
|
|
||||||
/// ```
|
|
||||||
#[lang = "panic_info"]
|
#[lang = "panic_info"]
|
||||||
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PanicInfo<'a> {
|
pub struct PanicInfo<'a> {
|
||||||
payload: &'a (dyn Any + Send),
|
message: fmt::Arguments<'a>,
|
||||||
message: Option<&'a fmt::Arguments<'a>>,
|
|
||||||
location: &'a Location<'a>,
|
location: &'a Location<'a>,
|
||||||
can_unwind: bool,
|
can_unwind: bool,
|
||||||
force_no_backtrace: bool,
|
force_no_backtrace: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PanicInfo<'a> {
|
impl<'a> PanicInfo<'a> {
|
||||||
#[unstable(
|
|
||||||
feature = "panic_internals",
|
|
||||||
reason = "internal details of the implementation of the `panic!` and related macros",
|
|
||||||
issue = "none"
|
|
||||||
)]
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn internal_constructor(
|
pub(crate) fn new(
|
||||||
message: Option<&'a fmt::Arguments<'a>>,
|
message: fmt::Arguments<'a>,
|
||||||
location: &'a Location<'a>,
|
location: &'a Location<'a>,
|
||||||
can_unwind: bool,
|
can_unwind: bool,
|
||||||
force_no_backtrace: bool,
|
force_no_backtrace: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
struct NoPayload;
|
PanicInfo { location, message, can_unwind, force_no_backtrace }
|
||||||
PanicInfo { location, message, payload: &NoPayload, can_unwind, force_no_backtrace }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unstable(
|
|
||||||
feature = "panic_internals",
|
|
||||||
reason = "internal details of the implementation of the `panic!` and related macros",
|
|
||||||
issue = "none"
|
|
||||||
)]
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[inline]
|
|
||||||
pub fn set_payload(&mut self, info: &'a (dyn Any + Send)) {
|
|
||||||
self.payload = info;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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| {
|
|
||||||
/// if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
|
|
||||||
/// println!("panic occurred: {s:?}");
|
|
||||||
/// } else {
|
|
||||||
/// println!("panic occurred");
|
|
||||||
/// }
|
|
||||||
/// }));
|
|
||||||
///
|
|
||||||
/// panic!("Normal panic");
|
|
||||||
/// ```
|
|
||||||
#[must_use]
|
|
||||||
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
|
||||||
pub fn payload(&self) -> &(dyn Any + Send) {
|
|
||||||
self.payload
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the `panic!` macro from the `core` crate (not from `std`)
|
/// If the `panic!` macro from the `core` crate (not from `std`)
|
||||||
@ -92,7 +34,7 @@ impl<'a> PanicInfo<'a> {
|
|||||||
/// returns that message ready to be used for example with [`fmt::write`]
|
/// returns that message ready to be used for example with [`fmt::write`]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "panic_info_message", issue = "66745")]
|
#[unstable(feature = "panic_info_message", issue = "66745")]
|
||||||
pub fn message(&self) -> Option<&fmt::Arguments<'_>> {
|
pub fn message(&self) -> fmt::Arguments<'_> {
|
||||||
self.message
|
self.message
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +70,24 @@ impl<'a> PanicInfo<'a> {
|
|||||||
Some(&self.location)
|
Some(&self.location)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the payload associated with the panic.
|
||||||
|
///
|
||||||
|
/// On `core::panic::PanicInfo`, this method never returns anything useful.
|
||||||
|
/// It only exists because of compatibility with [`std::panic::PanicHookInfo`],
|
||||||
|
/// which used to be the same type.
|
||||||
|
///
|
||||||
|
/// See [`std::panic::PanicHookInfo::payload`].
|
||||||
|
///
|
||||||
|
/// [`std::panic::PanicHookInfo`]: ../../std/panic/struct.PanicHookInfo.html
|
||||||
|
/// [`std::panic::PanicHookInfo::payload`]: ../../std/panic/struct.PanicHookInfo.html#method.payload
|
||||||
|
#[deprecated(since = "1.77.0", note = "this never returns anything useful")]
|
||||||
|
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
||||||
|
#[allow(deprecated, deprecated_in_future)]
|
||||||
|
pub fn payload(&self) -> &(dyn crate::any::Any + Send) {
|
||||||
|
struct NoPayload;
|
||||||
|
&NoPayload
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns whether the panic handler is allowed to unwind the stack from
|
/// Returns whether the panic handler is allowed to unwind the stack from
|
||||||
/// the point where the panic occurred.
|
/// the point where the panic occurred.
|
||||||
///
|
///
|
||||||
@ -161,18 +121,8 @@ impl fmt::Display for PanicInfo<'_> {
|
|||||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
formatter.write_str("panicked at ")?;
|
formatter.write_str("panicked at ")?;
|
||||||
self.location.fmt(formatter)?;
|
self.location.fmt(formatter)?;
|
||||||
formatter.write_str(":")?;
|
formatter.write_str(":\n")?;
|
||||||
if let Some(message) = self.message {
|
formatter.write_fmt(self.message)?;
|
||||||
formatter.write_str("\n")?;
|
|
||||||
formatter.write_fmt(*message)?;
|
|
||||||
} else if let Some(payload) = self.payload.downcast_ref::<&'static str>() {
|
|
||||||
formatter.write_str("\n")?;
|
|
||||||
formatter.write_str(payload)?;
|
|
||||||
}
|
|
||||||
// NOTE: we cannot use downcast_ref::<String>() here
|
|
||||||
// since String is not available in core!
|
|
||||||
// The payload is a String when `std::panic!` is called with multiple arguments,
|
|
||||||
// but in that case the message is also available.
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,14 @@
|
|||||||
//! Panic support for core
|
//! Panic support for core
|
||||||
//!
|
//!
|
||||||
//! The core library cannot define panicking, but it does *declare* panicking. This
|
//! In core, panicking is always done with a message, resulting in a `core::panic::PanicInfo`
|
||||||
//! means that the functions inside of core are allowed to panic, but to be
|
//! containing a `fmt::Arguments`. In std, however, panicking can be done with panic_any, which
|
||||||
|
//! throws a `Box<dyn Any>` containing any type of value. Because of this,
|
||||||
|
//! `std::panic::PanicHookInfo` is a different type, which contains a `&dyn Any` instead of a
|
||||||
|
//! `fmt::Arguments`. std's panic handler will convert the `fmt::Arguments` to a `&dyn Any`
|
||||||
|
//! containing either a `&'static str` or `String` containing the formatted message.
|
||||||
|
//!
|
||||||
|
//! The core library cannot define any panic handler, but it can invoke it.
|
||||||
|
//! This means that the functions inside of core are allowed to panic, but to be
|
||||||
//! useful an upstream crate must define panicking for core to use. The current
|
//! useful an upstream crate must define panicking for core to use. The current
|
||||||
//! interface for panicking is:
|
//! interface for panicking is:
|
||||||
//!
|
//!
|
||||||
@ -10,11 +17,6 @@
|
|||||||
//! # { loop {} }
|
//! # { loop {} }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! This definition allows for panicking with any general message, but it does not
|
|
||||||
//! allow for failing with a `Box<Any>` value. (`PanicInfo` just contains a `&(dyn Any + Send)`,
|
|
||||||
//! for which we fill in a dummy value in `PanicInfo::internal_constructor`.)
|
|
||||||
//! The reason for this is that core is not allowed to allocate.
|
|
||||||
//!
|
|
||||||
//! This module contains a few other panicking functions, but these are just the
|
//! This module contains a few other panicking functions, but these are just the
|
||||||
//! necessary lang items for the compiler. All panics are funneled through this
|
//! necessary lang items for the compiler. All panics are funneled through this
|
||||||
//! one function. The actual symbol is declared through the `#[panic_handler]` attribute.
|
//! one function. The actual symbol is declared through the `#[panic_handler]` attribute.
|
||||||
@ -61,8 +63,8 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
|
|||||||
fn panic_impl(pi: &PanicInfo<'_>) -> !;
|
fn panic_impl(pi: &PanicInfo<'_>) -> !;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pi = PanicInfo::internal_constructor(
|
let pi = PanicInfo::new(
|
||||||
Some(&fmt),
|
fmt,
|
||||||
Location::caller(),
|
Location::caller(),
|
||||||
/* can_unwind */ true,
|
/* can_unwind */ true,
|
||||||
/* force_no_backtrace */ false,
|
/* force_no_backtrace */ false,
|
||||||
@ -99,8 +101,8 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PanicInfo with the `can_unwind` flag set to false forces an abort.
|
// PanicInfo with the `can_unwind` flag set to false forces an abort.
|
||||||
let pi = PanicInfo::internal_constructor(
|
let pi = PanicInfo::new(
|
||||||
Some(&fmt),
|
fmt,
|
||||||
Location::caller(),
|
Location::caller(),
|
||||||
/* can_unwind */ false,
|
/* can_unwind */ false,
|
||||||
force_no_backtrace,
|
force_no_backtrace,
|
||||||
|
@ -4,11 +4,215 @@
|
|||||||
|
|
||||||
use crate::any::Any;
|
use crate::any::Any;
|
||||||
use crate::collections;
|
use crate::collections;
|
||||||
|
use crate::fmt;
|
||||||
use crate::panicking;
|
use crate::panicking;
|
||||||
use crate::sync::atomic::{AtomicU8, Ordering};
|
use crate::sync::atomic::{AtomicU8, Ordering};
|
||||||
use crate::sync::{Condvar, Mutex, RwLock};
|
use crate::sync::{Condvar, Mutex, RwLock};
|
||||||
use crate::thread::Result;
|
use crate::thread::Result;
|
||||||
|
|
||||||
|
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.82.0",
|
||||||
|
note = "use `PanicHookInfo` instead",
|
||||||
|
suggestion = "std::panic::PanicHookInfo"
|
||||||
|
)]
|
||||||
|
/// A struct providing information about a panic.
|
||||||
|
///
|
||||||
|
/// `PanicInfo` has been renamed to [`PanicHookInfo`] to avoid confusion with
|
||||||
|
/// [`core::panic::PanicInfo`].
|
||||||
|
pub type PanicInfo<'a> = PanicHookInfo<'a>;
|
||||||
|
|
||||||
|
/// A struct providing information about a panic.
|
||||||
|
///
|
||||||
|
/// `PanicHookInfo` structure is passed to a panic hook set by the [`set_hook`] function.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```should_panic
|
||||||
|
/// use std::panic;
|
||||||
|
///
|
||||||
|
/// panic::set_hook(Box::new(|panic_info| {
|
||||||
|
/// println!("panic occurred: {panic_info}");
|
||||||
|
/// }));
|
||||||
|
///
|
||||||
|
/// panic!("critical system failure");
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [`set_hook`]: ../../std/panic/fn.set_hook.html
|
||||||
|
#[stable(feature = "panic_hook_info", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PanicHookInfo<'a> {
|
||||||
|
payload: &'a (dyn Any + Send),
|
||||||
|
location: &'a Location<'a>,
|
||||||
|
can_unwind: bool,
|
||||||
|
force_no_backtrace: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> PanicHookInfo<'a> {
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn new(
|
||||||
|
location: &'a Location<'a>,
|
||||||
|
payload: &'a (dyn Any + Send),
|
||||||
|
can_unwind: bool,
|
||||||
|
force_no_backtrace: bool,
|
||||||
|
) -> Self {
|
||||||
|
PanicHookInfo { payload, location, can_unwind, force_no_backtrace }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the payload associated with the panic.
|
||||||
|
///
|
||||||
|
/// This will commonly, but not always, be a `&'static str` or [`String`].
|
||||||
|
///
|
||||||
|
/// A invocation of the `panic!()` macro in Rust 2021 or later will always result in a
|
||||||
|
/// panic payload of type `&'static str` or `String`.
|
||||||
|
///
|
||||||
|
/// Only an invocation of [`panic_any`]
|
||||||
|
/// (or, in Rust 2018 and earlier, `panic!(x)` where `x` is something other than a string)
|
||||||
|
/// can result in a panic payload other than a `&'static str` or `String`.
|
||||||
|
///
|
||||||
|
/// [`String`]: ../../std/string/struct.String.html
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```should_panic
|
||||||
|
/// use std::panic;
|
||||||
|
///
|
||||||
|
/// panic::set_hook(Box::new(|panic_info| {
|
||||||
|
/// if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
|
||||||
|
/// println!("panic occurred: {s:?}");
|
||||||
|
/// } else if let Some(s) = panic_info.payload().downcast_ref::<String>() {
|
||||||
|
/// println!("panic occurred: {s:?}");
|
||||||
|
/// } else {
|
||||||
|
/// println!("panic occurred");
|
||||||
|
/// }
|
||||||
|
/// }));
|
||||||
|
///
|
||||||
|
/// panic!("Normal panic");
|
||||||
|
/// ```
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
||||||
|
pub fn payload(&self) -> &(dyn Any + Send) {
|
||||||
|
self.payload
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the payload associated with the panic, if it is a string.
|
||||||
|
///
|
||||||
|
/// This returns the payload if it is of type `&'static str` or `String`.
|
||||||
|
///
|
||||||
|
/// A invocation of the `panic!()` macro in Rust 2021 or later will always result in a
|
||||||
|
/// panic payload where `payload_as_str` returns `Some`.
|
||||||
|
///
|
||||||
|
/// Only an invocation of [`panic_any`]
|
||||||
|
/// (or, in Rust 2018 and earlier, `panic!(x)` where `x` is something other than a string)
|
||||||
|
/// can result in a panic payload where `payload_as_str` returns `None`.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```should_panic
|
||||||
|
/// #![feature(panic_payload_as_str)]
|
||||||
|
///
|
||||||
|
/// std::panic::set_hook(Box::new(|panic_info| {
|
||||||
|
/// if let Some(s) = panic_info.payload_as_str() {
|
||||||
|
/// println!("panic occurred: {s:?}");
|
||||||
|
/// } else {
|
||||||
|
/// println!("panic occurred");
|
||||||
|
/// }
|
||||||
|
/// }));
|
||||||
|
///
|
||||||
|
/// panic!("Normal panic");
|
||||||
|
/// ```
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "panic_payload_as_str", issue = "125175")]
|
||||||
|
pub fn payload_as_str(&self) -> Option<&str> {
|
||||||
|
if let Some(s) = self.payload.downcast_ref::<&str>() {
|
||||||
|
Some(s)
|
||||||
|
} else if let Some(s) = self.payload.downcast_ref::<String>() {
|
||||||
|
Some(s)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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.
|
||||||
|
///
|
||||||
|
/// # 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");
|
||||||
|
/// ```
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
#[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 and core::panicking::panic_fmt.
|
||||||
|
Some(&self.location)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether the panic handler is allowed to unwind the stack from
|
||||||
|
/// the point where the panic occurred.
|
||||||
|
///
|
||||||
|
/// This is true for most kinds of panics with the exception of panics
|
||||||
|
/// caused by trying to unwind out of a `Drop` implementation or a function
|
||||||
|
/// whose ABI does not support unwinding.
|
||||||
|
///
|
||||||
|
/// It is safe for a panic handler to unwind even when this function returns
|
||||||
|
/// false, however this will simply cause the panic handler to be called
|
||||||
|
/// again.
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "panic_can_unwind", issue = "92988")]
|
||||||
|
pub fn can_unwind(&self) -> bool {
|
||||||
|
self.can_unwind
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(
|
||||||
|
feature = "panic_internals",
|
||||||
|
reason = "internal details of the implementation of the `panic!` and related macros",
|
||||||
|
issue = "none"
|
||||||
|
)]
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[inline]
|
||||||
|
pub fn force_no_backtrace(&self) -> bool {
|
||||||
|
self.force_no_backtrace
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "panic_hook_display", since = "1.26.0")]
|
||||||
|
impl fmt::Display for PanicHookInfo<'_> {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
formatter.write_str("panicked at ")?;
|
||||||
|
self.location.fmt(formatter)?;
|
||||||
|
if let Some(payload) = self.payload.downcast_ref::<&'static str>() {
|
||||||
|
formatter.write_str(":\n")?;
|
||||||
|
formatter.write_str(payload)?;
|
||||||
|
} else if let Some(payload) = self.payload.downcast_ref::<String>() {
|
||||||
|
formatter.write_str(":\n")?;
|
||||||
|
formatter.write_str(payload)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
|
#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
|
||||||
#[allow_internal_unstable(libstd_sys_internals, const_format_args, panic_internals, rt)]
|
#[allow_internal_unstable(libstd_sys_internals, const_format_args, panic_internals, rt)]
|
||||||
@ -43,7 +247,7 @@ pub use crate::panicking::{set_hook, take_hook};
|
|||||||
pub use crate::panicking::update_hook;
|
pub use crate::panicking::update_hook;
|
||||||
|
|
||||||
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
||||||
pub use core::panic::{Location, PanicInfo};
|
pub use core::panic::Location;
|
||||||
|
|
||||||
#[stable(feature = "catch_unwind", since = "1.9.0")]
|
#[stable(feature = "catch_unwind", since = "1.9.0")]
|
||||||
pub use core::panic::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe};
|
pub use core::panic::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe};
|
||||||
@ -53,7 +257,7 @@ pub use core::panic::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe};
|
|||||||
/// The message can be of any (`Any + Send`) type, not just strings.
|
/// The message can be of any (`Any + Send`) type, not just strings.
|
||||||
///
|
///
|
||||||
/// The message is wrapped in a `Box<'static + Any + Send>`, which can be
|
/// The message is wrapped in a `Box<'static + Any + Send>`, which can be
|
||||||
/// accessed later using [`PanicInfo::payload`].
|
/// accessed later using [`PanicHookInfo::payload`].
|
||||||
///
|
///
|
||||||
/// See the [`panic!`] macro for more information about panicking.
|
/// See the [`panic!`] macro for more information about panicking.
|
||||||
#[stable(feature = "panic_any", since = "1.51.0")]
|
#[stable(feature = "panic_any", since = "1.51.0")]
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
#![deny(unsafe_op_in_unsafe_fn)]
|
#![deny(unsafe_op_in_unsafe_fn)]
|
||||||
|
|
||||||
use crate::panic::BacktraceStyle;
|
use crate::panic::{BacktraceStyle, PanicHookInfo};
|
||||||
use core::panic::{Location, PanicInfo, PanicPayload};
|
use core::panic::{Location, PanicPayload};
|
||||||
|
|
||||||
use crate::any::Any;
|
use crate::any::Any;
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
@ -70,12 +70,12 @@ extern "C" fn __rust_foreign_exception() -> ! {
|
|||||||
|
|
||||||
enum Hook {
|
enum Hook {
|
||||||
Default,
|
Default,
|
||||||
Custom(Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>),
|
Custom(Box<dyn Fn(&PanicHookInfo<'_>) + 'static + Sync + Send>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hook {
|
impl Hook {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_box(self) -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
|
fn into_box(self) -> Box<dyn Fn(&PanicHookInfo<'_>) + 'static + Sync + Send> {
|
||||||
match self {
|
match self {
|
||||||
Hook::Default => Box::new(default_hook),
|
Hook::Default => Box::new(default_hook),
|
||||||
Hook::Custom(hook) => hook,
|
Hook::Custom(hook) => hook,
|
||||||
@ -105,7 +105,7 @@ static HOOK: RwLock<Hook> = RwLock::new(Hook::Default);
|
|||||||
///
|
///
|
||||||
/// [`take_hook`]: ./fn.take_hook.html
|
/// [`take_hook`]: ./fn.take_hook.html
|
||||||
///
|
///
|
||||||
/// The hook is provided with a `PanicInfo` struct which contains information
|
/// The hook is provided with a `PanicHookInfo` struct which contains information
|
||||||
/// about the origin of the panic, including the payload passed to `panic!` and
|
/// about the origin of the panic, including the payload passed to `panic!` and
|
||||||
/// the source code location from which the panic originated.
|
/// the source code location from which the panic originated.
|
||||||
///
|
///
|
||||||
@ -129,7 +129,7 @@ static HOOK: RwLock<Hook> = RwLock::new(Hook::Default);
|
|||||||
/// panic!("Normal panic");
|
/// panic!("Normal panic");
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
||||||
pub fn set_hook(hook: Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>) {
|
pub fn set_hook(hook: Box<dyn Fn(&PanicHookInfo<'_>) + 'static + Sync + Send>) {
|
||||||
if thread::panicking() {
|
if thread::panicking() {
|
||||||
panic!("cannot modify the panic hook from a panicking thread");
|
panic!("cannot modify the panic hook from a panicking thread");
|
||||||
}
|
}
|
||||||
@ -173,7 +173,7 @@ pub fn set_hook(hook: Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>) {
|
|||||||
/// ```
|
/// ```
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
||||||
pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
|
pub fn take_hook() -> Box<dyn Fn(&PanicHookInfo<'_>) + 'static + Sync + Send> {
|
||||||
if thread::panicking() {
|
if thread::panicking() {
|
||||||
panic!("cannot modify the panic hook from a panicking thread");
|
panic!("cannot modify the panic hook from a panicking thread");
|
||||||
}
|
}
|
||||||
@ -219,7 +219,7 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
|
|||||||
#[unstable(feature = "panic_update_hook", issue = "92649")]
|
#[unstable(feature = "panic_update_hook", issue = "92649")]
|
||||||
pub fn update_hook<F>(hook_fn: F)
|
pub fn update_hook<F>(hook_fn: F)
|
||||||
where
|
where
|
||||||
F: Fn(&(dyn Fn(&PanicInfo<'_>) + Send + Sync + 'static), &PanicInfo<'_>)
|
F: Fn(&(dyn Fn(&PanicHookInfo<'_>) + Send + Sync + 'static), &PanicHookInfo<'_>)
|
||||||
+ Sync
|
+ Sync
|
||||||
+ Send
|
+ Send
|
||||||
+ 'static,
|
+ 'static,
|
||||||
@ -234,7 +234,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The default panic handler.
|
/// The default panic handler.
|
||||||
fn default_hook(info: &PanicInfo<'_>) {
|
fn default_hook(info: &PanicHookInfo<'_>) {
|
||||||
// If this is a double panic, make sure that we print a backtrace
|
// If this is a double panic, make sure that we print a backtrace
|
||||||
// for this panic. Otherwise only print it if logging is enabled.
|
// for this panic. Otherwise only print it if logging is enabled.
|
||||||
let backtrace = if info.force_no_backtrace() {
|
let backtrace = if info.force_no_backtrace() {
|
||||||
@ -248,13 +248,7 @@ fn default_hook(info: &PanicInfo<'_>) {
|
|||||||
// The current implementation always returns `Some`.
|
// The current implementation always returns `Some`.
|
||||||
let location = info.location().unwrap();
|
let location = info.location().unwrap();
|
||||||
|
|
||||||
let msg = match info.payload().downcast_ref::<&'static str>() {
|
let msg = payload_as_str(info.payload());
|
||||||
Some(s) => *s,
|
|
||||||
None => match info.payload().downcast_ref::<String>() {
|
|
||||||
Some(s) => &s[..],
|
|
||||||
None => "Box<dyn Any>",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
let thread = thread::try_current();
|
let thread = thread::try_current();
|
||||||
let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
|
let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
|
||||||
|
|
||||||
@ -597,17 +591,13 @@ pub fn panicking() -> bool {
|
|||||||
/// Entry point of panics from the core crate (`panic_impl` lang item).
|
/// Entry point of panics from the core crate (`panic_impl` lang item).
|
||||||
#[cfg(not(any(test, doctest)))]
|
#[cfg(not(any(test, doctest)))]
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
|
pub fn begin_panic_handler(info: &core::panic::PanicInfo<'_>) -> ! {
|
||||||
struct FormatStringPayload<'a> {
|
struct FormatStringPayload<'a> {
|
||||||
inner: &'a fmt::Arguments<'a>,
|
inner: &'a fmt::Arguments<'a>,
|
||||||
string: Option<String>,
|
string: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FormatStringPayload<'a> {
|
impl FormatStringPayload<'_> {
|
||||||
fn new(inner: &'a fmt::Arguments<'a>) -> Self {
|
|
||||||
Self { inner, string: None }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fill(&mut self) -> &mut String {
|
fn fill(&mut self) -> &mut String {
|
||||||
use crate::fmt::Write;
|
use crate::fmt::Write;
|
||||||
|
|
||||||
@ -621,7 +611,7 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<'a> PanicPayload for FormatStringPayload<'a> {
|
unsafe impl PanicPayload for FormatStringPayload<'_> {
|
||||||
fn take_box(&mut self) -> *mut (dyn Any + Send) {
|
fn take_box(&mut self) -> *mut (dyn Any + Send) {
|
||||||
// We do two allocations here, unfortunately. But (a) they're required with the current
|
// 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
|
// scheme, and (b) we don't handle panic + OOM properly anyway (see comment in
|
||||||
@ -635,6 +625,12 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for FormatStringPayload<'_> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
if let Some(s) = &self.string { f.write_str(s) } else { f.write_fmt(*self.inner) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct StaticStrPayload(&'static str);
|
struct StaticStrPayload(&'static str);
|
||||||
|
|
||||||
unsafe impl PanicPayload for StaticStrPayload {
|
unsafe impl PanicPayload for StaticStrPayload {
|
||||||
@ -645,25 +641,31 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
|
|||||||
fn get(&mut self) -> &(dyn Any + Send) {
|
fn get(&mut self) -> &(dyn Any + Send) {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_str(&mut self) -> Option<&str> {
|
||||||
|
Some(self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for StaticStrPayload {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str(self.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let loc = info.location().unwrap(); // The current implementation always returns Some
|
let loc = info.location().unwrap(); // The current implementation always returns Some
|
||||||
let msg = info.message().unwrap(); // The current implementation always returns Some
|
let msg = info.message();
|
||||||
crate::sys_common::backtrace::__rust_end_short_backtrace(move || {
|
crate::sys_common::backtrace::__rust_end_short_backtrace(move || {
|
||||||
// FIXME: can we just pass `info` along rather than taking it apart here, only to have
|
if let Some(s) = msg.as_str() {
|
||||||
// `rust_panic_with_hook` construct a new `PanicInfo`?
|
|
||||||
if let Some(msg) = msg.as_str() {
|
|
||||||
rust_panic_with_hook(
|
rust_panic_with_hook(
|
||||||
&mut StaticStrPayload(msg),
|
&mut StaticStrPayload(s),
|
||||||
info.message(),
|
|
||||||
loc,
|
loc,
|
||||||
info.can_unwind(),
|
info.can_unwind(),
|
||||||
info.force_no_backtrace(),
|
info.force_no_backtrace(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
rust_panic_with_hook(
|
rust_panic_with_hook(
|
||||||
&mut FormatStringPayload::new(msg),
|
&mut FormatStringPayload { inner: &msg, string: None },
|
||||||
info.message(),
|
|
||||||
loc,
|
loc,
|
||||||
info.can_unwind(),
|
info.can_unwind(),
|
||||||
info.force_no_backtrace(),
|
info.force_no_backtrace(),
|
||||||
@ -689,27 +691,10 @@ pub const fn begin_panic<M: Any + Send>(msg: M) -> ! {
|
|||||||
intrinsics::abort()
|
intrinsics::abort()
|
||||||
}
|
}
|
||||||
|
|
||||||
let loc = Location::caller();
|
|
||||||
return crate::sys_common::backtrace::__rust_end_short_backtrace(move || {
|
|
||||||
rust_panic_with_hook(
|
|
||||||
&mut Payload::new(msg),
|
|
||||||
None,
|
|
||||||
loc,
|
|
||||||
/* can_unwind */ true,
|
|
||||||
/* force_no_backtrace */ false,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
struct Payload<A> {
|
struct Payload<A> {
|
||||||
inner: Option<A>,
|
inner: Option<A>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: Send + 'static> Payload<A> {
|
|
||||||
fn new(inner: A) -> Payload<A> {
|
|
||||||
Payload { inner: Some(inner) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl<A: Send + 'static> PanicPayload for Payload<A> {
|
unsafe impl<A: Send + 'static> PanicPayload for Payload<A> {
|
||||||
fn take_box(&mut self) -> *mut (dyn Any + Send) {
|
fn take_box(&mut self) -> *mut (dyn Any + Send) {
|
||||||
// Note that this should be the only allocation performed in this code path. Currently
|
// Note that this should be the only allocation performed in this code path. Currently
|
||||||
@ -731,6 +716,35 @@ pub const fn begin_panic<M: Any + Send>(msg: M) -> ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<A: 'static> fmt::Display for Payload<A> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match &self.inner {
|
||||||
|
Some(a) => f.write_str(payload_as_str(a)),
|
||||||
|
None => process::abort(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let loc = Location::caller();
|
||||||
|
crate::sys_common::backtrace::__rust_end_short_backtrace(move || {
|
||||||
|
rust_panic_with_hook(
|
||||||
|
&mut Payload { inner: Some(msg) },
|
||||||
|
loc,
|
||||||
|
/* can_unwind */ true,
|
||||||
|
/* force_no_backtrace */ false,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn payload_as_str(payload: &dyn Any) -> &str {
|
||||||
|
if let Some(&s) = payload.downcast_ref::<&'static str>() {
|
||||||
|
s
|
||||||
|
} else if let Some(s) = payload.downcast_ref::<String>() {
|
||||||
|
s.as_str()
|
||||||
|
} else {
|
||||||
|
"Box<dyn Any>"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Central point for dispatching panics.
|
/// Central point for dispatching panics.
|
||||||
@ -740,7 +754,6 @@ pub const fn begin_panic<M: Any + Send>(msg: M) -> ! {
|
|||||||
/// abort or unwind.
|
/// abort or unwind.
|
||||||
fn rust_panic_with_hook(
|
fn rust_panic_with_hook(
|
||||||
payload: &mut dyn PanicPayload,
|
payload: &mut dyn PanicPayload,
|
||||||
message: Option<&fmt::Arguments<'_>>,
|
|
||||||
location: &Location<'_>,
|
location: &Location<'_>,
|
||||||
can_unwind: bool,
|
can_unwind: bool,
|
||||||
force_no_backtrace: bool,
|
force_no_backtrace: bool,
|
||||||
@ -754,35 +767,21 @@ fn rust_panic_with_hook(
|
|||||||
// Don't try to format the message in this case, perhaps that is causing the
|
// Don't try to format the message in this case, perhaps that is causing the
|
||||||
// recursive panics. However if the message is just a string, no user-defined
|
// recursive panics. However if the message is just a string, no user-defined
|
||||||
// code is involved in printing it, so that is risk-free.
|
// code is involved in printing it, so that is risk-free.
|
||||||
let msg_str = message.and_then(|m| m.as_str()).map(|m| [m]);
|
let message: &str = payload.as_str().unwrap_or_default();
|
||||||
let message = msg_str.as_ref().map(|m| fmt::Arguments::new_const(m));
|
rtprintpanic!(
|
||||||
let panicinfo = PanicInfo::internal_constructor(
|
"panicked at {location}:\n{message}\nthread panicked while processing panic. aborting.\n"
|
||||||
message.as_ref(),
|
|
||||||
location,
|
|
||||||
can_unwind,
|
|
||||||
force_no_backtrace,
|
|
||||||
);
|
);
|
||||||
rtprintpanic!("{panicinfo}\nthread panicked while processing panic. aborting.\n");
|
|
||||||
}
|
}
|
||||||
panic_count::MustAbort::AlwaysAbort => {
|
panic_count::MustAbort::AlwaysAbort => {
|
||||||
// Unfortunately, this does not print a backtrace, because creating
|
// Unfortunately, this does not print a backtrace, because creating
|
||||||
// a `Backtrace` will allocate, which we must avoid here.
|
// a `Backtrace` will allocate, which we must avoid here.
|
||||||
let panicinfo = PanicInfo::internal_constructor(
|
rtprintpanic!("aborting due to panic at {location}:\n{payload}\n");
|
||||||
message,
|
|
||||||
location,
|
|
||||||
can_unwind,
|
|
||||||
force_no_backtrace,
|
|
||||||
);
|
|
||||||
rtprintpanic!("{panicinfo}\npanicked after panic::always_abort(), aborting.\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
crate::sys::abort_internal();
|
crate::sys::abort_internal();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut info =
|
match *HOOK.read().unwrap_or_else(PoisonError::into_inner) {
|
||||||
PanicInfo::internal_constructor(message, location, can_unwind, force_no_backtrace);
|
|
||||||
let hook = HOOK.read().unwrap_or_else(PoisonError::into_inner);
|
|
||||||
match *hook {
|
|
||||||
// Some platforms (like wasm) know that printing to stderr won't ever actually
|
// Some platforms (like wasm) know that printing to stderr won't ever actually
|
||||||
// print anything, and if that's the case we can skip the default
|
// print anything, and if that's the case we can skip the default
|
||||||
// hook. Since string formatting happens lazily when calling `payload`
|
// hook. Since string formatting happens lazily when calling `payload`
|
||||||
@ -791,15 +790,17 @@ fn rust_panic_with_hook(
|
|||||||
// formatting.)
|
// formatting.)
|
||||||
Hook::Default if panic_output().is_none() => {}
|
Hook::Default if panic_output().is_none() => {}
|
||||||
Hook::Default => {
|
Hook::Default => {
|
||||||
info.set_payload(payload.get());
|
default_hook(&PanicHookInfo::new(
|
||||||
default_hook(&info);
|
location,
|
||||||
|
payload.get(),
|
||||||
|
can_unwind,
|
||||||
|
force_no_backtrace,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
Hook::Custom(ref hook) => {
|
Hook::Custom(ref hook) => {
|
||||||
info.set_payload(payload.get());
|
hook(&PanicHookInfo::new(location, payload.get(), can_unwind, force_no_backtrace));
|
||||||
hook(&info);
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
drop(hook);
|
|
||||||
|
|
||||||
// Indicate that we have finished executing the panic hook. After this point
|
// Indicate that we have finished executing the panic hook. After this point
|
||||||
// it is fine if there is a panic while executing destructors, as long as it
|
// it is fine if there is a panic while executing destructors, as long as it
|
||||||
@ -835,6 +836,12 @@ pub fn rust_panic_without_hook(payload: Box<dyn Any + Send>) -> ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for RewrapBox {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str(payload_as_str(&self.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rust_panic(&mut RewrapBox(payload))
|
rust_panic(&mut RewrapBox(payload))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ use std::{
|
|||||||
env, io,
|
env, io,
|
||||||
io::prelude::Write,
|
io::prelude::Write,
|
||||||
mem::ManuallyDrop,
|
mem::ManuallyDrop,
|
||||||
panic::{self, catch_unwind, AssertUnwindSafe, PanicInfo},
|
panic::{self, catch_unwind, AssertUnwindSafe, PanicHookInfo},
|
||||||
process::{self, Command, Termination},
|
process::{self, Command, Termination},
|
||||||
sync::mpsc::{channel, Sender},
|
sync::mpsc::{channel, Sender},
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
@ -123,7 +123,7 @@ pub fn test_main(args: &[String], tests: Vec<TestDescAndFn>, options: Option<Opt
|
|||||||
// from interleaving with the panic message or appearing after it.
|
// from interleaving with the panic message or appearing after it.
|
||||||
let builtin_panic_hook = panic::take_hook();
|
let builtin_panic_hook = panic::take_hook();
|
||||||
let hook = Box::new({
|
let hook = Box::new({
|
||||||
move |info: &'_ PanicInfo<'_>| {
|
move |info: &'_ PanicHookInfo<'_>| {
|
||||||
if !info.can_unwind() {
|
if !info.can_unwind() {
|
||||||
std::mem::forget(std::io::stderr().lock());
|
std::mem::forget(std::io::stderr().lock());
|
||||||
let mut stdout = ManuallyDrop::new(std::io::stdout().lock());
|
let mut stdout = ManuallyDrop::new(std::io::stdout().lock());
|
||||||
@ -726,7 +726,7 @@ fn spawn_test_subprocess(
|
|||||||
|
|
||||||
fn run_test_in_spawned_subprocess(desc: TestDesc, runnable_test: RunnableTest) -> ! {
|
fn run_test_in_spawned_subprocess(desc: TestDesc, runnable_test: RunnableTest) -> ! {
|
||||||
let builtin_panic_hook = panic::take_hook();
|
let builtin_panic_hook = panic::take_hook();
|
||||||
let record_result = Arc::new(move |panic_info: Option<&'_ PanicInfo<'_>>| {
|
let record_result = Arc::new(move |panic_info: Option<&'_ PanicHookInfo<'_>>| {
|
||||||
let test_result = match panic_info {
|
let test_result = match panic_info {
|
||||||
Some(info) => calc_result(&desc, Err(info.payload()), &None, &None),
|
Some(info) => calc_result(&desc, Err(info.payload()), &None, &None),
|
||||||
None => calc_result(&desc, Ok(()), &None, &None),
|
None => calc_result(&desc, Ok(()), &None, &None),
|
||||||
|
@ -1,39 +1,36 @@
|
|||||||
# based on armhf-gnu/Dockerfile
|
# based on armhf-gnu/Dockerfile
|
||||||
FROM ubuntu:20.04
|
FROM ubuntu:22.04
|
||||||
|
|
||||||
RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
RUN apt-get update -y && apt-get install -y --no-install-recommends \
|
RUN apt-get update -y && apt-get install -y --no-install-recommends \
|
||||||
bc \
|
bc \
|
||||||
bison \
|
bzip2 \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
cmake \
|
cmake \
|
||||||
cpio \
|
cpio \
|
||||||
curl \
|
curl \
|
||||||
debian-ports-archive-keyring \
|
file \
|
||||||
debootstrap \
|
flex \
|
||||||
flex \
|
bison \
|
||||||
gcc \
|
g++ \
|
||||||
gcc-riscv64-linux-gnu \
|
g++-riscv64-linux-gnu \
|
||||||
git \
|
git \
|
||||||
g++-riscv64-linux-gnu \
|
libc6-dev \
|
||||||
g++ \
|
libc6-dev-riscv64-cross \
|
||||||
libc6-dev \
|
libssl-dev \
|
||||||
libc6-dev-riscv64-cross \
|
make \
|
||||||
libssl-dev \
|
ninja-build \
|
||||||
make \
|
python3 \
|
||||||
ninja-build \
|
qemu-system-riscv64 \
|
||||||
patch \
|
xz-utils
|
||||||
python3 \
|
|
||||||
qemu-system-misc \
|
|
||||||
xz-utils
|
|
||||||
|
|
||||||
ENV ARCH=riscv
|
ENV ARCH=riscv \
|
||||||
ENV CROSS_COMPILE=riscv64-linux-gnu-
|
CROSS_COMPILE=riscv64-linux-gnu-
|
||||||
|
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
|
|
||||||
# From https://github.com/michaeljclark/busybear-linux/blob/master/conf/linux.config
|
# From https://github.com/michaeljclark/busybear-linux/blob/master/conf/linux.config
|
||||||
COPY host-x86_64/riscv64gc-linux/linux.config /build
|
COPY host-x86_64/riscv64gc-gnu/linux.config /build
|
||||||
|
|
||||||
# Compile the kernel that we're going to be emulating with. This is
|
# Compile the kernel that we're going to be emulating with. This is
|
||||||
# basically just done to be compatible with the QEMU target that we're going
|
# basically just done to be compatible with the QEMU target that we're going
|
||||||
@ -49,29 +46,22 @@ RUN curl https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.6.16.tar.xz | tar
|
|||||||
# Compile an instance of busybox as this provides a lightweight system and init
|
# Compile an instance of busybox as this provides a lightweight system and init
|
||||||
# binary which we will boot into. Only trick here is configuring busybox to
|
# binary which we will boot into. Only trick here is configuring busybox to
|
||||||
# build static binaries.
|
# build static binaries.
|
||||||
RUN curl https://busybox.net/downloads/busybox-1.31.1.tar.bz2 | tar xjf -
|
RUN curl https://www.busybox.net/downloads/busybox-1.32.1.tar.bz2 | tar xjf - && \
|
||||||
COPY host-x86_64/riscv64gc-linux/0001-Remove-stime-function-calls.patch /build/busybox-1.31.1/
|
cd busybox-1.32.1 && \
|
||||||
RUN cd /build/busybox-1.31.1 && \
|
make defconfig && \
|
||||||
patch -p1 -i 0001-Remove-stime-function-calls.patch && \
|
sed -i 's/.*CONFIG_STATIC.*/CONFIG_STATIC=y/' .config && \
|
||||||
make defconfig && \
|
make -j$(nproc) && \
|
||||||
sed -i 's/.*CONFIG_STATIC.*/CONFIG_STATIC=y/' .config && \
|
make install && \
|
||||||
make -j$(nproc) && \
|
mv _install /tmp/rootfs && \
|
||||||
make install && \
|
cd /build && \
|
||||||
mv _install /tmp/rootfs && \
|
rm -rf busybox-1.32.1
|
||||||
cd /build && \
|
|
||||||
rm -rf busybox-1.31.1
|
|
||||||
|
|
||||||
# Download the ubuntu rootfs, which we'll use as a chroot for all our tests
|
# Download the ubuntu rootfs, which we'll use as a chroot for all our tests.
|
||||||
# This is only needed to provide /lib/* and /usr/lib/*
|
|
||||||
WORKDIR /tmp
|
WORKDIR /tmp
|
||||||
RUN debootstrap --variant=minbase --arch=riscv64 --foreign focal /tmp/rootfs/ubuntu
|
RUN mkdir rootfs/ubuntu
|
||||||
RUN cd rootfs && mkdir proc sys dev etc etc/init.d
|
RUN curl https://cdimage.ubuntu.com/ubuntu-base/releases/22.04/release/ubuntu-base-22.04.2-base-riscv64.tar.gz | \
|
||||||
# rootfs/ubuntu/proc is in a weird state (access fails with ELOOP) until
|
tar xzf - -C rootfs/ubuntu && \
|
||||||
# rootfs/ubuntu/debootstrap/debootstrap --second-stage is run (under emulation),
|
cd rootfs && mkdir proc sys dev etc etc/init.d
|
||||||
# but this takes ages. Instead hack it into a good enough state.
|
|
||||||
# /proc is used by std::env::current_exe() (which is roughly
|
|
||||||
# `readlink /proc/self/exe`)
|
|
||||||
RUN cd rootfs/ubuntu && rm -rf proc && mkdir proc
|
|
||||||
|
|
||||||
# Copy over our init script, which starts up our test server and also a few other
|
# Copy over our init script, which starts up our test server and also a few other
|
||||||
# misc tasks
|
# misc tasks
|
||||||
@ -95,12 +85,12 @@ RUN mkdir build && cd build && \
|
|||||||
WORKDIR /tmp
|
WORKDIR /tmp
|
||||||
RUN rm -rf /tmp/riscv-pk
|
RUN rm -rf /tmp/riscv-pk
|
||||||
|
|
||||||
COPY scripts/cmake.sh /scripts/
|
|
||||||
RUN /scripts/cmake.sh
|
|
||||||
|
|
||||||
COPY scripts/sccache.sh /scripts/
|
COPY scripts/sccache.sh /scripts/
|
||||||
RUN sh /scripts/sccache.sh
|
RUN sh /scripts/sccache.sh
|
||||||
|
|
||||||
|
# Avoid "fatal: detected dubious ownership in repository at '/checkout'" error
|
||||||
|
RUN git config --global --add safe.directory /checkout
|
||||||
|
|
||||||
ENV RUST_CONFIGURE_ARGS --qemu-riscv64-rootfs=/tmp/rootfs
|
ENV RUST_CONFIGURE_ARGS --qemu-riscv64-rootfs=/tmp/rootfs
|
||||||
ENV SCRIPT python3 ../x.py --stage 2 test --host='' --target riscv64gc-unknown-linux-gnu
|
ENV SCRIPT python3 ../x.py --stage 2 test --host='' --target riscv64gc-unknown-linux-gnu
|
||||||
|
|
@ -1,96 +0,0 @@
|
|||||||
From c820da85c65c7f3aa9e9cb3ed71ada69bf9b783e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Alistair Francis <alistair.francis@wdc.com>
|
|
||||||
Date: Tue, 19 Nov 2019 13:06:40 +0100
|
|
||||||
Subject: [PATCH] Remove stime() function calls
|
|
||||||
|
|
||||||
stime() has been deprecated in glibc 2.31 and replaced with
|
|
||||||
clock_settime(). Let's replace the stime() function calls with
|
|
||||||
clock_settime() in preparation.
|
|
||||||
|
|
||||||
function old new delta
|
|
||||||
rdate_main 197 224 +27
|
|
||||||
clock_settime - 27 +27
|
|
||||||
date_main 926 941 +15
|
|
||||||
stime 37 - -37
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
(add/remove: 2/2 grow/shrink: 2/0 up/down: 69/-37) Total: 32 bytes
|
|
||||||
|
|
||||||
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
|
|
||||||
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
|
|
||||||
|
|
||||||
[Tom Eccles: adjust patch context to apply on top of 1.31.1-stable]
|
|
||||||
Signed-off-by: Tom Eccles <tom.eccles@codethink.co.uk>
|
|
||||||
---
|
|
||||||
coreutils/date.c | 6 +++++-
|
|
||||||
libbb/missing_syscalls.c | 8 --------
|
|
||||||
util-linux/rdate.c | 8 ++++++--
|
|
||||||
3 files changed, 11 insertions(+), 11 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/coreutils/date.c b/coreutils/date.c
|
|
||||||
index 3414d38ae..4ade6abb4 100644
|
|
||||||
--- a/coreutils/date.c
|
|
||||||
+++ b/coreutils/date.c
|
|
||||||
@@ -279,6 +279,9 @@ int date_main(int argc UNUSED_PARAM, char **argv)
|
|
||||||
time(&ts.tv_sec);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
+#if !ENABLE_FEATURE_DATE_NANO
|
|
||||||
+ ts.tv_nsec = 0;
|
|
||||||
+#endif
|
|
||||||
localtime_r(&ts.tv_sec, &tm_time);
|
|
||||||
|
|
||||||
/* If date string is given, update tm_time, and maybe set date */
|
|
||||||
@@ -301,9 +304,10 @@ int date_main(int argc UNUSED_PARAM, char **argv)
|
|
||||||
if (date_str[0] != '@')
|
|
||||||
tm_time.tm_isdst = -1;
|
|
||||||
ts.tv_sec = validate_tm_time(date_str, &tm_time);
|
|
||||||
+ ts.tv_nsec = 0;
|
|
||||||
|
|
||||||
/* if setting time, set it */
|
|
||||||
- if ((opt & OPT_SET) && stime(&ts.tv_sec) < 0) {
|
|
||||||
+ if ((opt & OPT_SET) && clock_settime(CLOCK_REALTIME, &ts) < 0) {
|
|
||||||
bb_perror_msg("can't set date");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
diff --git a/libbb/missing_syscalls.c b/libbb/missing_syscalls.c
|
|
||||||
index 87cf59b3d..dc40d9155 100644
|
|
||||||
--- a/libbb/missing_syscalls.c
|
|
||||||
+++ b/libbb/missing_syscalls.c
|
|
||||||
@@ -15,14 +15,6 @@ pid_t getsid(pid_t pid)
|
|
||||||
return syscall(__NR_getsid, pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
-int stime(const time_t *t)
|
|
||||||
-{
|
|
||||||
- struct timeval tv;
|
|
||||||
- tv.tv_sec = *t;
|
|
||||||
- tv.tv_usec = 0;
|
|
||||||
- return settimeofday(&tv, NULL);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
int sethostname(const char *name, size_t len)
|
|
||||||
{
|
|
||||||
return syscall(__NR_sethostname, name, len);
|
|
||||||
diff --git a/util-linux/rdate.c b/util-linux/rdate.c
|
|
||||||
index 70f829e7f..878375d78 100644
|
|
||||||
--- a/util-linux/rdate.c
|
|
||||||
+++ b/util-linux/rdate.c
|
|
||||||
@@ -95,9 +95,13 @@ int rdate_main(int argc UNUSED_PARAM, char **argv)
|
|
||||||
if (!(flags & 2)) { /* no -p (-s may be present) */
|
|
||||||
if (time(NULL) == remote_time)
|
|
||||||
bb_error_msg("current time matches remote time");
|
|
||||||
- else
|
|
||||||
- if (stime(&remote_time) < 0)
|
|
||||||
+ else {
|
|
||||||
+ struct timespec ts;
|
|
||||||
+ ts.tv_sec = remote_time;
|
|
||||||
+ ts.tv_nsec = 0;
|
|
||||||
+ if (clock_settime(CLOCK_REALTIME, &ts) < 0)
|
|
||||||
bb_perror_msg_and_die("can't set time of day");
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags != 1) /* not lone -s */
|
|
||||||
--
|
|
||||||
2.25.1
|
|
||||||
|
|
@ -175,7 +175,6 @@ run-make/pgo-gen/Makefile
|
|||||||
run-make/pgo-indirect-call-promotion/Makefile
|
run-make/pgo-indirect-call-promotion/Makefile
|
||||||
run-make/pgo-use/Makefile
|
run-make/pgo-use/Makefile
|
||||||
run-make/pointer-auth-link-with-c/Makefile
|
run-make/pointer-auth-link-with-c/Makefile
|
||||||
run-make/prefer-dylib/Makefile
|
|
||||||
run-make/prefer-rlib/Makefile
|
run-make/prefer-rlib/Makefile
|
||||||
run-make/pretty-print-to-file/Makefile
|
run-make/pretty-print-to-file/Makefile
|
||||||
run-make/pretty-print-with-dep-file/Makefile
|
run-make/pretty-print-with-dep-file/Makefile
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
# ignore-cross-compile
|
|
||||||
include ../tools.mk
|
|
||||||
|
|
||||||
all:
|
|
||||||
$(RUSTC) bar.rs --crate-type=dylib --crate-type=rlib -C prefer-dynamic
|
|
||||||
$(RUSTC) foo.rs -C prefer-dynamic
|
|
||||||
$(call RUN,foo)
|
|
||||||
rm $(TMPDIR)/*bar*
|
|
||||||
$(call FAIL,foo)
|
|
16
tests/run-make/prefer-dylib/rmake.rs
Normal file
16
tests/run-make/prefer-dylib/rmake.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
//@ ignore-cross-compile
|
||||||
|
|
||||||
|
use run_make_support::{cwd, dynamic_lib_name, read_dir, run, run_fail, rustc};
|
||||||
|
use std::fs::remove_file;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
rustc().input("bar.rs").crate_type("dylib").crate_type("rlib").arg("-Cprefer-dynamic").run();
|
||||||
|
rustc().input("foo.rs").arg("-Cprefer-dynamic").run();
|
||||||
|
|
||||||
|
run("foo");
|
||||||
|
|
||||||
|
remove_file(dynamic_lib_name("bar")).unwrap();
|
||||||
|
// This time the command should fail.
|
||||||
|
run_fail("foo");
|
||||||
|
}
|
25
tests/ui/async-await/pin-needed-to-poll-3.rs
Normal file
25
tests/ui/async-await/pin-needed-to-poll-3.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
use std::{
|
||||||
|
future::Future,
|
||||||
|
pin::Pin,
|
||||||
|
task::{Context, Poll},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct FutureWrapper<F> {
|
||||||
|
fut: F,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F> Future for FutureWrapper<F>
|
||||||
|
where
|
||||||
|
F: Future,
|
||||||
|
{
|
||||||
|
type Output = F::Output;
|
||||||
|
|
||||||
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
let res = self.fut.poll(cx);
|
||||||
|
//~^ ERROR no method named `poll` found for type parameter `F` in the current scope
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
18
tests/ui/async-await/pin-needed-to-poll-3.stderr
Normal file
18
tests/ui/async-await/pin-needed-to-poll-3.stderr
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
error[E0599]: no method named `poll` found for type parameter `F` in the current scope
|
||||||
|
--> $DIR/pin-needed-to-poll-3.rs:19:28
|
||||||
|
|
|
||||||
|
LL | impl<F> Future for FutureWrapper<F>
|
||||||
|
| - method `poll` not found for this type parameter
|
||||||
|
...
|
||||||
|
LL | let res = self.fut.poll(cx);
|
||||||
|
| ^^^^ method not found in `F`
|
||||||
|
|
|
||||||
|
help: consider pinning the expression
|
||||||
|
|
|
||||||
|
LL ~ let mut pinned = std::pin::pin!(self.fut);
|
||||||
|
LL ~ let res = pinned.as_mut().poll(cx);
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0599`.
|
@ -5,7 +5,9 @@
|
|||||||
|
|
||||||
#![feature(lang_items)]
|
#![feature(lang_items)]
|
||||||
|
|
||||||
use std::panic::PanicInfo;
|
extern crate core;
|
||||||
|
|
||||||
|
use core::panic::PanicInfo;
|
||||||
|
|
||||||
#[lang = "panic_impl"]
|
#[lang = "panic_impl"]
|
||||||
fn panic_impl(info: &PanicInfo) -> ! {
|
fn panic_impl(info: &PanicInfo) -> ! {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error[E0152]: found duplicate lang item `panic_impl`
|
error[E0152]: found duplicate lang item `panic_impl`
|
||||||
--> $DIR/duplicate_entry_error.rs:11:1
|
--> $DIR/duplicate_entry_error.rs:13:1
|
||||||
|
|
|
|
||||||
LL | / fn panic_impl(info: &PanicInfo) -> ! {
|
LL | / fn panic_impl(info: &PanicInfo) -> ! {
|
||||||
LL | |
|
LL | |
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
//@ normalize-stderr-test "loaded from .*libstd-.*.rlib" -> "loaded from SYSROOT/libstd-*.rlib"
|
//@ normalize-stderr-test "loaded from .*libstd-.*.rlib" -> "loaded from SYSROOT/libstd-*.rlib"
|
||||||
//@ error-pattern: found duplicate lang item `panic_impl`
|
//@ error-pattern: found duplicate lang item `panic_impl`
|
||||||
|
|
||||||
|
extern crate core;
|
||||||
|
|
||||||
use std::panic::PanicInfo;
|
use core::panic::PanicInfo;
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(info: PanicInfo) -> ! {
|
fn panic(info: PanicInfo) -> ! {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error[E0152]: found duplicate lang item `panic_impl`
|
error[E0152]: found duplicate lang item `panic_impl`
|
||||||
--> $DIR/panic-handler-std.rs:8:1
|
--> $DIR/panic-handler-std.rs:9:1
|
||||||
|
|
|
|
||||||
LL | / fn panic(info: PanicInfo) -> ! {
|
LL | / fn panic(info: PanicInfo) -> ! {
|
||||||
LL | | loop {}
|
LL | | loop {}
|
||||||
|
Loading…
Reference in New Issue
Block a user