Skip to content

Commit

Permalink
Auto merge of rust-lang#126277 - jieyouxu:rollup-qn4o157, r=jieyouxu
Browse files Browse the repository at this point in the history
Rollup of 7 pull requests

Successful merges:

 - rust-lang#115974 (Split core's PanicInfo and std's PanicInfo)
 - rust-lang#125659 (Remove usage of `isize` in example)
 - rust-lang#125669 (CI: Update riscv64gc-linux job to Ubuntu 22.04, rename to riscv64gc-gnu)
 - rust-lang#125684 (Account for existing bindings when suggesting `pin!()`)
 - rust-lang#126055 (Expand list of trait implementers in E0277 when calling rustc with --verbose)
 - rust-lang#126174 (Migrate `tests/run-make/prefer-dylib` to `rmake.rs`)
 - rust-lang#126256 (Add {{target}} substitution to compiletest)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jun 11, 2024
2 parents 3ea5e23 + bc5bd47 commit ec64817
Show file tree
Hide file tree
Showing 26 changed files with 529 additions and 353 deletions.
9 changes: 4 additions & 5 deletions compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ use std::ffi::OsString;
use std::fmt::Write as _;
use std::fs::{self, File};
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::process::{self, Command, Stdio};
use std::str;
Expand Down Expand Up @@ -1366,11 +1366,10 @@ pub fn install_ice_hook(
let using_internal_features = Arc::new(std::sync::atomic::AtomicBool::default());
let using_internal_features_hook = using_internal_features.clone();
panic::update_hook(Box::new(
move |default_hook: &(dyn Fn(&PanicInfo<'_>) + Send + Sync + 'static),
info: &PanicInfo<'_>| {
move |default_hook: &(dyn Fn(&PanicHookInfo<'_>) + Send + Sync + 'static),
info: &PanicHookInfo<'_>| {
// Lock stderr to prevent interleaving of concurrent panics.
let _guard = io::stderr().lock();

// If the error was caused by a broken pipe then this is not a bug.
// Write the error and return immediately. See #98700.
#[cfg(windows)]
Expand Down Expand Up @@ -1431,7 +1430,7 @@ pub fn install_ice_hook(
/// When `install_ice_hook` is called, this function will be called as the panic
/// hook.
fn report_ice(
info: &panic::PanicInfo<'_>,
info: &panic::PanicHookInfo<'_>,
bug_report_url: &str,
extra_info: fn(&DiagCtxt),
using_internal_features: &AtomicBool,
Expand Down
68 changes: 60 additions & 8 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3360,14 +3360,66 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.source_map()
.indentation_before(rcvr.span)
.unwrap_or_else(|| " ".to_string());
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,
);
let mut expr = rcvr;
while let Node::Expr(call_expr) = self.tcx.parent_hir_node(expr.hir_id)
&& let hir::ExprKind::MethodCall(hir::PathSegment { .. }, ..) =
call_expr.kind
{
expr = call_expr;
}
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.
alt_rcvr_sugg = true;
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ declare_lint! {
/// ```rust,compile_fail
/// #![deny(box_pointers)]
/// struct Foo {
/// x: Box<isize>,
/// x: Box<i32>,
/// }
/// ```
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2069,12 +2069,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
})
.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!(
"the following {other}types implement trait `{}`:{}{}",
trait_ref.print_trait_sugared(),
candidates[..end].join(""),
if candidates.len() > 9 {
if candidates.len() > 9 && !self.tcx.sess.opts.verbose {
format!("\nand {} others", candidates.len() - 8)
} else {
String::new()
Expand Down
5 changes: 3 additions & 2 deletions library/core/src/error.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ The following are the primary interfaces of the panic system and the
responsibilities they cover:

* [`panic!`] and [`panic_any`] (Constructing, Propagated automatically)
* [`PanicInfo`] (Reporting)
* [`set_hook`], [`take_hook`], and [`#[panic_handler]`][panic-handler] (Reporting)
* [`set_hook`], [`take_hook`], and [`PanicHookInfo`] (Reporting)
* [`#[panic_handler]`][panic-handler] and [`PanicInfo`] (Reporting in no_std)
* [`catch_unwind`] and [`resume_unwind`] (Discarding, Propagating)

The following are the primary interfaces of the error system and the
Expand Down Expand Up @@ -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".

[`panic_any`]: ../../std/panic/fn.panic_any.html
[`PanicHookInfo`]: ../../std/panic/struct.PanicHookInfo.html
[`PanicInfo`]: crate::panic::PanicInfo
[`catch_unwind`]: ../../std/panic/fn.catch_unwind.html
[`resume_unwind`]: ../../std/panic/fn.resume_unwind.html
Expand Down
7 changes: 6 additions & 1 deletion library/core/src/panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ pub macro unreachable_2021 {
/// use.
#[unstable(feature = "std_internals", issue = "none")]
#[doc(hidden)]
pub unsafe trait PanicPayload {
pub unsafe trait PanicPayload: crate::fmt::Display {
/// Take full ownership of the contents.
/// The return type is actually `Box<dyn Any + Send>`, but we cannot use `Box` in core.
///
Expand All @@ -157,4 +157,9 @@ pub unsafe trait PanicPayload {

/// Just borrow the contents.
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
}
}
3 changes: 2 additions & 1 deletion library/core/src/panic/location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ use crate::fmt;

/// 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
/// [`PanicHookInfo::location()`]: ../../std/panic/struct.PanicHookInfo.html#method.location
///
/// # Examples
///
Expand Down
106 changes: 28 additions & 78 deletions library/core/src/panic/panic_info.rs
Original file line number Diff line number Diff line change
@@ -1,98 +1,40 @@
use crate::any::Any;
use crate::fmt;
use crate::panic::Location;

/// A struct providing information about a panic.
///
/// `PanicInfo` structure is passed to a panic hook set by the [`set_hook`]
/// function.
/// A `PanicInfo` structure is passed to the panic handler defined by `#[panic_handler]`.
///
/// [`set_hook`]: ../../std/panic/fn.set_hook.html
/// For the type used by the panic hook mechanism in `std`, see [`std::panic::PanicHookInfo`].
///
/// # Examples
///
/// ```should_panic
/// use std::panic;
///
/// panic::set_hook(Box::new(|panic_info| {
/// println!("panic occurred: {panic_info}");
/// }));
///
/// panic!("critical system failure");
/// ```
/// [`std::panic::PanicHookInfo`]: ../../std/panic/struct.PanicHookInfo.html
#[lang = "panic_info"]
#[stable(feature = "panic_hooks", since = "1.10.0")]
#[derive(Debug)]
pub struct PanicInfo<'a> {
payload: &'a (dyn Any + Send),
message: Option<&'a fmt::Arguments<'a>>,
message: fmt::Arguments<'a>,
location: &'a Location<'a>,
can_unwind: bool,
force_no_backtrace: bool,
}

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]
pub fn internal_constructor(
message: Option<&'a fmt::Arguments<'a>>,
pub(crate) fn new(
message: fmt::Arguments<'a>,
location: &'a Location<'a>,
can_unwind: bool,
force_no_backtrace: bool,
) -> Self {
struct NoPayload;
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
PanicInfo { location, message, can_unwind, force_no_backtrace }
}

/// If the `panic!` macro from the `core` crate (not from `std`)
/// was used with a formatting string and some additional arguments,
/// returns that message ready to be used for example with [`fmt::write`]
#[must_use]
#[unstable(feature = "panic_info_message", issue = "66745")]
pub fn message(&self) -> Option<&fmt::Arguments<'_>> {
pub fn message(&self) -> fmt::Arguments<'_> {
self.message
}

Expand Down Expand Up @@ -128,6 +70,24 @@ impl<'a> PanicInfo<'a> {
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
/// the point where the panic occurred.
///
Expand Down Expand Up @@ -161,18 +121,8 @@ impl fmt::Display for PanicInfo<'_> {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("panicked at ")?;
self.location.fmt(formatter)?;
formatter.write_str(":")?;
if let Some(message) = 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.
formatter.write_str(":\n")?;
formatter.write_fmt(self.message)?;
Ok(())
}
}
24 changes: 13 additions & 11 deletions library/core/src/panicking.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
//! Panic support for core
//!
//! The core library cannot define panicking, but it does *declare* panicking. This
//! means that the functions inside of core are allowed to panic, but to be
//! In core, panicking is always done with a message, resulting in a `core::panic::PanicInfo`
//! 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
//! interface for panicking is:
//!
Expand All @@ -10,11 +17,6 @@
//! # { 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
//! necessary lang items for the compiler. All panics are funneled through this
//! one function. The actual symbol is declared through the `#[panic_handler]` attribute.
Expand Down Expand Up @@ -61,8 +63,8 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
fn panic_impl(pi: &PanicInfo<'_>) -> !;
}

let pi = PanicInfo::internal_constructor(
Some(&fmt),
let pi = PanicInfo::new(
fmt,
Location::caller(),
/* can_unwind */ true,
/* force_no_backtrace */ false,
Expand Down Expand Up @@ -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.
let pi = PanicInfo::internal_constructor(
Some(&fmt),
let pi = PanicInfo::new(
fmt,
Location::caller(),
/* can_unwind */ false,
force_no_backtrace,
Expand Down
Loading

0 comments on commit ec64817

Please sign in to comment.