From eb0ed28cedc2f5d96695d0ccd75ff831ec221a13 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Tue, 28 May 2024 15:31:26 +0200 Subject: [PATCH 01/35] Remove usage of `isize` in example `isize` is a rare integer type, replace it with a more common one. --- compiler/rustc_lint/src/builtin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index ba42eae344158..6fd416ef517f2 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -142,7 +142,7 @@ declare_lint! { /// ```rust,compile_fail /// #![deny(box_pointers)] /// struct Foo { - /// x: Box, + /// x: Box, /// } /// ``` /// From 1a840e7732536bbf5c4d2f434d4af138983f4b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 28 May 2024 20:05:01 +0000 Subject: [PATCH 02/35] Add test for incorrect pinning suggestion The following suggestion is incorrect, as it doesn't account for the binding: ``` 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 Future for FutureWrapper | - 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 res = let mut pinned = std::pin::pin!(self.fut); LL ~ pinned.as_mut().poll(cx); | ``` --- tests/ui/async-await/pin-needed-to-poll-3.rs | 25 +++++++++++++++++++ .../async-await/pin-needed-to-poll-3.stderr | 18 +++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 tests/ui/async-await/pin-needed-to-poll-3.rs create mode 100644 tests/ui/async-await/pin-needed-to-poll-3.stderr diff --git a/tests/ui/async-await/pin-needed-to-poll-3.rs b/tests/ui/async-await/pin-needed-to-poll-3.rs new file mode 100644 index 0000000000000..11ba7d29abaf9 --- /dev/null +++ b/tests/ui/async-await/pin-needed-to-poll-3.rs @@ -0,0 +1,25 @@ +use std::{ + future::Future, + pin::Pin, + task::{Context, Poll}, +}; + + +struct FutureWrapper { + fut: F, +} + +impl Future for FutureWrapper +where + F: Future, +{ + type Output = F::Output; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let res = self.fut.poll(cx); + //~^ ERROR no method named `poll` found for type parameter `F` in the current scope + res + } +} + +fn main() {} diff --git a/tests/ui/async-await/pin-needed-to-poll-3.stderr b/tests/ui/async-await/pin-needed-to-poll-3.stderr new file mode 100644 index 0000000000000..83a0808c4ecf8 --- /dev/null +++ b/tests/ui/async-await/pin-needed-to-poll-3.stderr @@ -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 Future for FutureWrapper + | - 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 res = let mut pinned = std::pin::pin!(self.fut); +LL ~ pinned.as_mut().poll(cx); + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. From 5585f3133c05a33e59cd352a32fdf171447a9b2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 28 May 2024 20:48:35 +0000 Subject: [PATCH 03/35] Account for existing bindings when suggesting pinning When we encounter a situation where we'd suggest `pin!()`, we now account for that expression exising as part of an assignment and provide an appropriate suggestion: ``` 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 Future for FutureWrapper | - 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); | ``` Fix #125661. --- .../rustc_hir_typeck/src/method/suggest.rs | 68 ++++++++++++++++--- .../async-await/pin-needed-to-poll-3.stderr | 4 +- 2 files changed, 62 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 54af8354c4c72..75bb755183e27 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -3326,14 +3326,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; } diff --git a/tests/ui/async-await/pin-needed-to-poll-3.stderr b/tests/ui/async-await/pin-needed-to-poll-3.stderr index 83a0808c4ecf8..e4fbef69bacbf 100644 --- a/tests/ui/async-await/pin-needed-to-poll-3.stderr +++ b/tests/ui/async-await/pin-needed-to-poll-3.stderr @@ -9,8 +9,8 @@ LL | let res = self.fut.poll(cx); | help: consider pinning the expression | -LL ~ let res = let mut pinned = std::pin::pin!(self.fut); -LL ~ pinned.as_mut().poll(cx); +LL ~ let mut pinned = std::pin::pin!(self.fut); +LL ~ let res = pinned.as_mut().poll(cx); | error: aborting due to 1 previous error From 69769fc79776a284fed2e5d9ea9605b36f50f83a Mon Sep 17 00:00:00 2001 From: "rongfu.leng" Date: Thu, 6 Jun 2024 09:38:09 +0800 Subject: [PATCH 04/35] Expand list of trait implementers in E0277 when calling rustc with --verbose Signed-off-by: rongfu.leng --- .../src/traits/error_reporting/type_err_ctxt_ext.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 9a0929baeaf2e..1bdbd0f3ed78e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -2082,12 +2082,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() From 3ba0262c2d254c5510b97e01de198bdc05b27eab Mon Sep 17 00:00:00 2001 From: Ana Hobden Date: Mon, 27 May 2024 13:12:26 -0700 Subject: [PATCH 05/35] CI: Update riscv64gc-linux job to 22.04, rename to riscv64gc-gnu --- .../Dockerfile | 91 ++++++++---------- .../linux.config | 0 .../0001-Remove-stime-function-calls.patch | 96 ------------------- 3 files changed, 39 insertions(+), 148 deletions(-) rename src/ci/docker/host-x86_64/disabled/{riscv64gc-linux => riscv64gc-gnu}/Dockerfile (54%) rename src/ci/docker/host-x86_64/disabled/{riscv64gc-linux => riscv64gc-gnu}/linux.config (100%) delete mode 100644 src/ci/docker/host-x86_64/disabled/riscv64gc-linux/0001-Remove-stime-function-calls.patch diff --git a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile b/src/ci/docker/host-x86_64/disabled/riscv64gc-gnu/Dockerfile similarity index 54% rename from src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile rename to src/ci/docker/host-x86_64/disabled/riscv64gc-gnu/Dockerfile index 07260be35877a..bc7f8c3067312 100644 --- a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/disabled/riscv64gc-gnu/Dockerfile @@ -1,39 +1,36 @@ # 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 \ - bc \ - bison \ - ca-certificates \ - cmake \ - cpio \ - curl \ - debian-ports-archive-keyring \ - debootstrap \ - flex \ - gcc \ - gcc-riscv64-linux-gnu \ - git \ - g++-riscv64-linux-gnu \ - g++ \ - libc6-dev \ - libc6-dev-riscv64-cross \ - libssl-dev \ - make \ - ninja-build \ - patch \ - python3 \ - qemu-system-misc \ - xz-utils + bc \ + bzip2 \ + ca-certificates \ + cmake \ + cpio \ + curl \ + file \ + flex \ + bison \ + g++ \ + g++-riscv64-linux-gnu \ + git \ + libc6-dev \ + libc6-dev-riscv64-cross \ + libssl-dev \ + make \ + ninja-build \ + python3 \ + qemu-system-riscv64 \ + xz-utils -ENV ARCH=riscv -ENV CROSS_COMPILE=riscv64-linux-gnu- +ENV ARCH=riscv \ + CROSS_COMPILE=riscv64-linux-gnu- WORKDIR /build # 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 # 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 # binary which we will boot into. Only trick here is configuring busybox to # build static binaries. -RUN curl https://busybox.net/downloads/busybox-1.31.1.tar.bz2 | tar xjf - -COPY host-x86_64/riscv64gc-linux/0001-Remove-stime-function-calls.patch /build/busybox-1.31.1/ -RUN cd /build/busybox-1.31.1 && \ - patch -p1 -i 0001-Remove-stime-function-calls.patch && \ - make defconfig && \ - sed -i 's/.*CONFIG_STATIC.*/CONFIG_STATIC=y/' .config && \ - make -j$(nproc) && \ - make install && \ - mv _install /tmp/rootfs && \ - cd /build && \ - rm -rf busybox-1.31.1 +RUN curl https://www.busybox.net/downloads/busybox-1.32.1.tar.bz2 | tar xjf - && \ + cd busybox-1.32.1 && \ + make defconfig && \ + sed -i 's/.*CONFIG_STATIC.*/CONFIG_STATIC=y/' .config && \ + make -j$(nproc) && \ + make install && \ + mv _install /tmp/rootfs && \ + cd /build && \ + rm -rf busybox-1.32.1 -# 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/* +# Download the ubuntu rootfs, which we'll use as a chroot for all our tests. WORKDIR /tmp -RUN debootstrap --variant=minbase --arch=riscv64 --foreign focal /tmp/rootfs/ubuntu -RUN cd rootfs && mkdir proc sys dev etc etc/init.d -# rootfs/ubuntu/proc is in a weird state (access fails with ELOOP) until -# rootfs/ubuntu/debootstrap/debootstrap --second-stage is run (under emulation), -# 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 +RUN mkdir rootfs/ubuntu +RUN curl https://cdimage.ubuntu.com/ubuntu-base/releases/22.04/release/ubuntu-base-22.04.2-base-riscv64.tar.gz | \ + tar xzf - -C rootfs/ubuntu && \ + cd rootfs && mkdir proc sys dev etc etc/init.d # Copy over our init script, which starts up our test server and also a few other # misc tasks @@ -95,9 +85,6 @@ RUN mkdir build && cd build && \ WORKDIR /tmp RUN rm -rf /tmp/riscv-pk -COPY scripts/cmake.sh /scripts/ -RUN /scripts/cmake.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/linux.config b/src/ci/docker/host-x86_64/disabled/riscv64gc-gnu/linux.config similarity index 100% rename from src/ci/docker/host-x86_64/disabled/riscv64gc-linux/linux.config rename to src/ci/docker/host-x86_64/disabled/riscv64gc-gnu/linux.config diff --git a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/0001-Remove-stime-function-calls.patch b/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/0001-Remove-stime-function-calls.patch deleted file mode 100644 index 4437a870b207e..0000000000000 --- a/src/ci/docker/host-x86_64/disabled/riscv64gc-linux/0001-Remove-stime-function-calls.patch +++ /dev/null @@ -1,96 +0,0 @@ -From c820da85c65c7f3aa9e9cb3ed71ada69bf9b783e Mon Sep 17 00:00:00 2001 -From: Alistair Francis -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 -Signed-off-by: Denys Vlasenko - -[Tom Eccles: adjust patch context to apply on top of 1.31.1-stable] -Signed-off-by: Tom Eccles ---- - 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 - From aafa93feeeff5a2c24cf375923b5ce116bf96425 Mon Sep 17 00:00:00 2001 From: Ana Hobden Date: Wed, 29 May 2024 07:34:21 -0700 Subject: [PATCH 06/35] Move riscv64-gnu test out of disabled --- .../docker/host-x86_64/{disabled => }/riscv64gc-gnu/Dockerfile | 0 .../host-x86_64/{disabled => }/riscv64gc-gnu/linux.config | 0 src/ci/github-actions/jobs.yml | 3 +++ 3 files changed, 3 insertions(+) rename src/ci/docker/host-x86_64/{disabled => }/riscv64gc-gnu/Dockerfile (100%) rename src/ci/docker/host-x86_64/{disabled => }/riscv64gc-gnu/linux.config (100%) diff --git a/src/ci/docker/host-x86_64/disabled/riscv64gc-gnu/Dockerfile b/src/ci/docker/host-x86_64/riscv64gc-gnu/Dockerfile similarity index 100% rename from src/ci/docker/host-x86_64/disabled/riscv64gc-gnu/Dockerfile rename to src/ci/docker/host-x86_64/riscv64gc-gnu/Dockerfile diff --git a/src/ci/docker/host-x86_64/disabled/riscv64gc-gnu/linux.config b/src/ci/docker/host-x86_64/riscv64gc-gnu/linux.config similarity index 100% rename from src/ci/docker/host-x86_64/disabled/riscv64gc-gnu/linux.config rename to src/ci/docker/host-x86_64/riscv64gc-gnu/linux.config diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 48c39d2c33e56..8c1ca64f0c415 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -118,6 +118,9 @@ auto: - image: armhf-gnu <<: *job-linux-4c + - image: riscv64gc-gnu + <<: *job-linux-4c + - image: dist-aarch64-linux env: CODEGEN_BACKENDS: llvm,cranelift From f2e7d79e0c7f3f20032b4c8755e949787abe695f Mon Sep 17 00:00:00 2001 From: Ana Hobden Date: Wed, 29 May 2024 07:35:22 -0700 Subject: [PATCH 07/35] Add riscv64-gnu to PR tests --- src/ci/github-actions/jobs.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 8c1ca64f0c415..72d0ace0a1344 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -91,6 +91,9 @@ pr: <<: *job-linux-16c - image: x86_64-gnu-tools <<: *job-linux-16c + # TODO: This is temporary and for testing https://github.com/rust-lang/rust/pull/125669 + - image: riscv64gc-gnu + <<: *job-linux-4c # Jobs that run when you perform a try build (@bors try) # These jobs automatically inherit envs.try, to avoid repeating From 4c4eb39bc50230f5d50f451f323cfef2e70962d6 Mon Sep 17 00:00:00 2001 From: Ana Hobden Date: Fri, 31 May 2024 07:46:24 -0700 Subject: [PATCH 08/35] Add workaround for git dubious ownership issue --- src/ci/docker/host-x86_64/riscv64gc-gnu/Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ci/docker/host-x86_64/riscv64gc-gnu/Dockerfile b/src/ci/docker/host-x86_64/riscv64gc-gnu/Dockerfile index bc7f8c3067312..a9ffa5918b5bc 100644 --- a/src/ci/docker/host-x86_64/riscv64gc-gnu/Dockerfile +++ b/src/ci/docker/host-x86_64/riscv64gc-gnu/Dockerfile @@ -88,6 +88,9 @@ RUN rm -rf /tmp/riscv-pk COPY scripts/sccache.sh /scripts/ 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 SCRIPT python3 ../x.py --stage 2 test --host='' --target riscv64gc-unknown-linux-gnu From e1b489db8803a233d2d6633cc6aae513e0867224 Mon Sep 17 00:00:00 2001 From: Ana Hobden Date: Mon, 10 Jun 2024 13:25:56 -0700 Subject: [PATCH 09/35] Re-disable riscv64-gnu test --- .../host-x86_64/{ => disabled}/riscv64gc-gnu/Dockerfile | 0 .../host-x86_64/{ => disabled}/riscv64gc-gnu/linux.config | 0 src/ci/github-actions/jobs.yml | 6 ------ 3 files changed, 6 deletions(-) rename src/ci/docker/host-x86_64/{ => disabled}/riscv64gc-gnu/Dockerfile (100%) rename src/ci/docker/host-x86_64/{ => disabled}/riscv64gc-gnu/linux.config (100%) diff --git a/src/ci/docker/host-x86_64/riscv64gc-gnu/Dockerfile b/src/ci/docker/host-x86_64/disabled/riscv64gc-gnu/Dockerfile similarity index 100% rename from src/ci/docker/host-x86_64/riscv64gc-gnu/Dockerfile rename to src/ci/docker/host-x86_64/disabled/riscv64gc-gnu/Dockerfile diff --git a/src/ci/docker/host-x86_64/riscv64gc-gnu/linux.config b/src/ci/docker/host-x86_64/disabled/riscv64gc-gnu/linux.config similarity index 100% rename from src/ci/docker/host-x86_64/riscv64gc-gnu/linux.config rename to src/ci/docker/host-x86_64/disabled/riscv64gc-gnu/linux.config diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 72d0ace0a1344..48c39d2c33e56 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -91,9 +91,6 @@ pr: <<: *job-linux-16c - image: x86_64-gnu-tools <<: *job-linux-16c - # TODO: This is temporary and for testing https://github.com/rust-lang/rust/pull/125669 - - image: riscv64gc-gnu - <<: *job-linux-4c # Jobs that run when you perform a try build (@bors try) # These jobs automatically inherit envs.try, to avoid repeating @@ -121,9 +118,6 @@ auto: - image: armhf-gnu <<: *job-linux-4c - - image: riscv64gc-gnu - <<: *job-linux-4c - - image: dist-aarch64-linux env: CODEGEN_BACKENDS: llvm,cranelift From 1462f3d4eb6d5ce18c9c430c10315bc5543090bc Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 11 Jun 2024 08:42:20 +0200 Subject: [PATCH 10/35] Add {{target}} substitution to compiletest --- src/tools/compiletest/src/header.rs | 5 +++++ src/tools/tidy/src/target_specific_tests.rs | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index fd4ab72bbf463..fc6c721722211 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -1281,6 +1281,7 @@ fn expand_variables(mut value: String, config: &Config) -> String { const BUILD_BASE: &str = "{{build-base}}"; const SYSROOT_BASE: &str = "{{sysroot-base}}"; const TARGET_LINKER: &str = "{{target-linker}}"; + const TARGET: &str = "{{target}}"; if value.contains(CWD) { let cwd = env::current_dir().unwrap(); @@ -1303,6 +1304,10 @@ fn expand_variables(mut value: String, config: &Config) -> String { value = value.replace(TARGET_LINKER, config.target_linker.as_deref().unwrap_or("")); } + if value.contains(TARGET) { + value = value.replace(TARGET, &config.target); + } + value } diff --git a/src/tools/tidy/src/target_specific_tests.rs b/src/tools/tidy/src/target_specific_tests.rs index f3a64b38e8c66..8be27d1e117ce 100644 --- a/src/tools/tidy/src/target_specific_tests.rs +++ b/src/tools/tidy/src/target_specific_tests.rs @@ -53,9 +53,9 @@ pub fn check(path: &Path, bad: &mut bool) { } else if directive.starts_with(COMPILE_FLAGS_HEADER) { let compile_flags = &directive[COMPILE_FLAGS_HEADER.len()..]; if let Some((_, v)) = compile_flags.split_once("--target") { - if let Some((arch, _)) = - v.trim_start_matches(|c| c == ' ' || c == '=').split_once("-") - { + let v = v.trim_start_matches(|c| c == ' ' || c == '='); + let v = if v == "{{target}}" { Some((v, v)) } else { v.split_once("-") }; + if let Some((arch, _)) = v { let info = header_map.entry(revision).or_insert(RevisionInfo::default()); info.target_arch.replace(arch); } else { From 19a2dfea881568fb63e55e8535634ad33c783f02 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 8 Jun 2024 23:17:11 +0200 Subject: [PATCH 11/35] Migrate `tests/run-make/prefer-dylib` to `rmake.rs` --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/prefer-dylib/Makefile | 9 --------- tests/run-make/prefer-dylib/rmake.rs | 16 ++++++++++++++++ 3 files changed, 16 insertions(+), 10 deletions(-) delete mode 100644 tests/run-make/prefer-dylib/Makefile create mode 100644 tests/run-make/prefer-dylib/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index a015f96ae51d8..fb65c96c4aab6 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -177,7 +177,6 @@ run-make/pgo-gen/Makefile run-make/pgo-indirect-call-promotion/Makefile run-make/pgo-use/Makefile run-make/pointer-auth-link-with-c/Makefile -run-make/prefer-dylib/Makefile run-make/prefer-rlib/Makefile run-make/pretty-print-to-file/Makefile run-make/pretty-print-with-dep-file/Makefile diff --git a/tests/run-make/prefer-dylib/Makefile b/tests/run-make/prefer-dylib/Makefile deleted file mode 100644 index cc26e70ae67ca..0000000000000 --- a/tests/run-make/prefer-dylib/Makefile +++ /dev/null @@ -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) diff --git a/tests/run-make/prefer-dylib/rmake.rs b/tests/run-make/prefer-dylib/rmake.rs new file mode 100644 index 0000000000000..ad9fd8a15a2c0 --- /dev/null +++ b/tests/run-make/prefer-dylib/rmake.rs @@ -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"); +} From e3e815370e824a9d7e74024da54acbe5ac477786 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 19 Sep 2023 18:06:22 +0200 Subject: [PATCH 12/35] Split core's PanicInfo and std's PanicInfo. --- library/core/src/panic/panic_info.rs | 80 ++------------ library/core/src/panicking.rs | 4 +- library/std/src/panic.rs | 153 ++++++++++++++++++++++++++- library/std/src/panicking.rs | 37 +++---- 4 files changed, 177 insertions(+), 97 deletions(-) diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index 403262212580c..2b7bc76fbc278 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -1,31 +1,14 @@ -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. -/// -/// [`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}"); -/// })); -/// -/// panic!("critical system failure"); -/// ``` +/// A `PanicInfo` structure is passed to the panic handler defined by `#[panic_handler]`. #[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, @@ -40,51 +23,12 @@ impl<'a> PanicInfo<'a> { #[doc(hidden)] #[inline] pub fn internal_constructor( - message: Option<&'a fmt::Arguments<'a>>, + 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`) @@ -92,7 +36,7 @@ impl<'a> PanicInfo<'a> { /// 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 } @@ -161,18 +105,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::() 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(()) } } diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index ca06e059b75ac..683894a5ab49f 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -62,7 +62,7 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { } let pi = PanicInfo::internal_constructor( - Some(&fmt), + fmt, Location::caller(), /* can_unwind */ true, /* force_no_backtrace */ false, @@ -100,7 +100,7 @@ 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), + &fmt, Location::caller(), /* can_unwind */ false, force_no_backtrace, diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index e63b46ab70548..18072f6fe3df9 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -4,11 +4,162 @@ use crate::any::Any; use crate::collections; +use crate::fmt; use crate::panicking; use crate::sync::atomic::{AtomicU8, Ordering}; use crate::sync::{Condvar, Mutex, RwLock}; use crate::thread::Result; +/// 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}"); +/// })); +/// +/// panic!("critical system failure"); +/// ``` +#[stable(feature = "panic_hooks", since = "1.10.0")] +#[derive(Debug)] +pub struct PanicInfo<'a> { + payload: &'a (dyn Any + Send), + location: &'a Location<'a>, + can_unwind: bool, + force_no_backtrace: bool, +} + +impl<'a> PanicInfo<'a> { + #[unstable(feature = "panic_internals", issue = "none")] + #[doc(hidden)] + #[inline] + pub fn internal_constructor( + location: &'a Location<'a>, + can_unwind: bool, + force_no_backtrace: bool, + ) -> Self { + struct NoPayload; + PanicInfo { payload: &NoPayload, location, can_unwind, force_no_backtrace } + } + + #[unstable(feature = "panic_internals", 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 + } + + /// 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] + #[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] + #[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 PanicInfo<'_> { + 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::() { + formatter.write_str(":\n")?; + formatter.write_str(payload)?; + } + Ok(()) + } +} + #[doc(hidden)] #[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")] #[allow_internal_unstable(libstd_sys_internals, const_format_args, panic_internals, rt)] @@ -43,7 +194,7 @@ pub use crate::panicking::{set_hook, take_hook}; pub use crate::panicking::update_hook; #[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")] pub use core::panic::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe}; diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 5699937cdb49b..d6ef8f0dbbee3 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -9,8 +9,8 @@ #![deny(unsafe_op_in_unsafe_fn)] -use crate::panic::BacktraceStyle; -use core::panic::{Location, PanicInfo, PanicPayload}; +use crate::panic::{BacktraceStyle, PanicInfo}; +use core::panic::{Location, PanicPayload}; use crate::any::Any; use crate::fmt; @@ -597,7 +597,7 @@ pub fn panicking() -> bool { /// Entry point of panics from the core crate (`panic_impl` lang item). #[cfg(not(any(test, doctest)))] #[panic_handler] -pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { +pub fn begin_panic_handler(info: &core::panic::PanicInfo<'_>) -> ! { struct FormatStringPayload<'a> { inner: &'a fmt::Arguments<'a>, string: Option, @@ -648,22 +648,20 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { } 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 || { - // FIXME: can we just pass `info` along rather than taking it apart here, only to have - // `rust_panic_with_hook` construct a new `PanicInfo`? - if let Some(msg) = msg.as_str() { + if let Some(s) = msg.as_str() { rust_panic_with_hook( - &mut StaticStrPayload(msg), - info.message(), + &mut StaticStrPayload(s), + Some(msg), loc, info.can_unwind(), info.force_no_backtrace(), ); } else { rust_panic_with_hook( - &mut FormatStringPayload::new(msg), - info.message(), + &mut FormatStringPayload::new(&msg), + Some(msg), loc, info.can_unwind(), info.force_no_backtrace(), @@ -740,7 +738,7 @@ pub const fn begin_panic(msg: M) -> ! { /// abort or unwind. fn rust_panic_with_hook( payload: &mut dyn PanicPayload, - message: Option<&fmt::Arguments<'_>>, + message: Option>, location: &Location<'_>, can_unwind: bool, force_no_backtrace: bool, @@ -767,20 +765,17 @@ fn rust_panic_with_hook( panic_count::MustAbort::AlwaysAbort => { // Unfortunately, this does not print a backtrace, because creating // a `Backtrace` will allocate, which we must avoid here. - let panicinfo = PanicInfo::internal_constructor( - message, - location, - can_unwind, - force_no_backtrace, - ); - rtprintpanic!("{panicinfo}\npanicked after panic::always_abort(), aborting.\n"); + if let Some(message) = message { + rtprintpanic!("aborting due to panic at {location}:\n{message}\n"); + } else { + rtprintpanic!("aborting due to panic at {location}\n"); + } } } crate::sys::abort_internal(); } - let mut info = - PanicInfo::internal_constructor(message, location, can_unwind, force_no_backtrace); + let mut info = PanicInfo::internal_constructor(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 From a519dc85f8aa1348ec9cdc46906bbcbb9d115981 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 26 Sep 2023 14:40:36 +0200 Subject: [PATCH 13/35] Document difference between core and std's PanicInfo. --- library/core/src/panic/panic_info.rs | 9 +++++++++ library/std/src/panic.rs | 11 +++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index 2b7bc76fbc278..6a600e2d43123 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -4,6 +4,15 @@ use crate::panic::Location; /// A struct providing information about a panic. /// /// A `PanicInfo` structure is passed to the panic handler defined by `#[panic_handler]`. +/// +/// There two `PanicInfo` types: +/// - `core::panic::PanicInfo`, which is used as an argument to a `#[panic_handler]` in `#![no_std]` programs. +/// - [`std::panic::PanicInfo`], which is used as an argument to a panic hook set by [`std::panic::set_hook`]. +/// +/// This is the first one. +/// +/// [`std::panic::set_hook`]: ../../std/panic/fn.set_hook.html +/// [`std::panic::PanicInfo`]: ../../std/panic/struct.PanicInfo.html #[lang = "panic_info"] #[stable(feature = "panic_hooks", since = "1.10.0")] #[derive(Debug)] diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 18072f6fe3df9..54ab433d8209e 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -12,11 +12,16 @@ use crate::thread::Result; /// A struct providing information about a panic. /// -/// `PanicInfo` structure is passed to a panic hook set by the [`set_hook`] -/// function. +/// `PanicInfo` structure is passed to a panic hook set by the [`set_hook`] function. /// /// [`set_hook`]: ../../std/panic/fn.set_hook.html /// +/// There two `PanicInfo` types: +/// - [`core::panic::PanicInfo`], which is used as an argument to a `#[panic_handler]` in `#![no_std]` programs. +/// - `std::panic::PanicInfo`, which is used as an argument to a panic hook set by [`std::panic::set_hook`]. +/// +/// This is the second one. +/// /// # Examples /// /// ```should_panic @@ -28,6 +33,8 @@ use crate::thread::Result; /// /// panic!("critical system failure"); /// ``` +/// +/// [`core::panic::PanicInfo`]: ../../core/panic/struct.PanicInfo.html #[stable(feature = "panic_hooks", since = "1.10.0")] #[derive(Debug)] pub struct PanicInfo<'a> { From 16dfc6ddc114efa7174e2daa972916bbd2f67d87 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 26 Sep 2023 14:40:50 +0200 Subject: [PATCH 14/35] Add core::panic::PanicInfo::payload() for compatibility. --- library/core/src/panic/panic_info.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index 6a600e2d43123..5b784ff4f80a3 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -81,6 +81,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::PanicInfo`], + /// which used to be the same type. + /// + /// See [`std::panic::PanicInfo::payload`]. + /// + /// [`std::panic::PanicInfo`]: ../../std/panic/struct.PanicInfo.html + /// [`std::panic::PanicInfo::payload`]: ../../std/panic/struct.PanicInfo.html#method.payload + #[deprecated(since = "1.74.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. /// From 331b8a3edde67eb2418e7d9c5c6ef8d9a2a8c0b8 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 26 Sep 2023 15:02:34 +0200 Subject: [PATCH 15/35] Fix doc link. --- library/std/src/panic.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 54ab433d8209e..e2d182b4ba07e 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -14,11 +14,9 @@ use crate::thread::Result; /// /// `PanicInfo` structure is passed to a panic hook set by the [`set_hook`] function. /// -/// [`set_hook`]: ../../std/panic/fn.set_hook.html -/// /// There two `PanicInfo` types: /// - [`core::panic::PanicInfo`], which is used as an argument to a `#[panic_handler]` in `#![no_std]` programs. -/// - `std::panic::PanicInfo`, which is used as an argument to a panic hook set by [`std::panic::set_hook`]. +/// - `std::panic::PanicInfo`, which is used as an argument to a panic hook set by [`set_hook`]. /// /// This is the second one. /// @@ -35,6 +33,7 @@ use crate::thread::Result; /// ``` /// /// [`core::panic::PanicInfo`]: ../../core/panic/struct.PanicInfo.html +/// [`set_hook`]: ../../std/panic/fn.set_hook.html #[stable(feature = "panic_hooks", since = "1.10.0")] #[derive(Debug)] pub struct PanicInfo<'a> { From 83dd214f0651c680cea647c0ce7ccf451840f549 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 2 Oct 2023 14:12:37 +0200 Subject: [PATCH 16/35] Update doc comment about core::panicking. --- library/core/src/panicking.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 683894a5ab49f..aa11ae28dcb15 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -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 containing any type of value. Because of this, std::panic::PanicInfo 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: //! @@ -10,11 +17,6 @@ //! # { loop {} } //! ``` //! -//! This definition allows for panicking with any general message, but it does not -//! allow for failing with a `Box` 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. From 0266bbf6e4be7b025f4798046121607c587e94cb Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 2 Oct 2023 14:13:05 +0200 Subject: [PATCH 17/35] Remove core::panic::PanicInfo::internal_constructor. It no longer needs to be public. --- library/core/src/panic/panic_info.rs | 8 +------- library/core/src/panicking.rs | 10 +++------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index 5b784ff4f80a3..2a0cd8fda61ba 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -24,14 +24,8 @@ pub struct 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] - pub fn internal_constructor( + pub(crate) fn new( message: fmt::Arguments<'a>, location: &'a Location<'a>, can_unwind: bool, diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index aa11ae28dcb15..a6e5528094605 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -63,7 +63,7 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { fn panic_impl(pi: &PanicInfo<'_>) -> !; } - let pi = PanicInfo::internal_constructor( + let pi = PanicInfo::new( fmt, Location::caller(), /* can_unwind */ true, @@ -101,12 +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( - &fmt, - Location::caller(), - /* can_unwind */ false, - force_no_backtrace, - ); + let pi = + PanicInfo::new(fmt, Location::caller(), /* can_unwind */ false, force_no_backtrace); // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call. unsafe { panic_impl(&pi) } From 0642cb2994c192b9e910855b7c9a258376c8e0ff Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 2 Oct 2023 14:14:15 +0200 Subject: [PATCH 18/35] Remove std::panic::PanicInfo::internal_constructor+set_payload. We can just set the payload immediately in the constructor, and the constructor does not need to be public. --- library/std/src/panic.rs | 15 +++------------ library/std/src/panicking.rs | 13 ++++--------- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index e2d182b4ba07e..7adbce859f56c 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -44,23 +44,14 @@ pub struct PanicInfo<'a> { } impl<'a> PanicInfo<'a> { - #[unstable(feature = "panic_internals", issue = "none")] - #[doc(hidden)] #[inline] - pub fn internal_constructor( + pub(crate) fn new( location: &'a Location<'a>, + payload: &'a (dyn Any + Send), can_unwind: bool, force_no_backtrace: bool, ) -> Self { - struct NoPayload; - PanicInfo { payload: &NoPayload, location, can_unwind, force_no_backtrace } - } - - #[unstable(feature = "panic_internals", issue = "none")] - #[doc(hidden)] - #[inline] - pub fn set_payload(&mut self, info: &'a (dyn Any + Send)) { - self.payload = info; + PanicInfo { payload, location, can_unwind, force_no_backtrace } } /// Returns the payload associated with the panic. diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index d6ef8f0dbbee3..6d6aca01561a1 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -775,9 +775,7 @@ fn rust_panic_with_hook( crate::sys::abort_internal(); } - let mut info = PanicInfo::internal_constructor(location, can_unwind, force_no_backtrace); - let hook = HOOK.read().unwrap_or_else(PoisonError::into_inner); - match *hook { + match *HOOK.read().unwrap_or_else(PoisonError::into_inner) { // 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 // hook. Since string formatting happens lazily when calling `payload` @@ -786,15 +784,12 @@ fn rust_panic_with_hook( // formatting.) Hook::Default if panic_output().is_none() => {} Hook::Default => { - info.set_payload(payload.get()); - default_hook(&info); + default_hook(&PanicInfo::new(location, payload.get(), can_unwind, force_no_backtrace)); } Hook::Custom(ref hook) => { - info.set_payload(payload.get()); - hook(&info); + hook(&PanicInfo::new(location, payload.get(), can_unwind, force_no_backtrace)); } - }; - drop(hook); + } // 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 From 0087d899835cbcfa7c52e32c1825f8740621a485 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 2 Oct 2023 14:14:55 +0200 Subject: [PATCH 19/35] Mark some PanicInfo methods as #[inline] for consistency. --- library/std/src/panic.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 7adbce859f56c..ca0ec12a6009c 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -76,6 +76,7 @@ impl<'a> PanicInfo<'a> { /// panic!("Normal panic"); /// ``` #[must_use] + #[inline] #[stable(feature = "panic_hooks", since = "1.10.0")] pub fn payload(&self) -> &(dyn Any + Send) { self.payload @@ -106,6 +107,7 @@ impl<'a> PanicInfo<'a> { /// 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, @@ -124,6 +126,7 @@ impl<'a> PanicInfo<'a> { /// 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 From 4e356f3184ff43aeb68968a8ab96a0faacf6281b Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 2 Oct 2023 14:15:21 +0200 Subject: [PATCH 20/35] Move downcasting panic payload to str to a function. --- library/std/src/panicking.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 6d6aca01561a1..53df0bb40b5b5 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -248,13 +248,7 @@ fn default_hook(info: &PanicInfo<'_>) { // The current implementation always returns `Some`. let location = info.location().unwrap(); - let msg = match info.payload().downcast_ref::<&'static str>() { - Some(s) => *s, - None => match info.payload().downcast_ref::() { - Some(s) => &s[..], - None => "Box", - }, - }; + let msg = payload_as_str(info.payload()); let thread = thread::try_current(); let name = thread.as_ref().and_then(|t| t.name()).unwrap_or(""); @@ -731,6 +725,16 @@ pub const fn begin_panic(msg: M) -> ! { } } +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::() { + s.as_str() + } else { + "Box" + } +} + /// Central point for dispatching panics. /// /// Executes the primary logic for a panic, including checking for recursive From 22f7399b32dcf1bd4d38b7e88a9b482fba889a8f Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 2 Oct 2023 14:16:10 +0200 Subject: [PATCH 21/35] Use unnamed lifetimes for [..]Payload impl blocks. --- library/std/src/panicking.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 53df0bb40b5b5..a460f41b93d3d 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -597,11 +597,7 @@ pub fn begin_panic_handler(info: &core::panic::PanicInfo<'_>) -> ! { string: Option, } - impl<'a> FormatStringPayload<'a> { - fn new(inner: &'a fmt::Arguments<'a>) -> Self { - Self { inner, string: None } - } - + impl FormatStringPayload<'_> { fn fill(&mut self) -> &mut String { use crate::fmt::Write; @@ -615,7 +611,7 @@ pub fn begin_panic_handler(info: &core::panic::PanicInfo<'_>) -> ! { } } - unsafe impl<'a> PanicPayload for FormatStringPayload<'a> { + unsafe impl PanicPayload for FormatStringPayload<'_> { fn take_box(&mut self) -> *mut (dyn Any + Send) { // 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 @@ -654,7 +650,7 @@ pub fn begin_panic_handler(info: &core::panic::PanicInfo<'_>) -> ! { ); } else { rust_panic_with_hook( - &mut FormatStringPayload::new(&msg), + &mut FormatStringPayload { inner: &msg, string: None }, Some(msg), loc, info.can_unwind(), From 1642de33d3c4e59f3b4a766d0ad1abe046f0433f Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 2 Oct 2023 14:17:16 +0200 Subject: [PATCH 22/35] Impl Display for PanicPayload to simplify things. --- library/core/src/panic.rs | 2 +- library/std/src/panicking.rs | 37 +++++++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index 8771f40f9b42b..c9f3702e17889 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -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`, but we cannot use `Box` in core. /// diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index a460f41b93d3d..362aa8d06f33b 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -625,6 +625,12 @@ pub fn begin_panic_handler(info: &core::panic::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); unsafe impl PanicPayload for StaticStrPayload { @@ -637,13 +643,18 @@ pub fn begin_panic_handler(info: &core::panic::PanicInfo<'_>) -> ! { } } + 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 msg = info.message(); crate::sys_common::backtrace::__rust_end_short_backtrace(move || { if let Some(s) = msg.as_str() { rust_panic_with_hook( &mut StaticStrPayload(s), - Some(msg), loc, info.can_unwind(), info.force_no_backtrace(), @@ -651,7 +662,6 @@ pub fn begin_panic_handler(info: &core::panic::PanicInfo<'_>) -> ! { } else { rust_panic_with_hook( &mut FormatStringPayload { inner: &msg, string: None }, - Some(msg), loc, info.can_unwind(), info.force_no_backtrace(), @@ -681,7 +691,6 @@ pub const fn begin_panic(msg: M) -> ! { 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, @@ -719,6 +728,15 @@ pub const fn begin_panic(msg: M) -> ! { } } } + + impl fmt::Display for Payload { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match &self.inner { + Some(a) => f.write_str(payload_as_str(a)), + None => process::abort(), + } + } + } } fn payload_as_str(payload: &dyn Any) -> &str { @@ -738,7 +756,6 @@ fn payload_as_str(payload: &dyn Any) -> &str { /// abort or unwind. fn rust_panic_with_hook( payload: &mut dyn PanicPayload, - message: Option>, location: &Location<'_>, can_unwind: bool, force_no_backtrace: bool, @@ -765,11 +782,7 @@ fn rust_panic_with_hook( panic_count::MustAbort::AlwaysAbort => { // Unfortunately, this does not print a backtrace, because creating // a `Backtrace` will allocate, which we must avoid here. - if let Some(message) = message { - rtprintpanic!("aborting due to panic at {location}:\n{message}\n"); - } else { - rtprintpanic!("aborting due to panic at {location}\n"); - } + rtprintpanic!("aborting due to panic at {location}:\n{payload}\n"); } } crate::sys::abort_internal(); @@ -825,6 +838,12 @@ pub fn rust_panic_without_hook(payload: Box) -> ! { } } + 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)) } From bab26b02c78f46265d59dda4cf558918008617b2 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 2 Oct 2023 14:29:58 +0200 Subject: [PATCH 23/35] Reorder body of begin_panic for consistency. In the other functions, we put the struct and impl blocks first, such that the return expression can be at the end of the body as usual. --- library/std/src/panicking.rs | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 362aa8d06f33b..15544de9ff81f 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -687,26 +687,10 @@ pub const fn begin_panic(msg: M) -> ! { intrinsics::abort() } - let loc = Location::caller(); - return crate::sys_common::backtrace::__rust_end_short_backtrace(move || { - rust_panic_with_hook( - &mut Payload::new(msg), - loc, - /* can_unwind */ true, - /* force_no_backtrace */ false, - ) - }); - struct Payload { inner: Option, } - impl Payload { - fn new(inner: A) -> Payload { - Payload { inner: Some(inner) } - } - } - unsafe impl PanicPayload for Payload { fn take_box(&mut self) -> *mut (dyn Any + Send) { // Note that this should be the only allocation performed in this code path. Currently @@ -729,7 +713,7 @@ pub const fn begin_panic(msg: M) -> ! { } } - impl fmt::Display for Payload { + impl fmt::Display for Payload { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match &self.inner { Some(a) => f.write_str(payload_as_str(a)), @@ -737,6 +721,16 @@ pub const fn begin_panic(msg: M) -> ! { } } } + + 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 { From 6b2d7c47072a466b938fac75db416c9adbf59892 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 2 Oct 2023 14:58:31 +0200 Subject: [PATCH 24/35] Fix invalid markdown/html. --- library/core/src/panicking.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index a6e5528094605..0793c1b0f29b7 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -2,7 +2,7 @@ //! //! 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 containing any type of value. Because of this, std::panic::PanicInfo is a +//! a `Box` containing any type of value. Because of this, std::panic::PanicInfo 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. From b6180a918538b3afa04bbc1c5515c0be2154e1b6 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 31 Jan 2024 09:35:17 +0100 Subject: [PATCH 25/35] Formatting. --- library/core/src/panicking.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 0793c1b0f29b7..94b4113b24518 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -101,8 +101,12 @@ 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::new(fmt, Location::caller(), /* can_unwind */ false, force_no_backtrace); + let pi = PanicInfo::new( + fmt, + Location::caller(), + /* can_unwind */ false, + force_no_backtrace, + ); // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call. unsafe { panic_impl(&pi) } From 64e56db72aa2b1f112504504a7dceba63881cdef Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 31 Jan 2024 10:27:29 +0100 Subject: [PATCH 26/35] Rename std::panic::PanicInfo to PanicHookInfo. --- compiler/rustc_driver_impl/src/lib.rs | 9 +++--- library/core/src/error.md | 4 +-- library/core/src/panic/location.rs | 3 +- library/core/src/panic/panic_info.rs | 17 ++++------ library/core/src/panicking.rs | 12 +++---- library/std/src/panic.rs | 31 +++++++++++-------- library/std/src/panicking.rs | 25 +++++++++------ library/test/src/lib.rs | 6 ++-- tests/ui/duplicate_entry_error.rs | 4 ++- tests/ui/duplicate_entry_error.stderr | 2 +- tests/ui/panic-handler/panic-handler-std.rs | 3 +- .../ui/panic-handler/panic-handler-std.stderr | 2 +- 12 files changed, 63 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 93a65290602af..fef4ce0b471c8 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -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; @@ -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)] @@ -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, diff --git a/library/core/src/error.md b/library/core/src/error.md index a5deb71e6b80a..8d5a623df4b75 100644 --- a/library/core/src/error.md +++ b/library/core/src/error.md @@ -17,7 +17,7 @@ The following are the primary interfaces of the panic system and the responsibilities they cover: * [`panic!`] and [`panic_any`] (Constructing, Propagated automatically) -* [`PanicInfo`] (Reporting) +* [`PanicHookInfo`] (Reporting) * [`set_hook`], [`take_hook`], and [`#[panic_handler]`][panic-handler] (Reporting) * [`catch_unwind`] and [`resume_unwind`] (Discarding, Propagating) @@ -125,7 +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 -[`PanicInfo`]: crate::panic::PanicInfo +[`PanicHookInfo`]: ../../std/panic/struct.PanicHookInfo.html [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html [`resume_unwind`]: ../../std/panic/fn.resume_unwind.html [`downcast`]: crate::error::Error diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs index eb27da1724ec9..8c04994ac0fc4 100644 --- a/library/core/src/panic/location.rs +++ b/library/core/src/panic/location.rs @@ -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 /// diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index 2a0cd8fda61ba..7c792a58d2a8e 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -5,14 +5,9 @@ use crate::panic::Location; /// /// A `PanicInfo` structure is passed to the panic handler defined by `#[panic_handler]`. /// -/// There two `PanicInfo` types: -/// - `core::panic::PanicInfo`, which is used as an argument to a `#[panic_handler]` in `#![no_std]` programs. -/// - [`std::panic::PanicInfo`], which is used as an argument to a panic hook set by [`std::panic::set_hook`]. +/// For the type used by the panic hook mechanism in `std`, see [`std::panic::PanicHookInfo`]. /// -/// This is the first one. -/// -/// [`std::panic::set_hook`]: ../../std/panic/fn.set_hook.html -/// [`std::panic::PanicInfo`]: ../../std/panic/struct.PanicInfo.html +/// [`std::panic::PanicHookInfo`]: ../../std/panic/struct.PanicHookInfo.html #[lang = "panic_info"] #[stable(feature = "panic_hooks", since = "1.10.0")] #[derive(Debug)] @@ -78,13 +73,13 @@ impl<'a> PanicInfo<'a> { /// 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::PanicInfo`], + /// It only exists because of compatibility with [`std::panic::PanicHookInfo`], /// which used to be the same type. /// - /// See [`std::panic::PanicInfo::payload`]. + /// See [`std::panic::PanicHookInfo::payload`]. /// - /// [`std::panic::PanicInfo`]: ../../std/panic/struct.PanicInfo.html - /// [`std::panic::PanicInfo::payload`]: ../../std/panic/struct.PanicInfo.html#method.payload + /// [`std::panic::PanicHookInfo`]: ../../std/panic/struct.PanicHookInfo.html + /// [`std::panic::PanicHookInfo::payload`]: ../../std/panic/struct.PanicHookInfo.html#method.payload #[deprecated(since = "1.74.0", note = "this never returns anything useful")] #[stable(feature = "panic_hooks", since = "1.10.0")] #[allow(deprecated, deprecated_in_future)] diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 94b4113b24518..97fb1d6b7323f 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -1,11 +1,11 @@ //! Panic support for core //! -//! 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` containing any type of value. Because of this, std::panic::PanicInfo 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. +//! 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` 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 diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index ca0ec12a6009c..77defe14b708a 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -10,15 +10,21 @@ use crate::sync::atomic::{AtomicU8, Ordering}; use crate::sync::{Condvar, Mutex, RwLock}; use crate::thread::Result; +#[stable(feature = "panic_hooks", since = "1.10.0")] +#[deprecated( + since = "1.77.0", + note = "use `PanicHookInfo` instead", + suggestion = "std::panic::PanicHookInfo" +)] /// A struct providing information about a panic. /// -/// `PanicInfo` structure is passed to a panic hook set by the [`set_hook`] function. -/// -/// There two `PanicInfo` types: -/// - [`core::panic::PanicInfo`], which is used as an argument to a `#[panic_handler]` in `#![no_std]` programs. -/// - `std::panic::PanicInfo`, which is used as an argument to a panic hook set by [`set_hook`]. +/// `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. /// -/// This is the second one. +/// `PanicHookInfo` structure is passed to a panic hook set by the [`set_hook`] function. /// /// # Examples /// @@ -32,18 +38,17 @@ use crate::thread::Result; /// panic!("critical system failure"); /// ``` /// -/// [`core::panic::PanicInfo`]: ../../core/panic/struct.PanicInfo.html /// [`set_hook`]: ../../std/panic/fn.set_hook.html -#[stable(feature = "panic_hooks", since = "1.10.0")] +#[stable(feature = "panic_hook_info", since = "CURRENT_RUSTC_VERSION")] #[derive(Debug)] -pub struct PanicInfo<'a> { +pub struct PanicHookInfo<'a> { payload: &'a (dyn Any + Send), location: &'a Location<'a>, can_unwind: bool, force_no_backtrace: bool, } -impl<'a> PanicInfo<'a> { +impl<'a> PanicHookInfo<'a> { #[inline] pub(crate) fn new( location: &'a Location<'a>, @@ -51,7 +56,7 @@ impl<'a> PanicInfo<'a> { can_unwind: bool, force_no_backtrace: bool, ) -> Self { - PanicInfo { payload, location, can_unwind, force_no_backtrace } + PanicHookInfo { payload, location, can_unwind, force_no_backtrace } } /// Returns the payload associated with the panic. @@ -145,7 +150,7 @@ impl<'a> PanicInfo<'a> { } #[stable(feature = "panic_hook_display", since = "1.26.0")] -impl fmt::Display for PanicInfo<'_> { +impl fmt::Display for PanicHookInfo<'_> { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("panicked at ")?; self.location.fmt(formatter)?; @@ -204,7 +209,7 @@ pub use core::panic::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe}; /// 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 -/// accessed later using [`PanicInfo::payload`]. +/// accessed later using [`PanicHookInfo::payload`]. /// /// See the [`panic!`] macro for more information about panicking. #[stable(feature = "panic_any", since = "1.51.0")] diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 15544de9ff81f..caab7ed4b81a6 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -9,7 +9,7 @@ #![deny(unsafe_op_in_unsafe_fn)] -use crate::panic::{BacktraceStyle, PanicInfo}; +use crate::panic::{BacktraceStyle, PanicHookInfo}; use core::panic::{Location, PanicPayload}; use crate::any::Any; @@ -70,12 +70,12 @@ extern "C" fn __rust_foreign_exception() -> ! { enum Hook { Default, - Custom(Box) + 'static + Sync + Send>), + Custom(Box) + 'static + Sync + Send>), } impl Hook { #[inline] - fn into_box(self) -> Box) + 'static + Sync + Send> { + fn into_box(self) -> Box) + 'static + Sync + Send> { match self { Hook::Default => Box::new(default_hook), Hook::Custom(hook) => hook, @@ -105,7 +105,7 @@ static HOOK: RwLock = RwLock::new(Hook::Default); /// /// [`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 /// the source code location from which the panic originated. /// @@ -129,7 +129,7 @@ static HOOK: RwLock = RwLock::new(Hook::Default); /// panic!("Normal panic"); /// ``` #[stable(feature = "panic_hooks", since = "1.10.0")] -pub fn set_hook(hook: Box) + 'static + Sync + Send>) { +pub fn set_hook(hook: Box) + 'static + Sync + Send>) { if thread::panicking() { panic!("cannot modify the panic hook from a panicking thread"); } @@ -173,7 +173,7 @@ pub fn set_hook(hook: Box) + 'static + Sync + Send>) { /// ``` #[must_use] #[stable(feature = "panic_hooks", since = "1.10.0")] -pub fn take_hook() -> Box) + 'static + Sync + Send> { +pub fn take_hook() -> Box) + 'static + Sync + Send> { if thread::panicking() { panic!("cannot modify the panic hook from a panicking thread"); } @@ -219,7 +219,7 @@ pub fn take_hook() -> Box) + 'static + Sync + Send> { #[unstable(feature = "panic_update_hook", issue = "92649")] pub fn update_hook(hook_fn: F) where - F: Fn(&(dyn Fn(&PanicInfo<'_>) + Send + Sync + 'static), &PanicInfo<'_>) + F: Fn(&(dyn Fn(&PanicHookInfo<'_>) + Send + Sync + 'static), &PanicHookInfo<'_>) + Sync + Send + 'static, @@ -234,7 +234,7 @@ where } /// 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 // for this panic. Otherwise only print it if logging is enabled. let backtrace = if info.force_no_backtrace() { @@ -791,10 +791,15 @@ fn rust_panic_with_hook( // formatting.) Hook::Default if panic_output().is_none() => {} Hook::Default => { - default_hook(&PanicInfo::new(location, payload.get(), can_unwind, force_no_backtrace)); + default_hook(&PanicHookInfo::new( + location, + payload.get(), + can_unwind, + force_no_backtrace, + )); } Hook::Custom(ref hook) => { - hook(&PanicInfo::new(location, payload.get(), can_unwind, force_no_backtrace)); + hook(&PanicHookInfo::new(location, payload.get(), can_unwind, force_no_backtrace)); } } diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 7bd08a0605f83..7aff7fe1fdd68 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -58,7 +58,7 @@ use std::{ env, io, io::prelude::Write, mem::ManuallyDrop, - panic::{self, catch_unwind, AssertUnwindSafe, PanicInfo}, + panic::{self, catch_unwind, AssertUnwindSafe, PanicHookInfo}, process::{self, Command, Termination}, sync::mpsc::{channel, Sender}, sync::{Arc, Mutex}, @@ -123,7 +123,7 @@ pub fn test_main(args: &[String], tests: Vec, options: Option| { + move |info: &'_ PanicHookInfo<'_>| { if !info.can_unwind() { std::mem::forget(std::io::stderr().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) -> ! { 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 { Some(info) => calc_result(&desc, Err(info.payload()), &None, &None), None => calc_result(&desc, Ok(()), &None, &None), diff --git a/tests/ui/duplicate_entry_error.rs b/tests/ui/duplicate_entry_error.rs index 7ebbab4709557..8e49f57a3df94 100644 --- a/tests/ui/duplicate_entry_error.rs +++ b/tests/ui/duplicate_entry_error.rs @@ -5,7 +5,9 @@ #![feature(lang_items)] -use std::panic::PanicInfo; +extern crate core; + +use core::panic::PanicInfo; #[lang = "panic_impl"] fn panic_impl(info: &PanicInfo) -> ! { diff --git a/tests/ui/duplicate_entry_error.stderr b/tests/ui/duplicate_entry_error.stderr index 3b5998df353c4..958e9c7527d8c 100644 --- a/tests/ui/duplicate_entry_error.stderr +++ b/tests/ui/duplicate_entry_error.stderr @@ -1,5 +1,5 @@ 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 | | diff --git a/tests/ui/panic-handler/panic-handler-std.rs b/tests/ui/panic-handler/panic-handler-std.rs index 91b3997819ce4..051828ec8809f 100644 --- a/tests/ui/panic-handler/panic-handler-std.rs +++ b/tests/ui/panic-handler/panic-handler-std.rs @@ -1,8 +1,9 @@ //@ normalize-stderr-test "loaded from .*libstd-.*.rlib" -> "loaded from SYSROOT/libstd-*.rlib" //@ error-pattern: found duplicate lang item `panic_impl` +extern crate core; -use std::panic::PanicInfo; +use core::panic::PanicInfo; #[panic_handler] fn panic(info: PanicInfo) -> ! { diff --git a/tests/ui/panic-handler/panic-handler-std.stderr b/tests/ui/panic-handler/panic-handler-std.stderr index 48c216ce27ec4..caae16118ef7f 100644 --- a/tests/ui/panic-handler/panic-handler-std.stderr +++ b/tests/ui/panic-handler/panic-handler-std.stderr @@ -1,5 +1,5 @@ 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 | | loop {} From 3854357ad2c164a87f7e625874d4cdc3ccd9cc33 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 31 Jan 2024 10:28:00 +0100 Subject: [PATCH 27/35] Fix deprecation version. --- library/core/src/panic/panic_info.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index 7c792a58d2a8e..df8f441bf3533 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -80,7 +80,7 @@ impl<'a> PanicInfo<'a> { /// /// [`std::panic::PanicHookInfo`]: ../../std/panic/struct.PanicHookInfo.html /// [`std::panic::PanicHookInfo::payload`]: ../../std/panic/struct.PanicHookInfo.html#method.payload - #[deprecated(since = "1.74.0", note = "this never returns anything useful")] + #[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) { From f5fe82fdcab33b4137b94014f05dd2986ea396ba Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 31 Jan 2024 11:32:53 +0100 Subject: [PATCH 28/35] Move deprecation of std::panic::PanicInfo to 1.80.0. --- library/std/src/panic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 77defe14b708a..0f999f6a93e4a 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -12,7 +12,7 @@ use crate::thread::Result; #[stable(feature = "panic_hooks", since = "1.10.0")] #[deprecated( - since = "1.77.0", + since = "1.80.0", note = "use `PanicHookInfo` instead", suggestion = "std::panic::PanicHookInfo" )] From ce0bc8bd588f9a2a4ba149ae6a9d3490f401c376 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 16 May 2024 11:49:55 +0200 Subject: [PATCH 29/35] Downcast panic payload to String too in example. --- library/std/src/panic.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 0f999f6a93e4a..51228cc990751 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -73,6 +73,8 @@ impl<'a> PanicHookInfo<'a> { /// 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::() { + /// println!("panic occurred: {s:?}"); /// } else { /// println!("panic occurred"); /// } From 32bfe703e2f8b5062a769aa1b3467c80d5bb0b95 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 16 May 2024 11:54:11 +0200 Subject: [PATCH 30/35] Add note on panic payload type. --- library/std/src/panic.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 51228cc990751..d5566caa369cf 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -63,6 +63,13 @@ impl<'a> PanicHookInfo<'a> { /// /// 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 From 877a26f6c9cbd9878ea08c94cd5a698a53556511 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 16 May 2024 12:58:46 +0200 Subject: [PATCH 31/35] Mention core's PanicInfo in error.md. --- library/core/src/error.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/core/src/error.md b/library/core/src/error.md index 8d5a623df4b75..4b62391cafc37 100644 --- a/library/core/src/error.md +++ b/library/core/src/error.md @@ -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) -* [`PanicHookInfo`] (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 @@ -126,6 +126,7 @@ 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 [`downcast`]: crate::error::Error From fb0990d1e1e67a512930665bf7df5fb91f55982c Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 16 May 2024 12:59:09 +0200 Subject: [PATCH 32/35] Fix display of panic message in recursive panic. --- library/core/src/panic.rs | 5 +++++ library/std/src/panicking.rs | 15 ++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index c9f3702e17889..b5a0932221ad6 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -157,4 +157,9 @@ pub unsafe trait PanicPayload: crate::fmt::Display { /// 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 + } } diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index caab7ed4b81a6..e4d2ee7d98680 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -641,6 +641,10 @@ pub fn begin_panic_handler(info: &core::panic::PanicInfo<'_>) -> ! { fn get(&mut self) -> &(dyn Any + Send) { &self.0 } + + fn as_str(&mut self) -> Option<&str> { + Some(self.0) + } } impl fmt::Display for StaticStrPayload { @@ -763,15 +767,8 @@ fn rust_panic_with_hook( // 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 // 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 = msg_str.as_ref().map(|m| fmt::Arguments::new_const(m)); - let panicinfo = PanicInfo::internal_constructor( - message.as_ref(), - location, - can_unwind, - force_no_backtrace, - ); - rtprintpanic!("{panicinfo}\nthread panicked while processing panic. aborting.\n"); + let message: &str = payload.as_str().unwrap_or_default(); + rtprintpanic!("panicked at {location}:\n{message}\nthread panicked while processing panic. aborting.\n"); } panic_count::MustAbort::AlwaysAbort => { // Unfortunately, this does not print a backtrace, because creating From de07c1a928b3a1e6e12946c9d9d0ff47c2310ead Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 16 May 2024 13:08:27 +0200 Subject: [PATCH 33/35] Add PanicHookInfo::payload_as_str(). --- library/std/src/panic.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index d5566caa369cf..f1b45b1863058 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -96,6 +96,45 @@ impl<'a> PanicHookInfo<'a> { 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::() { + Some(s) + } else { + None + } + } + /// Returns information about the location from which the panic originated, /// if available. /// From a345c3daf65857fb12926c3c5f4c9d8e2ca00f00 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 16 May 2024 13:08:40 +0200 Subject: [PATCH 34/35] Bump deprecation of std's PanicInfo alias to 1.82.0. --- library/std/src/panic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index f1b45b1863058..5282c00fccaf0 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -12,7 +12,7 @@ use crate::thread::Result; #[stable(feature = "panic_hooks", since = "1.10.0")] #[deprecated( - since = "1.80.0", + since = "1.82.0", note = "use `PanicHookInfo` instead", suggestion = "std::panic::PanicHookInfo" )] From a6e23b126b925b270663436a1d2f4d24cc5f4711 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 11 Jun 2024 15:46:15 +0200 Subject: [PATCH 35/35] Formatting. --- library/std/src/panicking.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index e4d2ee7d98680..8fd8134c11147 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -768,7 +768,9 @@ fn rust_panic_with_hook( // recursive panics. However if the message is just a string, no user-defined // code is involved in printing it, so that is risk-free. let message: &str = payload.as_str().unwrap_or_default(); - rtprintpanic!("panicked at {location}:\n{message}\nthread panicked while processing panic. aborting.\n"); + rtprintpanic!( + "panicked at {location}:\n{message}\nthread panicked while processing panic. aborting.\n" + ); } panic_count::MustAbort::AlwaysAbort => { // Unfortunately, this does not print a backtrace, because creating