Skip to content

Commit

Permalink
feat(gstd) use stabilized panic_info_message feature from rust 1.81 (
Browse files Browse the repository at this point in the history
  • Loading branch information
StackOverflowExcept1on authored Sep 9, 2024
1 parent 056d0dd commit bc70fa0
Show file tree
Hide file tree
Showing 9 changed files with 11 additions and 197 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ edition = "2021"
license = "GPL-3.0"
homepage = "https://gear-tech.io"
repository = "https://github.com/gear-tech/gear"
rust-version = "1.80"
rust-version = "1.81"

[workspace]
resolver = "2"
Expand Down
16 changes: 6 additions & 10 deletions gstd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,24 +52,20 @@ panic-message = ["panic-handler", "arrayvec"]
## because it displays the code path.
panic-location = ["panic-message"]

#! ## Nightly features
#!
#! The `panic-message` and `panic-location` features gets additional
#! optimizations when using the nightly compiler.
#!
#! For example, if you don't use the `panic-location` feature, the compiler
#! will remove all locations such as `/home/username/dapp/src/lib.rs:1:2`
#! from the binary. The size of program will be reduced and
#! `/home/username/...` information will not be included in the binary.

#! ## Nightly features
#!
#! The final binary gets additional optimizations when using the nightly compiler.

## Enables all features below.
## These features depend on unstable Rust API and require nightly toolchain.
nightly = ["panic-info-message", "oom-handler"]
## When enabled, a panic handler will use a more efficient implementation.
## Relies on [`panic_info_message`][rust-66745].
panic-info-message = []
nightly = ["oom-handler"]
## When enabled, an OOM error handler is provided.
## Relies on [`alloc_error_handler`][rust-51540],
## Relies on [`alloc_error_handler`][rust-51540].
oom-handler = []

#! ## Additional features
Expand Down
132 changes: 2 additions & 130 deletions gstd/src/common/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,6 @@ pub fn oom(_: core::alloc::Layout) -> ! {
/// - `panic-handler`: it displays `panicked with '<unknown>'`
/// - `panic-message`: it displays `panicked with '{message}'`
/// - `panic-location`: it displays `panicked with '{message}' at '{location}'`
///
/// How we get the panic message in different versions of Rust:
/// - In nightly Rust, we use `#![feature(panic_info_message)]` and the
/// [`write!`] macro.
/// - In stable Rust, we need to modify the default panic handler message
/// format.
///
/// Default panic handler message format (according to <https://github.com/rust-lang/rust/pull/112849>):
/// `panicked at {location}:\n{message}`
///
/// We parse the output of `impl Display for PanicInfo<'_>` and
/// then convert it to custom format:
/// `panicked with '{message}'[ at '{location}']`.
#[cfg(target_arch = "wasm32")]
#[cfg(feature = "panic-handler")]
mod panic_handler {
Expand All @@ -61,11 +48,6 @@ mod panic_handler {
/// internal errors occur.
#[cfg(not(feature = "panic-message"))]
pub const UNKNOWN_REASON: &str = "<unknown>";

/// This prefix is used by `impl Display for PanicInfo<'_>`.
#[cfg(all(not(feature = "panic-info-message"), feature = "panic-message"))]
pub const PANICKED_AT: &str = "panicked at ";

/// Max amount of bytes allowed to be thrown as string explanation
/// of the error.
#[cfg(feature = "panic-message")]
Expand All @@ -87,8 +69,8 @@ mod panic_handler {
ext::panic(MESSAGE)
}

/// Panic handler for nightly Rust.
#[cfg(all(feature = "panic-info-message", feature = "panic-message"))]
/// Panic handler with extra information.
#[cfg(feature = "panic-message")]
#[panic_handler]
pub fn panic(panic_info: &PanicInfo) -> ! {
use crate::prelude::fmt::Write;
Expand All @@ -112,114 +94,4 @@ mod panic_handler {

ext::panic(&debug_msg)
}

/// Panic handler for stable Rust.
#[cfg(all(not(feature = "panic-info-message"), feature = "panic-message"))]
#[panic_handler]
pub fn panic(panic_info: &PanicInfo) -> ! {
use crate::prelude::fmt::{self, Write};
use arrayvec::ArrayString;

#[derive(Default)]
struct TempBuffer<const CAP: usize> {
overflowed: bool,
buffer: ArrayString<CAP>,
}

impl<const CAP: usize> TempBuffer<CAP> {
#[inline]
fn write_str(&mut self, s: &str) {
if !self.overflowed && self.buffer.write_str(s).is_err() {
self.overflowed = true;
}
}
}

#[derive(Default)]
struct TempOutput {
found_prefix: bool,
found_delimiter: bool,
#[cfg(feature = "panic-location")]
location: TempBuffer<TRIMMED_MAX_LEN>,
message: TempBuffer<TRIMMED_MAX_LEN>,
}

impl fmt::Write for TempOutput {
fn write_str(&mut self, s: &str) -> fmt::Result {
if !self.found_prefix && s.len() == PANICKED_AT.len() {
self.found_prefix = true;
return Ok(());
}

if !self.found_delimiter {
if s == ":\n" || s == "\n" {
self.found_delimiter = true;
return Ok(());
}
#[cfg(feature = "panic-location")]
self.location.write_str(s);
} else {
self.message.write_str(s);
}

Ok(())
}
}

let mut output = TempOutput::default();
let _ = write!(&mut output, "{panic_info}");

#[cfg(feature = "panic-location")]
let location = &*output.location.buffer;
let message = &*output.message.buffer;

let mut debug_msg = ArrayString::<TRIMMED_MAX_LEN>::new();
let _ = debug_msg.try_push_str(PANIC_PREFIX);

#[cfg(feature = "panic-location")]
for s in ["'", message, "' at '", location, "'"] {
if debug_msg.try_push_str(s).is_err() {
break;
}
}

#[cfg(not(feature = "panic-location"))]
for s in ["'", message, "'"] {
if debug_msg.try_push_str(s).is_err() {
break;
}
}

#[cfg(feature = "debug")]
let _ = ext::debug(&debug_msg);

ext::panic(&debug_msg)
}
}

#[cfg(test)]
mod tests {
extern crate std;

use std::{format, panic, prelude::v1::*};

/// Here is a test to verify that the default panic handler message
/// format has not changed.
#[test]
fn panic_msg_format_not_changed() {
const MESSAGE: &str = "message";

panic::set_hook(Box::new(|panic_info| {
let location = panic_info.location().unwrap();
assert_eq!(
panic_info.to_string(),
format!("panicked at {location}:\n{MESSAGE}")
);
}));

let result = panic::catch_unwind(|| {
panic!("{MESSAGE}");
});
assert!(result.is_err());
}
}
2 changes: 1 addition & 1 deletion gstd/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
//! providing convenient instruments for creating programs from programs, etc.
//!
//! # Minimum supported Rust version
//! This crate requires **Rust >= 1.73** due to the implementation of the panic
//! This crate requires **Rust >= 1.81** due to the implementation of the panic
//! handler in the stable version.
//!
//! # Crate features
Expand Down
1 change: 0 additions & 1 deletion utils/wasm-builder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ pwasm-utils = { workspace = true, features = ["sign_ext"] }
toml.workspace = true
log.workspace = true
pathdiff.workspace = true
dirs.workspace = true
gmeta.workspace = true
gear-core.workspace = true
gear-wasm-instrument.workspace = true
Expand Down
24 changes: 1 addition & 23 deletions utils/wasm-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub use gear_wasm_optimizer::{self as optimize, CargoCommand};
pub use wasm_project::{PreProcessor, PreProcessorResult, PreProcessorTarget};

use crate::wasm_project::WasmProject;
use anyhow::{Context, Result};
use anyhow::Result;
use gmeta::{Metadata, MetadataRepr};
use regex::Regex;
use std::{env, path::PathBuf, process};
Expand Down Expand Up @@ -132,9 +132,6 @@ impl WasmBuilder {
let profile = if profile == "debug" { "dev" } else { profile };
self.cargo.set_profile(profile.to_string());
self.cargo.set_features(&self.enabled_features()?);
if env::var("GEAR_WASM_BUILDER_PATH_REMAPPING").is_ok() {
self.cargo.set_paths_to_remap(&self.paths_to_remap()?);
}

self.cargo.run()?;
self.wasm_project.postprocess()
Expand Down Expand Up @@ -203,25 +200,6 @@ impl WasmBuilder {
.filter(|feature| feature != "gcli")
.collect())
}

fn paths_to_remap(&self) -> Result<Vec<(PathBuf, &'static str)>> {
let home_dir = dirs::home_dir().context("unable to get home directory")?;

let project_dir = self.wasm_project.original_dir();

let cargo_dir = std::env::var_os("CARGO_HOME")
.map(PathBuf::from)
.context("unable to get cargo home directory")?;

let cargo_checkouts_dir = cargo_dir.join("git").join("checkouts");

Ok(vec![
(home_dir, "/home"),
(project_dir, "/code"),
(cargo_dir, "/cargo"),
(cargo_checkouts_dir, "/deps"),
])
}
}

impl Default for WasmBuilder {
Expand Down
5 changes: 0 additions & 5 deletions utils/wasm-builder/src/wasm_project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,6 @@ impl WasmProject {
self.out_dir.join("Cargo.toml")
}

/// Return the path to the original project directory.
pub fn original_dir(&self) -> PathBuf {
self.original_dir.clone()
}

/// Return the path to the target directory.
pub fn target_dir(&self) -> PathBuf {
self.target_dir.clone()
Expand Down
25 changes: 0 additions & 25 deletions utils/wasm-optimizer/src/cargo_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ pub struct CargoCommand {
toolchain: Toolchain,
check_recommended_toolchain: bool,
force_recommended_toolchain: bool,
paths_to_remap: Vec<(PathBuf, &'static str)>,
}

impl CargoCommand {
Expand All @@ -48,7 +47,6 @@ impl CargoCommand {
toolchain: Toolchain::try_from_rustup().expect("Failed to get toolchain from rustup"),
check_recommended_toolchain: false,
force_recommended_toolchain: false,
paths_to_remap: vec![],
}
}
}
Expand Down Expand Up @@ -92,13 +90,6 @@ impl CargoCommand {
self.force_recommended_toolchain = force_recommended_toolchain;
}

/// Set paths to remap.
///
/// Used to hide the username from the panic message.
pub fn set_paths_to_remap(&mut self, paths_to_remap: &[(PathBuf, &'static str)]) {
self.paths_to_remap = paths_to_remap.into();
}

/// Execute the `cargo` command with invoking supplied arguments.
pub fn run(&self) -> Result<()> {
if self.check_recommended_toolchain {
Expand Down Expand Up @@ -139,22 +130,6 @@ impl CargoCommand {

self.remove_cargo_encoded_rustflags(&mut cargo);

if !self.paths_to_remap.is_empty() {
// `--remap-path-prefix` is used to remove username from panic messages
// https://doc.rust-lang.org/rustc/command-line-arguments.html#--remap-path-prefix-remap-source-names-in-output
let global_encoded_rustflags = self
.paths_to_remap
.iter()
.map(|(from, to)| format!("--remap-path-prefix={from}={to}", from = from.display()))
.collect::<Vec<_>>()
.join("\x1f");

// The environment variable `CARGO_ENCODED_RUSTFLAGS` is used to globally remap path prefix.
// It is also separated by `\x1f` to support folders with spaces or any unusual characters.
// Unlike `cargo rust`, this is useful for passing flags to all dependencies (i.e. globally).
cargo.env("CARGO_ENCODED_RUSTFLAGS", global_encoded_rustflags);
}

let status = cargo.status().context("unable to execute cargo command")?;
ensure!(
status.success(),
Expand Down

0 comments on commit bc70fa0

Please sign in to comment.