Add more from the std
This commit is contained in:
2
library/.gitignore
vendored
2
library/.gitignore
vendored
@@ -12,3 +12,5 @@ rustc-std-workspace-alloc
|
||||
rustc-std-workspace-core
|
||||
rustc-std-workspace-std
|
||||
windows_link
|
||||
test
|
||||
proc_macro
|
||||
|
||||
201
library/justfile
201
library/justfile
@@ -21,6 +21,11 @@ update-std:
|
||||
@just patch-std
|
||||
|
||||
cp_std path:
|
||||
@echo "Linking {{ path }}"
|
||||
@mkdir {{ "std/src" / parent_directory(path) }} -p
|
||||
@ln -fs {{ RUST_SRC / "std/src" / path }} {{ "std/src" / parent_directory(path) }}
|
||||
|
||||
real_cp_std path:
|
||||
@echo "Copying {{ path }}"
|
||||
@mkdir {{ "std/src" / parent_directory(path) }} -p
|
||||
@cp {{ RUST_SRC / "std/src" / path }} {{ "std/src" / path }}
|
||||
@@ -43,7 +48,9 @@ setup-std:
|
||||
ln -fs {{ RUST_SRC / "profiler_builtins" }} "."
|
||||
ln -fs {{ RUST_SRC / "test" }} "."
|
||||
|
||||
@# Complete
|
||||
@just cp_std "../build.rs"
|
||||
@sed -i "59a\ || target_os == \"survos\"" std/build.rs
|
||||
|
||||
@just cp_std "alloc.rs"
|
||||
@just cp_std "ascii.rs"
|
||||
@just cp_std "backtrace.rs"
|
||||
@@ -61,51 +68,38 @@ setup-std:
|
||||
@just cp_std "process.rs"
|
||||
@just cp_std "random.rs"
|
||||
@just cp_std "rt.rs"
|
||||
# @just cp_std "tests_helpers.rs"
|
||||
@just cp_std "tests_helpers.rs"
|
||||
@just cp_std "time.rs"
|
||||
|
||||
@# Complete
|
||||
ln -fs {{ RUST_SRC / "std/src/backtrace" }} "std/src/"
|
||||
@just cp_std "backtrace"
|
||||
|
||||
@# Complete
|
||||
ln -fs {{ RUST_SRC / "std/src/collections" }} "std/src/"
|
||||
@just cp_std "collections"
|
||||
|
||||
@# Complete
|
||||
ln -fs {{ RUST_SRC / "std/src/ffi" }} "std/src/"
|
||||
@just cp_std "ffi"
|
||||
|
||||
@# Complete
|
||||
ln -fs {{ RUST_SRC / "std/src/fs" }} "std/src/"
|
||||
@just cp_std "fs"
|
||||
|
||||
@# Complete
|
||||
ln -fs {{ RUST_SRC / "std/src/hash" }} "std/src/"
|
||||
@just cp_std "hash"
|
||||
|
||||
@# Complete
|
||||
ln -fs {{ RUST_SRC / "std/src/io" }} "std/src/"
|
||||
@just cp_std "io"
|
||||
|
||||
@# Complete
|
||||
ln -fs {{ RUST_SRC / "std/src/net" }} "std/src/"
|
||||
@just cp_std "net"
|
||||
|
||||
@# Complete
|
||||
ln -fs {{ RUST_SRC / "std/src/num" }} "std/src/"
|
||||
@just cp_std "num"
|
||||
|
||||
@# Complete
|
||||
@just cp_std "os/raw/mod.rs"
|
||||
@just cp_std "os/raw/tests.rs"
|
||||
@just cp_std "os/mod.rs"
|
||||
|
||||
@# Complete
|
||||
ln -fs {{ RUST_SRC / "std/src/prelude" }} "std/src/"
|
||||
@just cp_std "prelude"
|
||||
|
||||
@# Complete
|
||||
ln -fs {{ RUST_SRC / "std/src/process" }} "std/src/"
|
||||
@just cp_std "process"
|
||||
|
||||
@# Complete
|
||||
ln -fs {{ RUST_SRC / "std/src/sync" }} "std/src/"
|
||||
@just cp_std "sync"
|
||||
|
||||
@# Complete
|
||||
@just cp_std "sys/alloc/mod.rs"
|
||||
|
||||
@just cp_std "sys/args/mod.rs"
|
||||
@just real_cp_std "sys/args/mod.rs"
|
||||
@just cp_std "sys/args/unsupported.rs"
|
||||
|
||||
@just cp_std "sys/env/mod.rs"
|
||||
@@ -124,7 +118,7 @@ setup-std:
|
||||
@just cp_std "sys/helpers/wstr.rs"
|
||||
|
||||
@just cp_std "sys/io/error/generic.rs"
|
||||
@just cp_std "sys/io/error/mod.rs"
|
||||
@just real_cp_std "sys/io/error/mod.rs"
|
||||
@just cp_std "sys/io/io_slice/unsupported.rs"
|
||||
@just cp_std "sys/io/is_terminal/unsupported.rs"
|
||||
@just cp_std "sys/io/kernel_copy/mod.rs"
|
||||
@@ -140,7 +134,7 @@ setup-std:
|
||||
@just cp_std "sys/os_str/bytes.rs"
|
||||
@just cp_std "sys/os_str/mod.rs"
|
||||
|
||||
@just cp_std "sys/pal/mod.rs"
|
||||
@just real_cp_std "sys/pal/mod.rs"
|
||||
@just cp_std "sys/pal/unsupported/mod.rs"
|
||||
@just cp_std "sys/pal/unsupported/common.rs"
|
||||
@just cp_std "sys/pal/unsupported/os.rs"
|
||||
@@ -162,7 +156,7 @@ setup-std:
|
||||
@just cp_std "sys/process/env.rs"
|
||||
@just cp_std "sys/process/unsupported.rs"
|
||||
|
||||
@just cp_std "sys/random/mod.rs"
|
||||
@just real_cp_std "sys/random/mod.rs"
|
||||
@just cp_std "sys/random/unsupported.rs"
|
||||
|
||||
@just cp_std "sys/stdio/mod.rs"
|
||||
@@ -184,7 +178,7 @@ setup-std:
|
||||
@just cp_std "sys/thread/mod.rs"
|
||||
@just cp_std "sys/thread/unsupported.rs"
|
||||
|
||||
@just cp_std "sys/thread_local/mod.rs"
|
||||
@just real_cp_std "sys/thread_local/mod.rs"
|
||||
@just cp_std "sys/thread_local/no_threads.rs"
|
||||
@just cp_std "sys/thread_local/os.rs"
|
||||
|
||||
@@ -198,8 +192,115 @@ setup-std:
|
||||
@just cp_std "sys/exit.rs"
|
||||
@just cp_std "sys/mod.rs"
|
||||
|
||||
@# Complete
|
||||
ln -fs {{ RUST_SRC / "std/src/thread" }} "std/src/"
|
||||
@just cp_std "thread"
|
||||
|
||||
STD_FILES := "alloc.rs \
|
||||
ascii.rs \
|
||||
backtrace.rs \
|
||||
bstr.rs \
|
||||
env.rs \
|
||||
error.rs \
|
||||
fs.rs \
|
||||
keyword_docs.rs \
|
||||
lib.rs \
|
||||
macros.rs \
|
||||
panic.rs \
|
||||
panicking.rs \
|
||||
pat.rs \
|
||||
path.rs \
|
||||
process.rs \
|
||||
random.rs \
|
||||
rt.rs \
|
||||
tests_helpers.rs \
|
||||
time.rs \
|
||||
backtrace \
|
||||
collections \
|
||||
ffi \
|
||||
fs \
|
||||
hash \
|
||||
io \
|
||||
net \
|
||||
num \
|
||||
os/raw/mod.rs \
|
||||
os/raw/tests.rs \
|
||||
os/mod.rs \
|
||||
prelude \
|
||||
process \
|
||||
sync \
|
||||
sys/alloc/mod.rs \
|
||||
sys/args/mod.rs \
|
||||
sys/args/unsupported.rs \
|
||||
sys/env/mod.rs \
|
||||
sys/env/common.rs \
|
||||
sys/env/unsupported.rs \
|
||||
sys/fd/mod.rs \
|
||||
sys/fs/mod.rs \
|
||||
sys/fs/common.rs \
|
||||
sys/fs/unsupported.rs \
|
||||
sys/helpers/mod.rs \
|
||||
sys/helpers/small_c_string.rs \
|
||||
sys/helpers/tests.rs \
|
||||
sys/helpers/wstr.rs \
|
||||
sys/io/error/generic.rs \
|
||||
sys/io/error/mod.rs \
|
||||
sys/io/io_slice/unsupported.rs \
|
||||
sys/io/is_terminal/unsupported.rs \
|
||||
sys/io/kernel_copy/mod.rs \
|
||||
sys/io/mod.rs \
|
||||
sys/net/connection/mod.rs \
|
||||
sys/net/connection/unsupported.rs \
|
||||
sys/net/hostname/mod.rs \
|
||||
sys/net/hostname/unsupported.rs \
|
||||
sys/net/mod.rs \
|
||||
sys/os_str/bytes/tests.rs \
|
||||
sys/os_str/bytes.rs \
|
||||
sys/os_str/mod.rs \
|
||||
sys/pal/mod.rs \
|
||||
sys/pal/unsupported/mod.rs \
|
||||
sys/pal/unsupported/common.rs \
|
||||
sys/pal/unsupported/os.rs \
|
||||
sys/path/mod.rs \
|
||||
sys/path/unix.rs \
|
||||
sys/personality/dwarf/eh.rs \
|
||||
sys/personality/dwarf/mod.rs \
|
||||
sys/personality/dwarf/tests.rs \
|
||||
sys/personality/mod.rs \
|
||||
sys/pipe/mod.rs \
|
||||
sys/pipe/unsupported.rs \
|
||||
sys/platform_version/mod.rs \
|
||||
sys/process/mod.rs \
|
||||
sys/process/env.rs \
|
||||
sys/process/unsupported.rs \
|
||||
sys/random/mod.rs \
|
||||
sys/random/unsupported.rs \
|
||||
sys/stdio/mod.rs \
|
||||
sys/stdio/unsupported.rs \
|
||||
sys/sync/condvar/mod.rs \
|
||||
sys/sync/condvar/no_threads.rs \
|
||||
sys/sync/mutex/mod.rs \
|
||||
sys/sync/mutex/no_threads.rs \
|
||||
sys/sync/once/mod.rs \
|
||||
sys/sync/once/no_threads.rs \
|
||||
sys/sync/rwlock/mod.rs \
|
||||
sys/sync/rwlock/no_threads.rs \
|
||||
sys/sync/thread_parking/mod.rs \
|
||||
sys/sync/thread_parking/unsupported.rs \
|
||||
sys/sync/mod.rs \
|
||||
sys/sync/once_box.rs \
|
||||
sys/thread/mod.rs \
|
||||
sys/thread/unsupported.rs \
|
||||
sys/thread_local/mod.rs \
|
||||
sys/thread_local/no_threads.rs \
|
||||
sys/thread_local/os.rs \
|
||||
sys/time/mod.rs \
|
||||
sys/time/unsupported.rs \
|
||||
sys/backtrace.rs \
|
||||
sys/cmath.rs \
|
||||
sys/configure_builtins.rs \
|
||||
sys/env_consts.rs \
|
||||
sys/exit.rs \
|
||||
sys/mod.rs \
|
||||
thread"
|
||||
|
||||
build-sysroot: update-std
|
||||
RUSTFLAGS="-Zforce-unstable-if-unmarked -C relocation-model=pic -C link-arg=-pie" cargo build --target ../riscv64.json
|
||||
@@ -208,35 +309,11 @@ build-sysroot: update-std
|
||||
cp target/riscv64/debug/deps/*.rlib ../sysroot/lib/rustlib/riscv64/lib
|
||||
|
||||
clean:
|
||||
cargo clean
|
||||
# cargo clean
|
||||
rm ../sysroot/lib/rustlib/riscv64/lib/* -rf
|
||||
|
||||
rm -f alloc
|
||||
rm -f compiler-builtins
|
||||
rm -f panic_abort
|
||||
rm -f panic_unwind
|
||||
rm -f windows_link
|
||||
rm -f portable-simd
|
||||
rm -f unwind
|
||||
rm -f std_detect
|
||||
rm -f stdarch
|
||||
rm -f rustc-std-workspace-alloc
|
||||
rm -f rustc-std-workspace-core
|
||||
rm -f proc_macro
|
||||
rm -f profiler_builtins
|
||||
rm -f test
|
||||
for file in {{ STD_FILES }}; do \
|
||||
rm -rf std/src/$file; \
|
||||
done
|
||||
|
||||
rm -rf std/src/backtrace
|
||||
rm -rf std/src/thread
|
||||
rm -rf std/src/sync
|
||||
rm -rf std/src/collections
|
||||
rm -rf std/src/ffi
|
||||
rm -rf std/src/fs
|
||||
rm -rf std/src/num
|
||||
rm -rf std/src/net
|
||||
rm -rf std/src/io
|
||||
rm -rf std/src/hash
|
||||
rm -rf std/src/prelude
|
||||
rm -rf std/src/process
|
||||
|
||||
# rm -f Cargo.toml
|
||||
rm -rf std/build.rs
|
||||
|
||||
107
library/std/.gitignore
vendored
Normal file
107
library/std/.gitignore
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
src/alloc.rs
|
||||
src/ascii.rs
|
||||
src/backtrace.rs
|
||||
src/bstr.rs
|
||||
src/env.rs
|
||||
src/error.rs
|
||||
src/fs.rs
|
||||
src/keyword_docs.rs
|
||||
src/lib.rs
|
||||
src/macros.rs
|
||||
src/panic.rs
|
||||
src/panicking.rs
|
||||
src/pat.rs
|
||||
src/path.rs
|
||||
src/process.rs
|
||||
src/random.rs
|
||||
src/rt.rs
|
||||
src/tests_helpers.rs
|
||||
src/time.rs
|
||||
src/backtrace
|
||||
src/collections
|
||||
src/ffi
|
||||
src/fs
|
||||
src/hash
|
||||
src/io
|
||||
src/net
|
||||
src/num
|
||||
src/os/raw/mod.rs
|
||||
src/os/raw/tests.rs
|
||||
src/os/mod.rs
|
||||
src/prelude
|
||||
src/process
|
||||
src/sync
|
||||
src/sys/alloc/mod.rs
|
||||
src/sys/args/mod.rs
|
||||
src/sys/args/unsupported.rs
|
||||
src/sys/env/mod.rs
|
||||
src/sys/env/common.rs
|
||||
src/sys/env/unsupported.rs
|
||||
src/sys/fd/mod.rs
|
||||
src/sys/fs/mod.rs
|
||||
src/sys/fs/common.rs
|
||||
src/sys/fs/unsupported.rs
|
||||
src/sys/helpers/mod.rs
|
||||
src/sys/helpers/small_c_string.rs
|
||||
src/sys/helpers/tests.rs
|
||||
src/sys/helpers/wstr.rs
|
||||
src/sys/io/error/generic.rs
|
||||
src/sys/io/error/mod.rs
|
||||
src/sys/io/io_slice/unsupported.rs
|
||||
src/sys/io/is_terminal/unsupported.rs
|
||||
src/sys/io/kernel_copy/mod.rs
|
||||
src/sys/io/mod.rs
|
||||
src/sys/net/connection/mod.rs
|
||||
src/sys/net/connection/unsupported.rs
|
||||
src/sys/net/hostname/mod.rs
|
||||
src/sys/net/hostname/unsupported.rs
|
||||
src/sys/net/mod.rs
|
||||
src/sys/os_str/bytes/tests.rs
|
||||
src/sys/os_str/bytes.rs
|
||||
src/sys/os_str/mod.rs
|
||||
src/sys/pal/mod.rs
|
||||
src/sys/pal/unsupported/mod.rs
|
||||
src/sys/pal/unsupported/common.rs
|
||||
src/sys/pal/unsupported/os.rs
|
||||
src/sys/path/mod.rs
|
||||
src/sys/path/unix.rs
|
||||
src/sys/personality/dwarf/eh.rs
|
||||
src/sys/personality/dwarf/mod.rs
|
||||
src/sys/personality/dwarf/tests.rs
|
||||
src/sys/personality/mod.rs
|
||||
src/sys/pipe/mod.rs
|
||||
src/sys/pipe/unsupported.rs
|
||||
src/sys/platform_version/mod.rs
|
||||
src/sys/process/mod.rs
|
||||
src/sys/process/env.rs
|
||||
src/sys/process/unsupported.rs
|
||||
src/sys/random/mod.rs
|
||||
src/sys/random/unsupported.rs
|
||||
src/sys/stdio/mod.rs
|
||||
src/sys/stdio/unsupported.rs
|
||||
src/sys/sync/condvar/mod.rs
|
||||
src/sys/sync/condvar/no_threads.rs
|
||||
src/sys/sync/mutex/mod.rs
|
||||
src/sys/sync/mutex/no_threads.rs
|
||||
src/sys/sync/once/mod.rs
|
||||
src/sys/sync/once/no_threads.rs
|
||||
src/sys/sync/rwlock/mod.rs
|
||||
src/sys/sync/rwlock/no_threads.rs
|
||||
src/sys/sync/thread_parking/mod.rs
|
||||
src/sys/sync/thread_parking/unsupported.rs
|
||||
src/sys/sync/mod.rs
|
||||
src/sys/sync/once_box.rs
|
||||
src/sys/thread/mod.rs
|
||||
src/sys/thread/unsupported.rs
|
||||
src/sys/thread_local/mod.rs
|
||||
src/sys/thread_local/no_threads.rs
|
||||
src/sys/thread_local/os.rs
|
||||
src/sys/time/mod.rs
|
||||
src/sys/time/unsupported.rs
|
||||
src/sys/backtrace.rs
|
||||
src/sys/cmath.rs
|
||||
src/sys/configure_builtins.rs
|
||||
src/sys/env_consts.rs
|
||||
src/sys/exit.rs
|
||||
src/sys/mod.rs
|
||||
src/thread
|
||||
@@ -1,8 +1,107 @@
|
||||
use std::env;
|
||||
|
||||
pub fn main() {
|
||||
println!(
|
||||
"cargo:rustc-env=STD_ENV_ARCH={}",
|
||||
env::var("CARGO_CFG_TARGET_ARCH").unwrap()
|
||||
);
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").expect("CARGO_CFG_TARGET_ARCH was not set");
|
||||
let target_os = env::var("CARGO_CFG_TARGET_OS").expect("CARGO_CFG_TARGET_OS was not set");
|
||||
let target_vendor =
|
||||
env::var("CARGO_CFG_TARGET_VENDOR").expect("CARGO_CFG_TARGET_VENDOR was not set");
|
||||
let target_env = env::var("CARGO_CFG_TARGET_ENV").expect("CARGO_CFG_TARGET_ENV was not set");
|
||||
|
||||
println!("cargo:rustc-check-cfg=cfg(netbsd10)");
|
||||
if target_os == "netbsd" && env::var("RUSTC_STD_NETBSD10").is_ok() {
|
||||
println!("cargo:rustc-cfg=netbsd10");
|
||||
}
|
||||
|
||||
// Needed for `#![doc(auto_cfg(hide(no_global_oom_handling)))]` attribute.
|
||||
println!("cargo::rustc-check-cfg=cfg(no_global_oom_handling)");
|
||||
|
||||
println!("cargo:rustc-check-cfg=cfg(restricted_std)");
|
||||
if target_os == "linux"
|
||||
|| target_os == "android"
|
||||
|| target_os == "netbsd"
|
||||
|| target_os == "dragonfly"
|
||||
|| target_os == "openbsd"
|
||||
|| target_os == "freebsd"
|
||||
|| target_os == "solaris"
|
||||
|| target_os == "illumos"
|
||||
|| target_os == "macos"
|
||||
|| target_os == "ios"
|
||||
|| target_os == "tvos"
|
||||
|| target_os == "watchos"
|
||||
|| target_os == "visionos"
|
||||
|| target_os == "windows"
|
||||
|| target_os == "fuchsia"
|
||||
|| (target_vendor == "fortanix" && target_env == "sgx")
|
||||
|| target_os == "motor"
|
||||
|| target_os == "hermit"
|
||||
|| target_os == "trusty"
|
||||
|| target_os == "l4re"
|
||||
|| target_os == "redox"
|
||||
|| target_os == "haiku"
|
||||
|| target_os == "vxworks"
|
||||
|| target_arch == "wasm32"
|
||||
|| target_arch == "wasm64"
|
||||
|| target_os == "espidf"
|
||||
|| target_os.starts_with("solid")
|
||||
|| (target_vendor == "nintendo" && target_env == "newlib")
|
||||
|| target_os == "vita"
|
||||
|| target_os == "aix"
|
||||
|| target_os == "nto"
|
||||
|| target_os == "xous"
|
||||
|| target_os == "hurd"
|
||||
|| target_os == "uefi"
|
||||
|| target_os == "teeos"
|
||||
|| target_os == "zkvm"
|
||||
|| target_os == "rtems"
|
||||
|| target_os == "nuttx"
|
||||
|| target_os == "cygwin"
|
||||
|| target_os == "vexos"
|
||||
|| target_os == "survos"
|
||||
|
||||
// See src/bootstrap/src/core/build_steps/synthetic_targets.rs
|
||||
|| env::var("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET").is_ok()
|
||||
{
|
||||
// These platforms don't have any special requirements.
|
||||
} else {
|
||||
// This is for Cargo's build-std support, to mark std as unstable for
|
||||
// typically no_std platforms.
|
||||
// This covers:
|
||||
// - os=none ("bare metal" targets)
|
||||
// - mipsel-sony-psp
|
||||
// - nvptx64-nvidia-cuda
|
||||
// - arch=avr
|
||||
// - JSON targets
|
||||
// - Any new targets that have not been explicitly added above.
|
||||
println!("cargo:rustc-cfg=restricted_std");
|
||||
}
|
||||
|
||||
println!("cargo:rustc-check-cfg=cfg(backtrace_in_libstd)");
|
||||
println!("cargo:rustc-cfg=backtrace_in_libstd");
|
||||
|
||||
println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap());
|
||||
|
||||
println!("cargo:rustc-check-cfg=cfg(vxworks_lt_25_09)");
|
||||
|
||||
if target_os == "vxworks" {
|
||||
match vxworks_version_code() {
|
||||
Some((major, minor)) if (major, minor) < (25, 9) => {
|
||||
println!("cargo:rustc-cfg=vxworks_lt_25_09");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve the VxWorks release version from the environment variable set by the VxWorks build
|
||||
/// environment, in `(minor, patch)` form.
|
||||
fn vxworks_version_code() -> Option<(u32, u32)> {
|
||||
let version = env::var("WIND_RELEASE_ID").ok()?;
|
||||
|
||||
let mut pieces = version.trim().split(['.']);
|
||||
|
||||
let major: u32 = pieces.next().and_then(|x| x.parse().ok()).unwrap_or(0);
|
||||
let minor: u32 = pieces.next().and_then(|x| x.parse().ok()).unwrap_or(0);
|
||||
|
||||
Some((major, minor))
|
||||
}
|
||||
|
||||
@@ -1,490 +0,0 @@
|
||||
//! Memory allocation APIs.
|
||||
//!
|
||||
//! In a given program, the standard library has one “global” memory allocator
|
||||
//! that is used for example by `Box<T>` and `Vec<T>`.
|
||||
//!
|
||||
//! Currently the default global allocator is unspecified. Libraries, however,
|
||||
//! like `cdylib`s and `staticlib`s are guaranteed to use the [`System`] by
|
||||
//! default.
|
||||
//!
|
||||
//! # The `#[global_allocator]` attribute
|
||||
//!
|
||||
//! This attribute allows configuring the choice of global allocator.
|
||||
//! You can use this to implement a completely custom global allocator
|
||||
//! to route all[^system-alloc] default allocation requests to a custom object.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use std::alloc::{GlobalAlloc, System, Layout};
|
||||
//!
|
||||
//! struct MyAllocator;
|
||||
//!
|
||||
//! unsafe impl GlobalAlloc for MyAllocator {
|
||||
//! unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
//! unsafe { System.alloc(layout) }
|
||||
//! }
|
||||
//!
|
||||
//! unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||
//! unsafe { System.dealloc(ptr, layout) }
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! #[global_allocator]
|
||||
//! static GLOBAL: MyAllocator = MyAllocator;
|
||||
//!
|
||||
//! fn main() {
|
||||
//! // This `Vec` will allocate memory through `GLOBAL` above
|
||||
//! let mut v = Vec::new();
|
||||
//! v.push(1);
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! The attribute is used on a `static` item whose type implements the
|
||||
//! [`GlobalAlloc`] trait. This type can be provided by an external library:
|
||||
//!
|
||||
//! ```rust,ignore (demonstrates crates.io usage)
|
||||
//! use jemallocator::Jemalloc;
|
||||
//!
|
||||
//! #[global_allocator]
|
||||
//! static GLOBAL: Jemalloc = Jemalloc;
|
||||
//!
|
||||
//! fn main() {}
|
||||
//! ```
|
||||
//!
|
||||
//! The `#[global_allocator]` can only be used once in a crate
|
||||
//! or its recursive dependencies.
|
||||
//!
|
||||
//! [^system-alloc]: Note that the Rust standard library internals may still
|
||||
//! directly call [`System`] when necessary (for example for the runtime
|
||||
//! support typically required to implement a global allocator, see [re-entrance] on [`GlobalAlloc`]
|
||||
//! for more details).
|
||||
//!
|
||||
//! [re-entrance]: trait.GlobalAlloc.html#re-entrance
|
||||
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
#![stable(feature = "alloc_module", since = "1.28.0")]
|
||||
|
||||
use core::ptr::NonNull;
|
||||
use core::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
|
||||
use core::{hint, mem, ptr};
|
||||
|
||||
#[stable(feature = "alloc_module", since = "1.28.0")]
|
||||
#[doc(inline)]
|
||||
pub use alloc_crate::alloc::*;
|
||||
|
||||
/// The default memory allocator provided by the operating system.
|
||||
///
|
||||
/// This is based on `malloc` on Unix platforms and `HeapAlloc` on Windows,
|
||||
/// plus related functions. However, it is not valid to mix use of the backing
|
||||
/// system allocator with `System`, as this implementation may include extra
|
||||
/// work, such as to serve alignment requests greater than the alignment
|
||||
/// provided directly by the backing system allocator.
|
||||
///
|
||||
/// This type implements the [`GlobalAlloc`] trait. Currently the default
|
||||
/// global allocator is unspecified. Libraries, however, like `cdylib`s and
|
||||
/// `staticlib`s are guaranteed to use the [`System`] by default and as such
|
||||
/// work as if they had this definition:
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::alloc::System;
|
||||
///
|
||||
/// #[global_allocator]
|
||||
/// static A: System = System;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let a = Box::new(4); // Allocates from the system allocator.
|
||||
/// println!("{a}");
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// You can also define your own wrapper around `System` if you'd like, such as
|
||||
/// keeping track of the number of all bytes allocated:
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::alloc::{System, GlobalAlloc, Layout};
|
||||
/// use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};
|
||||
///
|
||||
/// struct Counter;
|
||||
///
|
||||
/// static ALLOCATED: AtomicUsize = AtomicUsize::new(0);
|
||||
///
|
||||
/// unsafe impl GlobalAlloc for Counter {
|
||||
/// unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
/// let ret = unsafe { System.alloc(layout) };
|
||||
/// if !ret.is_null() {
|
||||
/// ALLOCATED.fetch_add(layout.size(), Relaxed);
|
||||
/// }
|
||||
/// ret
|
||||
/// }
|
||||
///
|
||||
/// unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||
/// unsafe { System.dealloc(ptr, layout); }
|
||||
/// ALLOCATED.fetch_sub(layout.size(), Relaxed);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// #[global_allocator]
|
||||
/// static A: Counter = Counter;
|
||||
///
|
||||
/// fn main() {
|
||||
/// println!("allocated bytes before main: {}", ALLOCATED.load(Relaxed));
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// It can also be used directly to allocate memory independently of whatever
|
||||
/// global allocator has been selected for a Rust program. For example if a Rust
|
||||
/// program opts in to using jemalloc as the global allocator, `System` will
|
||||
/// still allocate memory using `malloc` and `HeapAlloc`.
|
||||
#[stable(feature = "alloc_system_type", since = "1.28.0")]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub struct System;
|
||||
|
||||
impl System {
|
||||
#[inline]
|
||||
fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError> {
|
||||
match layout.size() {
|
||||
0 => Ok(NonNull::slice_from_raw_parts(layout.dangling_ptr(), 0)),
|
||||
// SAFETY: `layout` is non-zero in size,
|
||||
size => unsafe {
|
||||
let raw_ptr = if zeroed {
|
||||
GlobalAlloc::alloc_zeroed(self, layout)
|
||||
} else {
|
||||
GlobalAlloc::alloc(self, layout)
|
||||
};
|
||||
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
|
||||
Ok(NonNull::slice_from_raw_parts(ptr, size))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: Same as `Allocator::grow`
|
||||
#[inline]
|
||||
unsafe fn grow_impl(
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
zeroed: bool,
|
||||
) -> Result<NonNull<[u8]>, AllocError> {
|
||||
debug_assert!(
|
||||
new_layout.size() >= old_layout.size(),
|
||||
"`new_layout.size()` must be greater than or equal to `old_layout.size()`"
|
||||
);
|
||||
|
||||
match old_layout.size() {
|
||||
0 => self.alloc_impl(new_layout, zeroed),
|
||||
|
||||
// SAFETY: `new_size` is non-zero as `new_size` is greater than or equal to `old_size`
|
||||
// as required by safety conditions and the `old_size == 0` case was handled in the
|
||||
// previous match arm. Other conditions must be upheld by the caller
|
||||
old_size if old_layout.align() == new_layout.align() => unsafe {
|
||||
let new_size = new_layout.size();
|
||||
|
||||
// `realloc` probably checks for `new_size >= old_layout.size()` or something similar.
|
||||
hint::assert_unchecked(new_size >= old_layout.size());
|
||||
|
||||
let raw_ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), old_layout, new_size);
|
||||
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
|
||||
if zeroed {
|
||||
raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
|
||||
}
|
||||
Ok(NonNull::slice_from_raw_parts(ptr, new_size))
|
||||
},
|
||||
|
||||
// SAFETY: because `new_layout.size()` must be greater than or equal to `old_size`,
|
||||
// both the old and new memory allocation are valid for reads and writes for `old_size`
|
||||
// bytes. Also, because the old allocation wasn't yet deallocated, it cannot overlap
|
||||
// `new_ptr`. Thus, the call to `copy_nonoverlapping` is safe. The safety contract
|
||||
// for `dealloc` must be upheld by the caller.
|
||||
old_size => unsafe {
|
||||
let new_ptr = self.alloc_impl(new_layout, zeroed)?;
|
||||
ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), old_size);
|
||||
Allocator::deallocate(self, ptr, old_layout);
|
||||
Ok(new_ptr)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The Allocator impl checks the layout size to be non-zero and forwards to the GlobalAlloc impl,
|
||||
// which is in `std::sys::*::alloc`.
|
||||
#[unstable(feature = "allocator_api", issue = "32838")]
|
||||
unsafe impl Allocator for System {
|
||||
#[inline]
|
||||
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
|
||||
self.alloc_impl(layout, false)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
|
||||
self.alloc_impl(layout, true)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
|
||||
if layout.size() != 0 {
|
||||
// SAFETY: `layout` is non-zero in size,
|
||||
// other conditions must be upheld by the caller
|
||||
unsafe { GlobalAlloc::dealloc(self, ptr.as_ptr(), layout) }
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn grow(
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
) -> Result<NonNull<[u8]>, AllocError> {
|
||||
// SAFETY: all conditions must be upheld by the caller
|
||||
unsafe { self.grow_impl(ptr, old_layout, new_layout, false) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn grow_zeroed(
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
) -> Result<NonNull<[u8]>, AllocError> {
|
||||
// SAFETY: all conditions must be upheld by the caller
|
||||
unsafe { self.grow_impl(ptr, old_layout, new_layout, true) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn shrink(
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
) -> Result<NonNull<[u8]>, AllocError> {
|
||||
debug_assert!(
|
||||
new_layout.size() <= old_layout.size(),
|
||||
"`new_layout.size()` must be smaller than or equal to `old_layout.size()`"
|
||||
);
|
||||
|
||||
match new_layout.size() {
|
||||
// SAFETY: conditions must be upheld by the caller
|
||||
0 => unsafe {
|
||||
Allocator::deallocate(self, ptr, old_layout);
|
||||
Ok(NonNull::slice_from_raw_parts(new_layout.dangling_ptr(), 0))
|
||||
},
|
||||
|
||||
// SAFETY: `new_size` is non-zero. Other conditions must be upheld by the caller
|
||||
new_size if old_layout.align() == new_layout.align() => unsafe {
|
||||
// `realloc` probably checks for `new_size <= old_layout.size()` or something similar.
|
||||
hint::assert_unchecked(new_size <= old_layout.size());
|
||||
|
||||
let raw_ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), old_layout, new_size);
|
||||
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
|
||||
Ok(NonNull::slice_from_raw_parts(ptr, new_size))
|
||||
},
|
||||
|
||||
// SAFETY: because `new_size` must be smaller than or equal to `old_layout.size()`,
|
||||
// both the old and new memory allocation are valid for reads and writes for `new_size`
|
||||
// bytes. Also, because the old allocation wasn't yet deallocated, it cannot overlap
|
||||
// `new_ptr`. Thus, the call to `copy_nonoverlapping` is safe. The safety contract
|
||||
// for `dealloc` must be upheld by the caller.
|
||||
new_size => unsafe {
|
||||
let new_ptr = Allocator::allocate(self, new_layout)?;
|
||||
ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), new_size);
|
||||
Allocator::deallocate(self, ptr, old_layout);
|
||||
Ok(new_ptr)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
|
||||
|
||||
/// Registers a custom allocation error hook, replacing any that was previously registered.
|
||||
///
|
||||
/// The allocation error hook is invoked when an infallible memory allocation fails — that is,
|
||||
/// as a consequence of calling [`handle_alloc_error`] — before the runtime aborts.
|
||||
///
|
||||
/// The allocation error hook is a global resource. [`take_alloc_error_hook`] may be used to
|
||||
/// retrieve a previously registered hook and wrap or discard it.
|
||||
///
|
||||
/// # What the provided `hook` function should expect
|
||||
///
|
||||
/// The hook function is provided with a [`Layout`] struct which contains information
|
||||
/// about the allocation that failed.
|
||||
///
|
||||
/// The hook function may choose to panic or abort; in the event that it returns normally, this
|
||||
/// will cause an immediate abort.
|
||||
///
|
||||
/// Since [`take_alloc_error_hook`] is a safe function that allows retrieving the hook, the hook
|
||||
/// function must be _sound_ to call even if no memory allocations were attempted.
|
||||
///
|
||||
/// # The default hook
|
||||
///
|
||||
/// The default hook, used if [`set_alloc_error_hook`] is never called, prints a message to
|
||||
/// standard error (and then returns, causing the runtime to abort the process).
|
||||
/// Compiler options may cause it to panic instead, and the default behavior may be changed
|
||||
/// to panicking in future versions of Rust.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(alloc_error_hook)]
|
||||
///
|
||||
/// use std::alloc::{Layout, set_alloc_error_hook};
|
||||
///
|
||||
/// fn custom_alloc_error_hook(layout: Layout) {
|
||||
/// panic!("memory allocation of {} bytes failed", layout.size());
|
||||
/// }
|
||||
///
|
||||
/// set_alloc_error_hook(custom_alloc_error_hook);
|
||||
/// ```
|
||||
#[unstable(feature = "alloc_error_hook", issue = "51245")]
|
||||
pub fn set_alloc_error_hook(hook: fn(Layout)) {
|
||||
HOOK.store(hook as *mut (), Ordering::Release);
|
||||
}
|
||||
|
||||
/// Unregisters the current allocation error hook, returning it.
|
||||
///
|
||||
/// *See also the function [`set_alloc_error_hook`].*
|
||||
///
|
||||
/// If no custom hook is registered, the default hook will be returned.
|
||||
#[unstable(feature = "alloc_error_hook", issue = "51245")]
|
||||
pub fn take_alloc_error_hook() -> fn(Layout) {
|
||||
let hook = HOOK.swap(ptr::null_mut(), Ordering::Acquire);
|
||||
if hook.is_null() { default_alloc_error_hook } else { unsafe { mem::transmute(hook) } }
|
||||
}
|
||||
|
||||
#[optimize(size)]
|
||||
fn default_alloc_error_hook(layout: Layout) {
|
||||
if cfg!(panic = "immediate-abort") {
|
||||
return;
|
||||
}
|
||||
|
||||
// This is the default path taken on OOM, and the only path taken on stable with std.
|
||||
// Crucially, it does *not* call any user-defined code, and therefore users do not have to
|
||||
// worry about allocation failure causing reentrancy issues. That makes it different from
|
||||
// the default `__rdl_alloc_error_handler` defined in alloc (i.e., the default alloc error
|
||||
// handler that is called when there is no `#[alloc_error_handler]`), which triggers a
|
||||
// regular panic and thus can invoke a user-defined panic hook, executing arbitrary
|
||||
// user-defined code.
|
||||
|
||||
static PREV_ALLOC_FAILURE: AtomicBool = AtomicBool::new(false);
|
||||
if PREV_ALLOC_FAILURE.swap(true, Ordering::Relaxed) {
|
||||
// Don't try to print a backtrace if a previous alloc error happened. This likely means
|
||||
// there is not enough memory to print a backtrace, although it could also mean that two
|
||||
// threads concurrently run out of memory.
|
||||
rtprintpanic!(
|
||||
"memory allocation of {} bytes failed\nskipping backtrace printing to avoid potential recursion\n",
|
||||
layout.size()
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
rtprintpanic!("memory allocation of {} bytes failed\n", layout.size());
|
||||
}
|
||||
|
||||
let Some(mut out) = crate::sys::stdio::panic_output() else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Use a lock to prevent mixed output in multithreading context.
|
||||
// Some platforms also require it when printing a backtrace, like `SymFromAddr` on Windows.
|
||||
// Make sure to not take this lock until after checking PREV_ALLOC_FAILURE to avoid deadlocks
|
||||
// when there is too little memory to print a backtrace.
|
||||
let mut lock = crate::sys::backtrace::lock();
|
||||
|
||||
match crate::panic::get_backtrace_style() {
|
||||
Some(crate::panic::BacktraceStyle::Short) => {
|
||||
drop(lock.print(&mut out, crate::backtrace_rs::PrintFmt::Short))
|
||||
}
|
||||
Some(crate::panic::BacktraceStyle::Full) => {
|
||||
drop(lock.print(&mut out, crate::backtrace_rs::PrintFmt::Full))
|
||||
}
|
||||
Some(crate::panic::BacktraceStyle::Off) => {
|
||||
use crate::io::Write;
|
||||
let _ = writeln!(
|
||||
out,
|
||||
"note: run with `RUST_BACKTRACE=1` environment variable to display a \
|
||||
backtrace"
|
||||
);
|
||||
if cfg!(miri) {
|
||||
let _ = writeln!(
|
||||
out,
|
||||
"note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` \
|
||||
for the environment variable to have an effect"
|
||||
);
|
||||
}
|
||||
}
|
||||
// If backtraces aren't supported or are forced-off, do nothing.
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[doc(hidden)]
|
||||
#[alloc_error_handler]
|
||||
#[unstable(feature = "alloc_internals", issue = "none")]
|
||||
pub fn rust_oom(layout: Layout) -> ! {
|
||||
crate::sys::backtrace::__rust_end_short_backtrace(|| {
|
||||
let hook = HOOK.load(Ordering::Acquire);
|
||||
let hook: fn(Layout) =
|
||||
if hook.is_null() { default_alloc_error_hook } else { unsafe { mem::transmute(hook) } };
|
||||
hook(layout);
|
||||
crate::process::abort()
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[doc(hidden)]
|
||||
#[allow(unused_attributes)]
|
||||
#[unstable(feature = "alloc_internals", issue = "none")]
|
||||
pub mod __default_lib_allocator {
|
||||
use super::{GlobalAlloc, Layout, System};
|
||||
// These magic symbol names are used as a fallback for implementing the
|
||||
// `__rust_alloc` etc symbols (see `src/liballoc/alloc.rs`) when there is
|
||||
// no `#[global_allocator]` attribute.
|
||||
|
||||
// for symbol names src/librustc_ast/expand/allocator.rs
|
||||
// for signatures src/librustc_allocator/lib.rs
|
||||
|
||||
// linkage directives are provided as part of the current compiler allocator
|
||||
// ABI
|
||||
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern "C" fn __rdl_alloc(size: usize, align: usize) -> *mut u8 {
|
||||
// SAFETY: see the guarantees expected by `Layout::from_size_align` and
|
||||
// `GlobalAlloc::alloc`.
|
||||
unsafe {
|
||||
let layout = Layout::from_size_align_unchecked(size, align);
|
||||
System.alloc(layout)
|
||||
}
|
||||
}
|
||||
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern "C" fn __rdl_dealloc(ptr: *mut u8, size: usize, align: usize) {
|
||||
// SAFETY: see the guarantees expected by `Layout::from_size_align` and
|
||||
// `GlobalAlloc::dealloc`.
|
||||
unsafe { System.dealloc(ptr, Layout::from_size_align_unchecked(size, align)) }
|
||||
}
|
||||
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern "C" fn __rdl_realloc(
|
||||
ptr: *mut u8,
|
||||
old_size: usize,
|
||||
align: usize,
|
||||
new_size: usize,
|
||||
) -> *mut u8 {
|
||||
// SAFETY: see the guarantees expected by `Layout::from_size_align` and
|
||||
// `GlobalAlloc::realloc`.
|
||||
unsafe {
|
||||
let old_layout = Layout::from_size_align_unchecked(old_size, align);
|
||||
System.realloc(ptr, old_layout, new_size)
|
||||
}
|
||||
}
|
||||
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern "C" fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
|
||||
// SAFETY: see the guarantees expected by `Layout::from_size_align` and
|
||||
// `GlobalAlloc::alloc_zeroed`.
|
||||
unsafe {
|
||||
let layout = Layout::from_size_align_unchecked(size, align);
|
||||
System.alloc_zeroed(layout)
|
||||
}
|
||||
}
|
||||
}
|
||||
1
library/std/src/alloc.rs
Symbolic link
1
library/std/src/alloc.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/alloc.rs
|
||||
@@ -1,210 +0,0 @@
|
||||
//! Operations on ASCII strings and characters.
|
||||
//!
|
||||
//! Most string operations in Rust act on UTF-8 strings. However, at times it
|
||||
//! makes more sense to only consider the ASCII character set for a specific
|
||||
//! operation.
|
||||
//!
|
||||
//! The [`AsciiExt`] trait provides methods that allow for character
|
||||
//! operations that only act on the ASCII subset and leave non-ASCII characters
|
||||
//! alone.
|
||||
//!
|
||||
//! The [`escape_default`] function provides an iterator over the bytes of an
|
||||
//! escaped version of the character given.
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||
pub use core::ascii::Char;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::ascii::{EscapeDefault, escape_default};
|
||||
|
||||
/// Extension methods for ASCII-subset only operations.
|
||||
///
|
||||
/// Be aware that operations on seemingly non-ASCII characters can sometimes
|
||||
/// have unexpected results. Consider this example:
|
||||
///
|
||||
/// ```
|
||||
/// use std::ascii::AsciiExt;
|
||||
///
|
||||
/// assert_eq!(AsciiExt::to_ascii_uppercase("café"), "CAFÉ");
|
||||
/// assert_eq!(AsciiExt::to_ascii_uppercase("café"), "CAFé");
|
||||
/// ```
|
||||
///
|
||||
/// In the first example, the lowercased string is represented `"cafe\u{301}"`
|
||||
/// (the last character is an acute accent [combining character]). Unlike the
|
||||
/// other characters in the string, the combining character will not get mapped
|
||||
/// to an uppercase variant, resulting in `"CAFE\u{301}"`. In the second
|
||||
/// example, the lowercased string is represented `"caf\u{e9}"` (the last
|
||||
/// character is a single Unicode character representing an 'e' with an acute
|
||||
/// accent). Since the last character is defined outside the scope of ASCII,
|
||||
/// it will not get mapped to an uppercase variant, resulting in `"CAF\u{e9}"`.
|
||||
///
|
||||
/// [combining character]: https://en.wikipedia.org/wiki/Combining_character
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(since = "1.26.0", note = "use inherent methods instead")]
|
||||
pub trait AsciiExt {
|
||||
/// Container type for copied ASCII characters.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
type Owned;
|
||||
|
||||
/// Checks if the value is within the ASCII range.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This method is deprecated in favor of the identically-named
|
||||
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn is_ascii(&self) -> bool;
|
||||
|
||||
/// Makes a copy of the value in its ASCII upper case equivalent.
|
||||
///
|
||||
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
|
||||
/// but non-ASCII letters are unchanged.
|
||||
///
|
||||
/// To uppercase the value in-place, use [`make_ascii_uppercase`].
|
||||
///
|
||||
/// To uppercase ASCII characters in addition to non-ASCII characters, use
|
||||
/// [`str::to_uppercase`].
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This method is deprecated in favor of the identically-named
|
||||
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
|
||||
///
|
||||
/// [`make_ascii_uppercase`]: AsciiExt::make_ascii_uppercase
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated)]
|
||||
fn to_ascii_uppercase(&self) -> Self::Owned;
|
||||
|
||||
/// Makes a copy of the value in its ASCII lower case equivalent.
|
||||
///
|
||||
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
|
||||
/// but non-ASCII letters are unchanged.
|
||||
///
|
||||
/// To lowercase the value in-place, use [`make_ascii_lowercase`].
|
||||
///
|
||||
/// To lowercase ASCII characters in addition to non-ASCII characters, use
|
||||
/// [`str::to_lowercase`].
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This method is deprecated in favor of the identically-named
|
||||
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
|
||||
///
|
||||
/// [`make_ascii_lowercase`]: AsciiExt::make_ascii_lowercase
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated)]
|
||||
fn to_ascii_lowercase(&self) -> Self::Owned;
|
||||
|
||||
/// Checks that two values are an ASCII case-insensitive match.
|
||||
///
|
||||
/// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
|
||||
/// but without allocating and copying temporaries.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This method is deprecated in favor of the identically-named
|
||||
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn eq_ignore_ascii_case(&self, other: &Self) -> bool;
|
||||
|
||||
/// Converts this type to its ASCII upper case equivalent in-place.
|
||||
///
|
||||
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
|
||||
/// but non-ASCII letters are unchanged.
|
||||
///
|
||||
/// To return a new uppercased value without modifying the existing one, use
|
||||
/// [`to_ascii_uppercase`].
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This method is deprecated in favor of the identically-named
|
||||
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
|
||||
///
|
||||
/// [`to_ascii_uppercase`]: AsciiExt::to_ascii_uppercase
|
||||
#[stable(feature = "ascii", since = "1.9.0")]
|
||||
fn make_ascii_uppercase(&mut self);
|
||||
|
||||
/// Converts this type to its ASCII lower case equivalent in-place.
|
||||
///
|
||||
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
|
||||
/// but non-ASCII letters are unchanged.
|
||||
///
|
||||
/// To return a new lowercased value without modifying the existing one, use
|
||||
/// [`to_ascii_lowercase`].
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This method is deprecated in favor of the identically-named
|
||||
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
|
||||
///
|
||||
/// [`to_ascii_lowercase`]: AsciiExt::to_ascii_lowercase
|
||||
#[stable(feature = "ascii", since = "1.9.0")]
|
||||
fn make_ascii_lowercase(&mut self);
|
||||
}
|
||||
|
||||
macro_rules! delegating_ascii_methods {
|
||||
() => {
|
||||
#[inline]
|
||||
fn is_ascii(&self) -> bool {
|
||||
self.is_ascii()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_ascii_uppercase(&self) -> Self::Owned {
|
||||
self.to_ascii_uppercase()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_ascii_lowercase(&self) -> Self::Owned {
|
||||
self.to_ascii_lowercase()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn eq_ignore_ascii_case(&self, o: &Self) -> bool {
|
||||
self.eq_ignore_ascii_case(o)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn make_ascii_uppercase(&mut self) {
|
||||
self.make_ascii_uppercase();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn make_ascii_lowercase(&mut self) {
|
||||
self.make_ascii_lowercase();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated)]
|
||||
impl AsciiExt for u8 {
|
||||
type Owned = u8;
|
||||
|
||||
delegating_ascii_methods!();
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated)]
|
||||
impl AsciiExt for char {
|
||||
type Owned = char;
|
||||
|
||||
delegating_ascii_methods!();
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated)]
|
||||
impl AsciiExt for [u8] {
|
||||
type Owned = Vec<u8>;
|
||||
|
||||
delegating_ascii_methods!();
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated)]
|
||||
impl AsciiExt for str {
|
||||
type Owned = String;
|
||||
|
||||
delegating_ascii_methods!();
|
||||
}
|
||||
1
library/std/src/ascii.rs
Symbolic link
1
library/std/src/ascii.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/ascii.rs
|
||||
@@ -1,478 +0,0 @@
|
||||
//! Support for capturing a stack backtrace of an OS thread
|
||||
//!
|
||||
//! This module contains the support necessary to capture a stack backtrace of a
|
||||
//! running OS thread from the OS thread itself. The `Backtrace` type supports
|
||||
//! capturing a stack trace via the `Backtrace::capture` and
|
||||
//! `Backtrace::force_capture` functions.
|
||||
//!
|
||||
//! A backtrace is typically quite handy to attach to errors (e.g. types
|
||||
//! implementing `std::error::Error`) to get a causal chain of where an error
|
||||
//! was generated.
|
||||
//!
|
||||
//! ## Accuracy
|
||||
//!
|
||||
//! Backtraces are attempted to be as accurate as possible, but no guarantees
|
||||
//! are provided about the exact accuracy of a backtrace. Instruction pointers,
|
||||
//! symbol names, filenames, line numbers, etc, may all be incorrect when
|
||||
//! reported. Accuracy is attempted on a best-effort basis, however, any bug
|
||||
//! reports are always welcome to indicate areas of improvement!
|
||||
//!
|
||||
//! For most platforms a backtrace with a filename/line number requires that
|
||||
//! programs be compiled with debug information. Without debug information
|
||||
//! filenames/line numbers will not be reported.
|
||||
//!
|
||||
//! ## Platform support
|
||||
//!
|
||||
//! Not all platforms that std compiles for support capturing backtraces. Some
|
||||
//! platforms simply do nothing when capturing a backtrace. To check whether the
|
||||
//! platform supports capturing backtraces you can consult the `BacktraceStatus`
|
||||
//! enum as a result of `Backtrace::status`.
|
||||
//!
|
||||
//! Like above with accuracy platform support is done on a best effort basis.
|
||||
//! Sometimes libraries might not be available at runtime or something may go
|
||||
//! wrong which would cause a backtrace to not be captured. Please feel free to
|
||||
//! report issues with platforms where a backtrace cannot be captured though!
|
||||
//!
|
||||
//! ## Environment Variables
|
||||
//!
|
||||
//! The `Backtrace::capture` function might not actually capture a backtrace by
|
||||
//! default. Its behavior is governed by two environment variables:
|
||||
//!
|
||||
//! * `RUST_LIB_BACKTRACE` - if this is set to `0` then `Backtrace::capture`
|
||||
//! will never capture a backtrace. Any other value set will enable
|
||||
//! `Backtrace::capture`.
|
||||
//!
|
||||
//! * `RUST_BACKTRACE` - if `RUST_LIB_BACKTRACE` is not set, then this variable
|
||||
//! is consulted with the same rules of `RUST_LIB_BACKTRACE`.
|
||||
//!
|
||||
//! * If neither of the above env vars are set, then `Backtrace::capture` will
|
||||
//! be disabled.
|
||||
//!
|
||||
//! Capturing a backtrace can be a quite expensive runtime operation, so the
|
||||
//! environment variables allow either forcibly disabling this runtime
|
||||
//! performance hit or allow selectively enabling it in some programs.
|
||||
//!
|
||||
//! Note that the `Backtrace::force_capture` function can be used to ignore
|
||||
//! these environment variables. Also note that the state of environment
|
||||
//! variables is cached once the first backtrace is created, so altering
|
||||
//! `RUST_LIB_BACKTRACE` or `RUST_BACKTRACE` at runtime might not actually change
|
||||
//! how backtraces are captured.
|
||||
|
||||
#![stable(feature = "backtrace", since = "1.65.0")]
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
// NB: A note on resolution of a backtrace:
|
||||
//
|
||||
// Backtraces primarily happen in two steps, one is where we actually capture
|
||||
// the stack backtrace, giving us a list of instruction pointers corresponding
|
||||
// to stack frames. Next we take these instruction pointers and, one-by-one,
|
||||
// turn them into a human readable name (like `main`).
|
||||
//
|
||||
// The first phase can be somewhat expensive (walking the stack), especially
|
||||
// on MSVC where debug information is consulted to return inline frames each as
|
||||
// their own frame. The second phase, however, is almost always extremely
|
||||
// expensive (on the order of milliseconds sometimes) when it's consulting debug
|
||||
// information.
|
||||
//
|
||||
// We attempt to amortize this cost as much as possible by delaying resolution
|
||||
// of an address to a human readable name for as long as possible. When
|
||||
// `Backtrace::create` is called to capture a backtrace it doesn't actually
|
||||
// perform any symbol resolution, but rather we lazily resolve symbols only just
|
||||
// before they're needed for printing. This way we can make capturing a
|
||||
// backtrace and throwing it away much cheaper, but actually printing a
|
||||
// backtrace is still basically the same cost.
|
||||
//
|
||||
// This strategy comes at the cost of some synchronization required inside of a
|
||||
// `Backtrace`, but that's a relatively small price to pay relative to capturing
|
||||
// a backtrace or actually symbolizing it.
|
||||
|
||||
use crate::backtrace_rs::{self, BytesOrWideString};
|
||||
use crate::ffi::c_void;
|
||||
use crate::panic::UnwindSafe;
|
||||
use crate::sync::LazyLock;
|
||||
use crate::sync::atomic::Ordering::Relaxed;
|
||||
use crate::sync::atomic::{Atomic, AtomicU8};
|
||||
use crate::sys::backtrace::{lock, output_filename, set_image_base};
|
||||
use crate::{env, fmt};
|
||||
|
||||
/// A captured OS thread stack backtrace.
|
||||
///
|
||||
/// This type represents a stack backtrace for an OS thread captured at a
|
||||
/// previous point in time. In some instances the `Backtrace` type may
|
||||
/// internally be empty due to configuration. For more information see
|
||||
/// `Backtrace::capture`.
|
||||
#[stable(feature = "backtrace", since = "1.65.0")]
|
||||
#[must_use]
|
||||
pub struct Backtrace {
|
||||
inner: Inner,
|
||||
}
|
||||
|
||||
/// The current status of a backtrace, indicating whether it was captured or
|
||||
/// whether it is empty for some other reason.
|
||||
#[stable(feature = "backtrace", since = "1.65.0")]
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum BacktraceStatus {
|
||||
/// Capturing a backtrace is not supported, likely because it's not
|
||||
/// implemented for the current platform.
|
||||
#[stable(feature = "backtrace", since = "1.65.0")]
|
||||
Unsupported,
|
||||
/// Capturing a backtrace has been disabled through either the
|
||||
/// `RUST_LIB_BACKTRACE` or `RUST_BACKTRACE` environment variables.
|
||||
#[stable(feature = "backtrace", since = "1.65.0")]
|
||||
Disabled,
|
||||
/// A backtrace has been captured and the `Backtrace` should print
|
||||
/// reasonable information when rendered.
|
||||
#[stable(feature = "backtrace", since = "1.65.0")]
|
||||
Captured,
|
||||
}
|
||||
|
||||
enum Inner {
|
||||
Unsupported,
|
||||
Disabled,
|
||||
Captured(LazyLock<Capture, LazyResolve>),
|
||||
}
|
||||
|
||||
struct Capture {
|
||||
actual_start: usize,
|
||||
frames: Vec<BacktraceFrame>,
|
||||
}
|
||||
|
||||
fn _assert_send_sync() {
|
||||
fn _assert<T: Send + Sync>() {}
|
||||
_assert::<Backtrace>();
|
||||
}
|
||||
|
||||
/// A single frame of a backtrace.
|
||||
#[unstable(feature = "backtrace_frames", issue = "79676")]
|
||||
pub struct BacktraceFrame {
|
||||
frame: RawFrame,
|
||||
symbols: Vec<BacktraceSymbol>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum RawFrame {
|
||||
Actual(backtrace_rs::Frame),
|
||||
#[cfg(test)]
|
||||
Fake,
|
||||
}
|
||||
|
||||
struct BacktraceSymbol {
|
||||
name: Option<Vec<u8>>,
|
||||
filename: Option<BytesOrWide>,
|
||||
lineno: Option<u32>,
|
||||
colno: Option<u32>,
|
||||
}
|
||||
|
||||
enum BytesOrWide {
|
||||
Bytes(Vec<u8>),
|
||||
Wide(Vec<u16>),
|
||||
}
|
||||
|
||||
#[stable(feature = "backtrace", since = "1.65.0")]
|
||||
impl fmt::Debug for Backtrace {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let capture = match &self.inner {
|
||||
Inner::Unsupported => return fmt.write_str("<unsupported>"),
|
||||
Inner::Disabled => return fmt.write_str("<disabled>"),
|
||||
Inner::Captured(c) => &**c,
|
||||
};
|
||||
|
||||
let frames = &capture.frames[capture.actual_start..];
|
||||
|
||||
write!(fmt, "Backtrace ")?;
|
||||
|
||||
let mut dbg = fmt.debug_list();
|
||||
|
||||
for frame in frames {
|
||||
if frame.frame.ip().is_null() {
|
||||
continue;
|
||||
}
|
||||
|
||||
dbg.entries(&frame.symbols);
|
||||
}
|
||||
|
||||
dbg.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "backtrace_frames", issue = "79676")]
|
||||
impl fmt::Debug for BacktraceFrame {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut dbg = fmt.debug_list();
|
||||
dbg.entries(&self.symbols);
|
||||
dbg.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for BacktraceSymbol {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// FIXME: improve formatting: https://github.com/rust-lang/rust/issues/65280
|
||||
// FIXME: Also, include column numbers into the debug format as Display already has them.
|
||||
// Until there are stable per-frame accessors, the format shouldn't be changed:
|
||||
// https://github.com/rust-lang/rust/issues/65280#issuecomment-638966585
|
||||
write!(fmt, "{{ ")?;
|
||||
|
||||
if let Some(fn_name) = self.name.as_ref().map(|b| backtrace_rs::SymbolName::new(b)) {
|
||||
write!(fmt, "fn: \"{:#}\"", fn_name)?;
|
||||
} else {
|
||||
write!(fmt, "fn: <unknown>")?;
|
||||
}
|
||||
|
||||
if let Some(fname) = self.filename.as_ref() {
|
||||
write!(fmt, ", file: \"{:?}\"", fname)?;
|
||||
}
|
||||
|
||||
if let Some(line) = self.lineno {
|
||||
write!(fmt, ", line: {:?}", line)?;
|
||||
}
|
||||
|
||||
write!(fmt, " }}")
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for BytesOrWide {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
output_filename(
|
||||
fmt,
|
||||
match self {
|
||||
BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w),
|
||||
BytesOrWide::Wide(w) => BytesOrWideString::Wide(w),
|
||||
},
|
||||
backtrace_rs::PrintFmt::Short,
|
||||
crate::env::current_dir().as_ref().ok(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Backtrace {
|
||||
/// Returns whether backtrace captures are enabled through environment
|
||||
/// variables.
|
||||
fn enabled() -> bool {
|
||||
// Cache the result of reading the environment variables to make
|
||||
// backtrace captures speedy, because otherwise reading environment
|
||||
// variables every time can be somewhat slow.
|
||||
static ENABLED: Atomic<u8> = AtomicU8::new(0);
|
||||
match ENABLED.load(Relaxed) {
|
||||
0 => {}
|
||||
1 => return false,
|
||||
_ => return true,
|
||||
}
|
||||
let enabled = match env::var("RUST_LIB_BACKTRACE") {
|
||||
Ok(s) => s != "0",
|
||||
Err(_) => match env::var("RUST_BACKTRACE") {
|
||||
Ok(s) => s != "0",
|
||||
Err(_) => false,
|
||||
},
|
||||
};
|
||||
ENABLED.store(enabled as u8 + 1, Relaxed);
|
||||
enabled
|
||||
}
|
||||
|
||||
/// Captures a stack backtrace of the current thread.
|
||||
///
|
||||
/// This function will capture a stack backtrace of the current OS thread of
|
||||
/// execution, returning a `Backtrace` type which can be later used to print
|
||||
/// the entire stack trace or render it to a string.
|
||||
///
|
||||
/// This function will be a noop if the `RUST_BACKTRACE` or
|
||||
/// `RUST_LIB_BACKTRACE` backtrace variables are both not set. If either
|
||||
/// environment variable is set and enabled then this function will actually
|
||||
/// capture a backtrace. Capturing a backtrace can be both memory intensive
|
||||
/// and slow, so these environment variables allow liberally using
|
||||
/// `Backtrace::capture` and only incurring a slowdown when the environment
|
||||
/// variables are set.
|
||||
///
|
||||
/// To forcibly capture a backtrace regardless of environment variables, use
|
||||
/// the `Backtrace::force_capture` function.
|
||||
#[stable(feature = "backtrace", since = "1.65.0")]
|
||||
#[inline(never)] // want to make sure there's a frame here to remove
|
||||
pub fn capture() -> Backtrace {
|
||||
if !Backtrace::enabled() {
|
||||
return Backtrace { inner: Inner::Disabled };
|
||||
}
|
||||
Backtrace::create(Backtrace::capture as fn() -> Backtrace as usize)
|
||||
}
|
||||
|
||||
/// Forcibly captures a full backtrace, regardless of environment variable
|
||||
/// configuration.
|
||||
///
|
||||
/// This function behaves the same as `capture` except that it ignores the
|
||||
/// values of the `RUST_BACKTRACE` and `RUST_LIB_BACKTRACE` environment
|
||||
/// variables, always capturing a backtrace.
|
||||
///
|
||||
/// Note that capturing a backtrace can be an expensive operation on some
|
||||
/// platforms, so this should be used with caution in performance-sensitive
|
||||
/// parts of code.
|
||||
#[stable(feature = "backtrace", since = "1.65.0")]
|
||||
#[inline(never)] // want to make sure there's a frame here to remove
|
||||
pub fn force_capture() -> Backtrace {
|
||||
Backtrace::create(Backtrace::force_capture as fn() -> Backtrace as usize)
|
||||
}
|
||||
|
||||
/// Forcibly captures a disabled backtrace, regardless of environment
|
||||
/// variable configuration.
|
||||
#[stable(feature = "backtrace", since = "1.65.0")]
|
||||
#[rustc_const_stable(feature = "backtrace", since = "1.65.0")]
|
||||
pub const fn disabled() -> Backtrace {
|
||||
Backtrace { inner: Inner::Disabled }
|
||||
}
|
||||
|
||||
// Capture a backtrace which start just before the function addressed by
|
||||
// `ip`
|
||||
fn create(ip: usize) -> Backtrace {
|
||||
let _lock = lock();
|
||||
let mut frames = Vec::new();
|
||||
let mut actual_start = None;
|
||||
set_image_base();
|
||||
unsafe {
|
||||
backtrace_rs::trace_unsynchronized(|frame| {
|
||||
frames.push(BacktraceFrame {
|
||||
frame: RawFrame::Actual(frame.clone()),
|
||||
symbols: Vec::new(),
|
||||
});
|
||||
if frame.symbol_address().addr() == ip && actual_start.is_none() {
|
||||
actual_start = Some(frames.len());
|
||||
}
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
// If no frames came out assume that this is an unsupported platform
|
||||
// since `backtrace` doesn't provide a way of learning this right now,
|
||||
// and this should be a good enough approximation.
|
||||
let inner = if frames.is_empty() {
|
||||
Inner::Unsupported
|
||||
} else {
|
||||
Inner::Captured(LazyLock::new(lazy_resolve(Capture {
|
||||
actual_start: actual_start.unwrap_or(0),
|
||||
frames,
|
||||
})))
|
||||
};
|
||||
|
||||
Backtrace { inner }
|
||||
}
|
||||
|
||||
/// Returns the status of this backtrace, indicating whether this backtrace
|
||||
/// request was unsupported, disabled, or a stack trace was actually
|
||||
/// captured.
|
||||
#[stable(feature = "backtrace", since = "1.65.0")]
|
||||
#[must_use]
|
||||
pub fn status(&self) -> BacktraceStatus {
|
||||
match self.inner {
|
||||
Inner::Unsupported => BacktraceStatus::Unsupported,
|
||||
Inner::Disabled => BacktraceStatus::Disabled,
|
||||
Inner::Captured(_) => BacktraceStatus::Captured,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Backtrace {
|
||||
/// Returns an iterator over the backtrace frames.
|
||||
#[must_use]
|
||||
#[unstable(feature = "backtrace_frames", issue = "79676")]
|
||||
pub fn frames(&'a self) -> &'a [BacktraceFrame] {
|
||||
if let Inner::Captured(c) = &self.inner { &c.frames } else { &[] }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "backtrace", since = "1.65.0")]
|
||||
impl fmt::Display for Backtrace {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let capture = match &self.inner {
|
||||
Inner::Unsupported => return fmt.write_str("unsupported backtrace"),
|
||||
Inner::Disabled => return fmt.write_str("disabled backtrace"),
|
||||
Inner::Captured(c) => &**c,
|
||||
};
|
||||
|
||||
let full = fmt.alternate();
|
||||
let (frames, style) = if full {
|
||||
(&capture.frames[..], backtrace_rs::PrintFmt::Full)
|
||||
} else {
|
||||
(&capture.frames[capture.actual_start..], backtrace_rs::PrintFmt::Short)
|
||||
};
|
||||
|
||||
// When printing paths we try to strip the cwd if it exists, otherwise
|
||||
// we just print the path as-is. Note that we also only do this for the
|
||||
// short format, because if it's full we presumably want to print
|
||||
// everything.
|
||||
let cwd = crate::env::current_dir();
|
||||
let mut print_path = move |fmt: &mut fmt::Formatter<'_>, path: BytesOrWideString<'_>| {
|
||||
output_filename(fmt, path, style, cwd.as_ref().ok())
|
||||
};
|
||||
|
||||
let mut f = backtrace_rs::BacktraceFmt::new(fmt, style, &mut print_path);
|
||||
f.add_context()?;
|
||||
for frame in frames {
|
||||
if frame.symbols.is_empty() {
|
||||
f.frame().print_raw(frame.frame.ip(), None, None, None)?;
|
||||
} else {
|
||||
for symbol in frame.symbols.iter() {
|
||||
f.frame().print_raw_with_column(
|
||||
frame.frame.ip(),
|
||||
symbol.name.as_ref().map(|b| backtrace_rs::SymbolName::new(b)),
|
||||
symbol.filename.as_ref().map(|b| match b {
|
||||
BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w),
|
||||
BytesOrWide::Wide(w) => BytesOrWideString::Wide(w),
|
||||
}),
|
||||
symbol.lineno,
|
||||
symbol.colno,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
f.finish()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
mod helper {
|
||||
use super::*;
|
||||
pub(super) type LazyResolve = impl (FnOnce() -> Capture) + Send + Sync + UnwindSafe;
|
||||
|
||||
#[define_opaque(LazyResolve)]
|
||||
pub(super) fn lazy_resolve(mut capture: Capture) -> LazyResolve {
|
||||
move || {
|
||||
// Use the global backtrace lock to synchronize this as it's a
|
||||
// requirement of the `backtrace` crate, and then actually resolve
|
||||
// everything.
|
||||
let _lock = lock();
|
||||
for frame in capture.frames.iter_mut() {
|
||||
let symbols = &mut frame.symbols;
|
||||
let frame = match &frame.frame {
|
||||
RawFrame::Actual(frame) => frame,
|
||||
#[cfg(test)]
|
||||
RawFrame::Fake => unimplemented!(),
|
||||
};
|
||||
unsafe {
|
||||
backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
|
||||
symbols.push(BacktraceSymbol {
|
||||
name: symbol.name().map(|m| m.as_bytes().to_vec()),
|
||||
filename: symbol.filename_raw().map(|b| match b {
|
||||
BytesOrWideString::Bytes(b) => BytesOrWide::Bytes(b.to_owned()),
|
||||
BytesOrWideString::Wide(b) => BytesOrWide::Wide(b.to_owned()),
|
||||
}),
|
||||
lineno: symbol.lineno(),
|
||||
colno: symbol.colno(),
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
capture
|
||||
}
|
||||
}
|
||||
}
|
||||
use helper::*;
|
||||
|
||||
impl RawFrame {
|
||||
fn ip(&self) -> *mut c_void {
|
||||
match self {
|
||||
RawFrame::Actual(frame) => frame.ip(),
|
||||
#[cfg(test)]
|
||||
RawFrame::Fake => crate::ptr::without_provenance_mut(1),
|
||||
}
|
||||
}
|
||||
}
|
||||
1
library/std/src/backtrace.rs
Symbolic link
1
library/std/src/backtrace.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/backtrace.rs
|
||||
@@ -1,4 +0,0 @@
|
||||
//! The `ByteStr` and `ByteString` types and trait implementations.
|
||||
|
||||
#[unstable(feature = "bstr", issue = "134915")]
|
||||
pub use alloc::bstr::{ByteStr, ByteString};
|
||||
1
library/std/src/bstr.rs
Symbolic link
1
library/std/src/bstr.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/bstr.rs
|
||||
File diff suppressed because it is too large
Load Diff
1
library/std/src/env.rs
Symbolic link
1
library/std/src/env.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/env.rs
|
||||
@@ -1,562 +0,0 @@
|
||||
#![doc = include_str!("../../core/src/error.md")]
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::error::Error;
|
||||
#[unstable(feature = "error_generic_member_access", issue = "99301")]
|
||||
pub use core::error::{Request, request_ref, request_value};
|
||||
|
||||
use crate::backtrace::Backtrace;
|
||||
use crate::fmt::{self, Write};
|
||||
|
||||
/// An error reporter that prints an error and its sources.
|
||||
///
|
||||
/// Report also exposes configuration options for formatting the error sources, either entirely on a
|
||||
/// single line, or in multi-line format with each source on a new line.
|
||||
///
|
||||
/// `Report` only requires that the wrapped error implement `Error`. It doesn't require that the
|
||||
/// wrapped error be `Send`, `Sync`, or `'static`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(error_reporter)]
|
||||
/// use std::error::{Error, Report};
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// #[derive(Debug)]
|
||||
/// struct SuperError {
|
||||
/// source: SuperErrorSideKick,
|
||||
/// }
|
||||
///
|
||||
/// impl fmt::Display for SuperError {
|
||||
/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// write!(f, "SuperError is here!")
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl Error for SuperError {
|
||||
/// fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
/// Some(&self.source)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// #[derive(Debug)]
|
||||
/// struct SuperErrorSideKick;
|
||||
///
|
||||
/// impl fmt::Display for SuperErrorSideKick {
|
||||
/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// write!(f, "SuperErrorSideKick is here!")
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl Error for SuperErrorSideKick {}
|
||||
///
|
||||
/// fn get_super_error() -> Result<(), SuperError> {
|
||||
/// Err(SuperError { source: SuperErrorSideKick })
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// match get_super_error() {
|
||||
/// Err(e) => println!("Error: {}", Report::new(e)),
|
||||
/// _ => println!("No error"),
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This example produces the following output:
|
||||
///
|
||||
/// ```console
|
||||
/// Error: SuperError is here!: SuperErrorSideKick is here!
|
||||
/// ```
|
||||
///
|
||||
/// ## Output consistency
|
||||
///
|
||||
/// Report prints the same output via `Display` and `Debug`, so it works well with
|
||||
/// [`Result::unwrap`]/[`Result::expect`] which print their `Err` variant via `Debug`:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(error_reporter)]
|
||||
/// use std::error::Report;
|
||||
/// # use std::error::Error;
|
||||
/// # use std::fmt;
|
||||
/// # #[derive(Debug)]
|
||||
/// # struct SuperError {
|
||||
/// # source: SuperErrorSideKick,
|
||||
/// # }
|
||||
/// # impl fmt::Display for SuperError {
|
||||
/// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// # write!(f, "SuperError is here!")
|
||||
/// # }
|
||||
/// # }
|
||||
/// # impl Error for SuperError {
|
||||
/// # fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
/// # Some(&self.source)
|
||||
/// # }
|
||||
/// # }
|
||||
/// # #[derive(Debug)]
|
||||
/// # struct SuperErrorSideKick;
|
||||
/// # impl fmt::Display for SuperErrorSideKick {
|
||||
/// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// # write!(f, "SuperErrorSideKick is here!")
|
||||
/// # }
|
||||
/// # }
|
||||
/// # impl Error for SuperErrorSideKick {}
|
||||
/// # fn get_super_error() -> Result<(), SuperError> {
|
||||
/// # Err(SuperError { source: SuperErrorSideKick })
|
||||
/// # }
|
||||
///
|
||||
/// get_super_error().map_err(Report::new).unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// This example produces the following output:
|
||||
///
|
||||
/// ```console
|
||||
/// thread 'main' panicked at src/error.rs:34:40:
|
||||
/// called `Result::unwrap()` on an `Err` value: SuperError is here!: SuperErrorSideKick is here!
|
||||
/// note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||
/// ```
|
||||
///
|
||||
/// ## Return from `main`
|
||||
///
|
||||
/// `Report` also implements `From` for all types that implement [`Error`]; this when combined with
|
||||
/// the `Debug` output means `Report` is an ideal starting place for formatting errors returned
|
||||
/// from `main`.
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(error_reporter)]
|
||||
/// use std::error::Report;
|
||||
/// # use std::error::Error;
|
||||
/// # use std::fmt;
|
||||
/// # #[derive(Debug)]
|
||||
/// # struct SuperError {
|
||||
/// # source: SuperErrorSideKick,
|
||||
/// # }
|
||||
/// # impl fmt::Display for SuperError {
|
||||
/// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// # write!(f, "SuperError is here!")
|
||||
/// # }
|
||||
/// # }
|
||||
/// # impl Error for SuperError {
|
||||
/// # fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
/// # Some(&self.source)
|
||||
/// # }
|
||||
/// # }
|
||||
/// # #[derive(Debug)]
|
||||
/// # struct SuperErrorSideKick;
|
||||
/// # impl fmt::Display for SuperErrorSideKick {
|
||||
/// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// # write!(f, "SuperErrorSideKick is here!")
|
||||
/// # }
|
||||
/// # }
|
||||
/// # impl Error for SuperErrorSideKick {}
|
||||
/// # fn get_super_error() -> Result<(), SuperError> {
|
||||
/// # Err(SuperError { source: SuperErrorSideKick })
|
||||
/// # }
|
||||
///
|
||||
/// fn main() -> Result<(), Report<SuperError>> {
|
||||
/// get_super_error()?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This example produces the following output:
|
||||
///
|
||||
/// ```console
|
||||
/// Error: SuperError is here!: SuperErrorSideKick is here!
|
||||
/// ```
|
||||
///
|
||||
/// **Note**: `Report`s constructed via `?` and `From` will be configured to use the single line
|
||||
/// output format. If you want to make sure your `Report`s are pretty printed and include backtrace
|
||||
/// you will need to manually convert and enable those flags.
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(error_reporter)]
|
||||
/// use std::error::Report;
|
||||
/// # use std::error::Error;
|
||||
/// # use std::fmt;
|
||||
/// # #[derive(Debug)]
|
||||
/// # struct SuperError {
|
||||
/// # source: SuperErrorSideKick,
|
||||
/// # }
|
||||
/// # impl fmt::Display for SuperError {
|
||||
/// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// # write!(f, "SuperError is here!")
|
||||
/// # }
|
||||
/// # }
|
||||
/// # impl Error for SuperError {
|
||||
/// # fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
/// # Some(&self.source)
|
||||
/// # }
|
||||
/// # }
|
||||
/// # #[derive(Debug)]
|
||||
/// # struct SuperErrorSideKick;
|
||||
/// # impl fmt::Display for SuperErrorSideKick {
|
||||
/// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// # write!(f, "SuperErrorSideKick is here!")
|
||||
/// # }
|
||||
/// # }
|
||||
/// # impl Error for SuperErrorSideKick {}
|
||||
/// # fn get_super_error() -> Result<(), SuperError> {
|
||||
/// # Err(SuperError { source: SuperErrorSideKick })
|
||||
/// # }
|
||||
///
|
||||
/// fn main() -> Result<(), Report<SuperError>> {
|
||||
/// get_super_error()
|
||||
/// .map_err(Report::from)
|
||||
/// .map_err(|r| r.pretty(true).show_backtrace(true))?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This example produces the following output:
|
||||
///
|
||||
/// ```console
|
||||
/// Error: SuperError is here!
|
||||
///
|
||||
/// Caused by:
|
||||
/// SuperErrorSideKick is here!
|
||||
/// ```
|
||||
#[unstable(feature = "error_reporter", issue = "90172")]
|
||||
pub struct Report<E = Box<dyn Error>> {
|
||||
/// The error being reported.
|
||||
error: E,
|
||||
/// Whether a backtrace should be included as part of the report.
|
||||
show_backtrace: bool,
|
||||
/// Whether the report should be pretty-printed.
|
||||
pretty: bool,
|
||||
}
|
||||
|
||||
impl<E> Report<E>
|
||||
where
|
||||
Report<E>: From<E>,
|
||||
{
|
||||
/// Creates a new `Report` from an input error.
|
||||
#[unstable(feature = "error_reporter", issue = "90172")]
|
||||
pub fn new(error: E) -> Report<E> {
|
||||
Self::from(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> Report<E> {
|
||||
/// Enable pretty-printing the report across multiple lines.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(error_reporter)]
|
||||
/// use std::error::Report;
|
||||
/// # use std::error::Error;
|
||||
/// # use std::fmt;
|
||||
/// # #[derive(Debug)]
|
||||
/// # struct SuperError {
|
||||
/// # source: SuperErrorSideKick,
|
||||
/// # }
|
||||
/// # impl fmt::Display for SuperError {
|
||||
/// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// # write!(f, "SuperError is here!")
|
||||
/// # }
|
||||
/// # }
|
||||
/// # impl Error for SuperError {
|
||||
/// # fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
/// # Some(&self.source)
|
||||
/// # }
|
||||
/// # }
|
||||
/// # #[derive(Debug)]
|
||||
/// # struct SuperErrorSideKick;
|
||||
/// # impl fmt::Display for SuperErrorSideKick {
|
||||
/// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// # write!(f, "SuperErrorSideKick is here!")
|
||||
/// # }
|
||||
/// # }
|
||||
/// # impl Error for SuperErrorSideKick {}
|
||||
///
|
||||
/// let error = SuperError { source: SuperErrorSideKick };
|
||||
/// let report = Report::new(error).pretty(true);
|
||||
/// eprintln!("Error: {report:?}");
|
||||
/// ```
|
||||
///
|
||||
/// This example produces the following output:
|
||||
///
|
||||
/// ```console
|
||||
/// Error: SuperError is here!
|
||||
///
|
||||
/// Caused by:
|
||||
/// SuperErrorSideKick is here!
|
||||
/// ```
|
||||
///
|
||||
/// When there are multiple source errors the causes will be numbered in order of iteration
|
||||
/// starting from the outermost error.
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(error_reporter)]
|
||||
/// use std::error::Report;
|
||||
/// # use std::error::Error;
|
||||
/// # use std::fmt;
|
||||
/// # #[derive(Debug)]
|
||||
/// # struct SuperError {
|
||||
/// # source: SuperErrorSideKick,
|
||||
/// # }
|
||||
/// # impl fmt::Display for SuperError {
|
||||
/// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// # write!(f, "SuperError is here!")
|
||||
/// # }
|
||||
/// # }
|
||||
/// # impl Error for SuperError {
|
||||
/// # fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
/// # Some(&self.source)
|
||||
/// # }
|
||||
/// # }
|
||||
/// # #[derive(Debug)]
|
||||
/// # struct SuperErrorSideKick {
|
||||
/// # source: SuperErrorSideKickSideKick,
|
||||
/// # }
|
||||
/// # impl fmt::Display for SuperErrorSideKick {
|
||||
/// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// # write!(f, "SuperErrorSideKick is here!")
|
||||
/// # }
|
||||
/// # }
|
||||
/// # impl Error for SuperErrorSideKick {
|
||||
/// # fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
/// # Some(&self.source)
|
||||
/// # }
|
||||
/// # }
|
||||
/// # #[derive(Debug)]
|
||||
/// # struct SuperErrorSideKickSideKick;
|
||||
/// # impl fmt::Display for SuperErrorSideKickSideKick {
|
||||
/// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// # write!(f, "SuperErrorSideKickSideKick is here!")
|
||||
/// # }
|
||||
/// # }
|
||||
/// # impl Error for SuperErrorSideKickSideKick { }
|
||||
///
|
||||
/// let source = SuperErrorSideKickSideKick;
|
||||
/// let source = SuperErrorSideKick { source };
|
||||
/// let error = SuperError { source };
|
||||
/// let report = Report::new(error).pretty(true);
|
||||
/// eprintln!("Error: {report:?}");
|
||||
/// ```
|
||||
///
|
||||
/// This example produces the following output:
|
||||
///
|
||||
/// ```console
|
||||
/// Error: SuperError is here!
|
||||
///
|
||||
/// Caused by:
|
||||
/// 0: SuperErrorSideKick is here!
|
||||
/// 1: SuperErrorSideKickSideKick is here!
|
||||
/// ```
|
||||
#[unstable(feature = "error_reporter", issue = "90172")]
|
||||
pub fn pretty(mut self, pretty: bool) -> Self {
|
||||
self.pretty = pretty;
|
||||
self
|
||||
}
|
||||
|
||||
/// Display backtrace if available when using pretty output format.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// **Note**: Report will search for the first `Backtrace` it can find starting from the
|
||||
/// outermost error. In this example it will display the backtrace from the second error in the
|
||||
/// sources, `SuperErrorSideKick`.
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(error_reporter)]
|
||||
/// #![feature(error_generic_member_access)]
|
||||
/// # use std::error::Error;
|
||||
/// # use std::fmt;
|
||||
/// use std::error::Request;
|
||||
/// use std::error::Report;
|
||||
/// use std::backtrace::Backtrace;
|
||||
///
|
||||
/// # #[derive(Debug)]
|
||||
/// # struct SuperError {
|
||||
/// # source: SuperErrorSideKick,
|
||||
/// # }
|
||||
/// # impl fmt::Display for SuperError {
|
||||
/// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// # write!(f, "SuperError is here!")
|
||||
/// # }
|
||||
/// # }
|
||||
/// # impl Error for SuperError {
|
||||
/// # fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
/// # Some(&self.source)
|
||||
/// # }
|
||||
/// # }
|
||||
/// #[derive(Debug)]
|
||||
/// struct SuperErrorSideKick {
|
||||
/// backtrace: Backtrace,
|
||||
/// }
|
||||
///
|
||||
/// impl SuperErrorSideKick {
|
||||
/// fn new() -> SuperErrorSideKick {
|
||||
/// SuperErrorSideKick { backtrace: Backtrace::force_capture() }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl Error for SuperErrorSideKick {
|
||||
/// fn provide<'a>(&'a self, request: &mut Request<'a>) {
|
||||
/// request.provide_ref::<Backtrace>(&self.backtrace);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // The rest of the example is unchanged ...
|
||||
/// # impl fmt::Display for SuperErrorSideKick {
|
||||
/// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// # write!(f, "SuperErrorSideKick is here!")
|
||||
/// # }
|
||||
/// # }
|
||||
///
|
||||
/// let source = SuperErrorSideKick::new();
|
||||
/// let error = SuperError { source };
|
||||
/// let report = Report::new(error).pretty(true).show_backtrace(true);
|
||||
/// eprintln!("Error: {report:?}");
|
||||
/// ```
|
||||
///
|
||||
/// This example produces something similar to the following output:
|
||||
///
|
||||
/// ```console
|
||||
/// Error: SuperError is here!
|
||||
///
|
||||
/// Caused by:
|
||||
/// SuperErrorSideKick is here!
|
||||
///
|
||||
/// Stack backtrace:
|
||||
/// 0: rust_out::main::_doctest_main_src_error_rs_1158_0::SuperErrorSideKick::new
|
||||
/// 1: rust_out::main::_doctest_main_src_error_rs_1158_0
|
||||
/// 2: rust_out::main
|
||||
/// 3: core::ops::function::FnOnce::call_once
|
||||
/// 4: std::sys::backtrace::__rust_begin_short_backtrace
|
||||
/// 5: std::rt::lang_start::{{closure}}
|
||||
/// 6: std::panicking::try
|
||||
/// 7: std::rt::lang_start_internal
|
||||
/// 8: std::rt::lang_start
|
||||
/// 9: main
|
||||
/// 10: __libc_start_main
|
||||
/// 11: _start
|
||||
/// ```
|
||||
#[unstable(feature = "error_reporter", issue = "90172")]
|
||||
pub fn show_backtrace(mut self, show_backtrace: bool) -> Self {
|
||||
self.show_backtrace = show_backtrace;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> Report<E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
fn backtrace(&self) -> Option<&Backtrace> {
|
||||
// have to grab the backtrace on the first error directly since that error may not be
|
||||
// 'static
|
||||
let backtrace = request_ref(&self.error);
|
||||
let backtrace = backtrace.or_else(|| {
|
||||
self.error
|
||||
.source()
|
||||
.map(|source| source.sources().find_map(|source| request_ref(source)))
|
||||
.flatten()
|
||||
});
|
||||
backtrace
|
||||
}
|
||||
|
||||
/// Format the report as a single line.
|
||||
#[unstable(feature = "error_reporter", issue = "90172")]
|
||||
fn fmt_singleline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.error)?;
|
||||
|
||||
let sources = self.error.source().into_iter().flat_map(<dyn Error>::sources);
|
||||
|
||||
for cause in sources {
|
||||
write!(f, ": {cause}")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Format the report as multiple lines, with each error cause on its own line.
|
||||
#[unstable(feature = "error_reporter", issue = "90172")]
|
||||
fn fmt_multiline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let error = &self.error;
|
||||
|
||||
write!(f, "{error}")?;
|
||||
|
||||
if let Some(cause) = error.source() {
|
||||
write!(f, "\n\nCaused by:")?;
|
||||
|
||||
let multiple = cause.source().is_some();
|
||||
|
||||
for (ind, error) in cause.sources().enumerate() {
|
||||
writeln!(f)?;
|
||||
let mut indented = Indented { inner: f };
|
||||
if multiple {
|
||||
write!(indented, "{ind: >4}: {error}")?;
|
||||
} else {
|
||||
write!(indented, " {error}")?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.show_backtrace {
|
||||
if let Some(backtrace) = self.backtrace() {
|
||||
write!(f, "\n\nStack backtrace:\n{}", backtrace.to_string().trim_end())?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "error_reporter", issue = "90172")]
|
||||
impl<E> From<E> for Report<E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
fn from(error: E) -> Self {
|
||||
Report { error, show_backtrace: false, pretty: false }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "error_reporter", issue = "90172")]
|
||||
impl<E> fmt::Display for Report<E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if self.pretty { self.fmt_multiline(f) } else { self.fmt_singleline(f) }
|
||||
}
|
||||
}
|
||||
|
||||
// This type intentionally outputs the same format for `Display` and `Debug`for
|
||||
// situations where you unwrap a `Report` or return it from main.
|
||||
#[unstable(feature = "error_reporter", issue = "90172")]
|
||||
impl<E> fmt::Debug for Report<E>
|
||||
where
|
||||
Report<E>: fmt::Display,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper type for indenting the inner source.
|
||||
struct Indented<'a, D> {
|
||||
inner: &'a mut D,
|
||||
}
|
||||
|
||||
impl<T> Write for Indented<'_, T>
|
||||
where
|
||||
T: Write,
|
||||
{
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
for (i, line) in s.split('\n').enumerate() {
|
||||
if i > 0 {
|
||||
self.inner.write_char('\n')?;
|
||||
self.inner.write_str(" ")?;
|
||||
}
|
||||
|
||||
self.inner.write_str(line)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
1
library/std/src/error.rs
Symbolic link
1
library/std/src/error.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/error.rs
|
||||
File diff suppressed because it is too large
Load Diff
1
library/std/src/fs.rs
Symbolic link
1
library/std/src/fs.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/fs.rs
|
||||
File diff suppressed because it is too large
Load Diff
1
library/std/src/keyword_docs.rs
Symbolic link
1
library/std/src/keyword_docs.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/keyword_docs.rs
|
||||
@@ -1,766 +0,0 @@
|
||||
//! # The Rust Standard Library
|
||||
//!
|
||||
//! The Rust Standard Library is the foundation of portable Rust software, a
|
||||
//! set of minimal and battle-tested shared abstractions for the [broader Rust
|
||||
//! ecosystem][crates.io]. It offers core types, like [`Vec<T>`] and
|
||||
//! [`Option<T>`], library-defined [operations on language
|
||||
//! primitives](#primitives), [standard macros](#macros), [I/O] and
|
||||
//! [multithreading], among [many other things][other].
|
||||
//!
|
||||
//! `std` is available to all Rust crates by default. Therefore, the
|
||||
//! standard library can be accessed in [`use`] statements through the path
|
||||
//! `std`, as in [`use std::env`].
|
||||
//!
|
||||
//! # How to read this documentation
|
||||
//!
|
||||
//! If you already know the name of what you are looking for, the fastest way to
|
||||
//! find it is to use the <a href="#" onclick="window.searchState.focus();">search
|
||||
//! button</a> at the top of the page.
|
||||
//!
|
||||
//! Otherwise, you may want to jump to one of these useful sections:
|
||||
//!
|
||||
//! * [`std::*` modules](#modules)
|
||||
//! * [Primitive types](#primitives)
|
||||
//! * [Standard macros](#macros)
|
||||
//! * [The Rust Prelude]
|
||||
//!
|
||||
//! If this is your first time, the documentation for the standard library is
|
||||
//! written to be casually perused. Clicking on interesting things should
|
||||
//! generally lead you to interesting places. Still, there are important bits
|
||||
//! you don't want to miss, so read on for a tour of the standard library and
|
||||
//! its documentation!
|
||||
//!
|
||||
//! Once you are familiar with the contents of the standard library you may
|
||||
//! begin to find the verbosity of the prose distracting. At this stage in your
|
||||
//! development you may want to press the
|
||||
//! "<svg style="width:0.75rem;height:0.75rem" viewBox="0 0 12 12" stroke="currentColor" fill="none"><path d="M2,2l4,4l4,-4M2,6l4,4l4,-4"/></svg> Summary"
|
||||
//! button near the top of the page to collapse it into a more skimmable view.
|
||||
//!
|
||||
//! While you are looking at the top of the page, also notice the
|
||||
//! "Source" link. Rust's API documentation comes with the source
|
||||
//! code and you are encouraged to read it. The standard library source is
|
||||
//! generally high quality and a peek behind the curtains is
|
||||
//! often enlightening.
|
||||
//!
|
||||
//! # What is in the standard library documentation?
|
||||
//!
|
||||
//! First of all, The Rust Standard Library is divided into a number of focused
|
||||
//! modules, [all listed further down this page](#modules). These modules are
|
||||
//! the bedrock upon which all of Rust is forged, and they have mighty names
|
||||
//! like [`std::slice`] and [`std::cmp`]. Modules' documentation typically
|
||||
//! includes an overview of the module along with examples, and are a smart
|
||||
//! place to start familiarizing yourself with the library.
|
||||
//!
|
||||
//! Second, implicit methods on [primitive types] are documented here. This can
|
||||
//! be a source of confusion for two reasons:
|
||||
//!
|
||||
//! 1. While primitives are implemented by the compiler, the standard library
|
||||
//! implements methods directly on the primitive types (and it is the only
|
||||
//! library that does so), which are [documented in the section on
|
||||
//! primitives](#primitives).
|
||||
//! 2. The standard library exports many modules *with the same name as
|
||||
//! primitive types*. These define additional items related to the primitive
|
||||
//! type, but not the all-important methods.
|
||||
//!
|
||||
//! So for example there is a [page for the primitive type
|
||||
//! `char`](primitive::char) that lists all the methods that can be called on
|
||||
//! characters (very useful), and there is a [page for the module
|
||||
//! `std::char`](crate::char) that documents iterator and error types created by these methods
|
||||
//! (rarely useful).
|
||||
//!
|
||||
//! Note the documentation for the primitives [`str`] and [`[T]`][prim@slice] (also
|
||||
//! called 'slice'). Many method calls on [`String`] and [`Vec<T>`] are actually
|
||||
//! calls to methods on [`str`] and [`[T]`][prim@slice] respectively, via [deref
|
||||
//! coercions][deref-coercions].
|
||||
//!
|
||||
//! Third, the standard library defines [The Rust Prelude], a small collection
|
||||
//! of items - mostly traits - that are imported into every module of every
|
||||
//! crate. The traits in the prelude are pervasive, making the prelude
|
||||
//! documentation a good entry point to learning about the library.
|
||||
//!
|
||||
//! And finally, the standard library exports a number of standard macros, and
|
||||
//! [lists them on this page](#macros) (technically, not all of the standard
|
||||
//! macros are defined by the standard library - some are defined by the
|
||||
//! compiler - but they are documented here the same). Like the prelude, the
|
||||
//! standard macros are imported by default into all crates.
|
||||
//!
|
||||
//! # Contributing changes to the documentation
|
||||
//!
|
||||
//! Check out the Rust contribution guidelines [here](
|
||||
//! https://rustc-dev-guide.rust-lang.org/contributing.html#writing-documentation).
|
||||
//! The source for this documentation can be found on
|
||||
//! [GitHub](https://github.com/rust-lang/rust) in the 'library/std/' directory.
|
||||
//! To contribute changes, make sure you read the guidelines first, then submit
|
||||
//! pull-requests for your suggested changes.
|
||||
//!
|
||||
//! Contributions are appreciated! If you see a part of the docs that can be
|
||||
//! improved, submit a PR, or chat with us first on [Zulip][rust-zulip]
|
||||
//! #docs.
|
||||
//!
|
||||
//! # A Tour of The Rust Standard Library
|
||||
//!
|
||||
//! The rest of this crate documentation is dedicated to pointing out notable
|
||||
//! features of The Rust Standard Library.
|
||||
//!
|
||||
//! ## Containers and collections
|
||||
//!
|
||||
//! The [`option`] and [`result`] modules define optional and error-handling
|
||||
//! types, [`Option<T>`] and [`Result<T, E>`]. The [`iter`] module defines
|
||||
//! Rust's iterator trait, [`Iterator`], which works with the [`for`] loop to
|
||||
//! access collections.
|
||||
//!
|
||||
//! The standard library exposes three common ways to deal with contiguous
|
||||
//! regions of memory:
|
||||
//!
|
||||
//! * [`Vec<T>`] - A heap-allocated *vector* that is resizable at runtime.
|
||||
//! * [`[T; N]`][prim@array] - An inline *array* with a fixed size at compile time.
|
||||
//! * [`[T]`][prim@slice] - A dynamically sized *slice* into any other kind of contiguous
|
||||
//! storage, whether heap-allocated or not.
|
||||
//!
|
||||
//! Slices can only be handled through some kind of *pointer*, and as such come
|
||||
//! in many flavors such as:
|
||||
//!
|
||||
//! * `&[T]` - *shared slice*
|
||||
//! * `&mut [T]` - *mutable slice*
|
||||
//! * [`Box<[T]>`][owned slice] - *owned slice*
|
||||
//!
|
||||
//! [`str`], a UTF-8 string slice, is a primitive type, and the standard library
|
||||
//! defines many methods for it. Rust [`str`]s are typically accessed as
|
||||
//! immutable references: `&str`. Use the owned [`String`] for building and
|
||||
//! mutating strings.
|
||||
//!
|
||||
//! For converting to strings use the [`format!`] macro, and for converting from
|
||||
//! strings use the [`FromStr`] trait.
|
||||
//!
|
||||
//! Data may be shared by placing it in a reference-counted box or the [`Rc`]
|
||||
//! type, and if further contained in a [`Cell`] or [`RefCell`], may be mutated
|
||||
//! as well as shared. Likewise, in a concurrent setting it is common to pair an
|
||||
//! atomically-reference-counted box, [`Arc`], with a [`Mutex`] to get the same
|
||||
//! effect.
|
||||
//!
|
||||
//! The [`collections`] module defines maps, sets, linked lists and other
|
||||
//! typical collection types, including the common [`HashMap<K, V>`].
|
||||
//!
|
||||
//! ## Platform abstractions and I/O
|
||||
//!
|
||||
//! Besides basic data types, the standard library is largely concerned with
|
||||
//! abstracting over differences in common platforms, most notably Windows and
|
||||
//! Unix derivatives.
|
||||
//!
|
||||
//! Common types of I/O, including [files], [TCP], and [UDP], are defined in
|
||||
//! the [`io`], [`fs`], and [`net`] modules.
|
||||
//!
|
||||
//! The [`thread`] module contains Rust's threading abstractions. [`sync`]
|
||||
//! contains further primitive shared memory types, including [`atomic`], [`mpmc`] and
|
||||
//! [`mpsc`], which contains the channel types for message passing.
|
||||
//!
|
||||
//! # Use before and after `main()`
|
||||
//!
|
||||
//! Many parts of the standard library are expected to work before and after `main()`;
|
||||
//! but this is not guaranteed or ensured by tests. It is recommended that you write your own tests
|
||||
//! and run them on each platform you wish to support.
|
||||
//! This means that use of `std` before/after main, especially of features that interact with the
|
||||
//! OS or global state, is exempted from stability and portability guarantees and instead only
|
||||
//! provided on a best-effort basis. Nevertheless bug reports are appreciated.
|
||||
//!
|
||||
//! On the other hand `core` and `alloc` are most likely to work in such environments with
|
||||
//! the caveat that any hookable behavior such as panics, oom handling or allocators will also
|
||||
//! depend on the compatibility of the hooks.
|
||||
//!
|
||||
//! Some features may also behave differently outside main, e.g. stdio could become unbuffered,
|
||||
//! some panics might turn into aborts, backtraces might not get symbolicated or similar.
|
||||
//!
|
||||
//! Non-exhaustive list of known limitations:
|
||||
//!
|
||||
//! - after-main use of thread-locals, which also affects additional features:
|
||||
//! - [`thread::current()`]
|
||||
//! - under UNIX, before main, file descriptors 0, 1, and 2 may be unchanged
|
||||
//! (they are guaranteed to be open during main,
|
||||
//! and are opened to /dev/null O_RDWR if they weren't open on program start)
|
||||
//!
|
||||
//!
|
||||
//! [I/O]: io
|
||||
//! [TCP]: net::TcpStream
|
||||
//! [The Rust Prelude]: prelude
|
||||
//! [UDP]: net::UdpSocket
|
||||
//! [`Arc`]: sync::Arc
|
||||
//! [owned slice]: boxed
|
||||
//! [`Cell`]: cell::Cell
|
||||
//! [`FromStr`]: str::FromStr
|
||||
//! [`HashMap<K, V>`]: collections::HashMap
|
||||
//! [`Mutex`]: sync::Mutex
|
||||
//! [`Option<T>`]: option::Option
|
||||
//! [`Rc`]: rc::Rc
|
||||
//! [`RefCell`]: cell::RefCell
|
||||
//! [`Result<T, E>`]: result::Result
|
||||
//! [`Vec<T>`]: vec::Vec
|
||||
//! [`atomic`]: sync::atomic
|
||||
//! [`for`]: ../book/ch03-05-control-flow.html#looping-through-a-collection-with-for
|
||||
//! [`str`]: prim@str
|
||||
//! [`mpmc`]: sync::mpmc
|
||||
//! [`mpsc`]: sync::mpsc
|
||||
//! [`std::cmp`]: cmp
|
||||
//! [`std::slice`]: mod@slice
|
||||
//! [`use std::env`]: env/index.html
|
||||
//! [`use`]: ../book/ch07-02-defining-modules-to-control-scope-and-privacy.html
|
||||
//! [crates.io]: https://crates.io
|
||||
//! [deref-coercions]: ../book/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods
|
||||
//! [files]: fs::File
|
||||
//! [multithreading]: thread
|
||||
//! [other]: #what-is-in-the-standard-library-documentation
|
||||
//! [primitive types]: ../book/ch03-02-data-types.html
|
||||
//! [rust-zulip]: https://rust-lang.zulipchat.com/
|
||||
//! [array]: prim@array
|
||||
//! [slice]: prim@slice
|
||||
|
||||
#![cfg_attr(not(restricted_std), stable(feature = "rust1", since = "1.0.0"))]
|
||||
#![cfg_attr(
|
||||
restricted_std,
|
||||
unstable(
|
||||
feature = "restricted_std",
|
||||
issue = "none",
|
||||
reason = "You have attempted to use a standard library built for a platform that it doesn't \
|
||||
know how to support. Consider building it for a known environment, disabling it with \
|
||||
`#![no_std]` or overriding this warning by enabling this feature."
|
||||
)
|
||||
)]
|
||||
#![rustc_preserve_ub_checks]
|
||||
#![doc(
|
||||
html_playground_url = "https://play.rust-lang.org/",
|
||||
issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
|
||||
test(no_crate_inject, attr(deny(warnings))),
|
||||
test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
|
||||
)]
|
||||
#![doc(rust_logo)]
|
||||
#![doc(auto_cfg(hide(no_global_oom_handling)))]
|
||||
// Don't link to std. We are std.
|
||||
#![no_std]
|
||||
// Tell the compiler to link to either panic_abort or panic_unwind
|
||||
#![needs_panic_runtime]
|
||||
//
|
||||
// Lints:
|
||||
#![warn(deprecated_in_future)]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(missing_debug_implementations)]
|
||||
#![allow(explicit_outlives_requirements)]
|
||||
#![allow(unused_lifetimes)]
|
||||
#![allow(internal_features)]
|
||||
#![deny(fuzzy_provenance_casts)]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
#![allow(rustdoc::redundant_explicit_links)]
|
||||
#![warn(rustdoc::unescaped_backticks)]
|
||||
// Ensure that std can be linked against panic_abort despite compiled with `-C panic=unwind`
|
||||
#![deny(ffi_unwind_calls)]
|
||||
// std may use features in a platform-specific way
|
||||
#![allow(unused_features)]
|
||||
//
|
||||
// Features:
|
||||
#![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count, rt))]
|
||||
#![cfg_attr(
|
||||
all(target_vendor = "fortanix", target_env = "sgx"),
|
||||
feature(slice_index_methods, coerce_unsized, sgx_platform)
|
||||
)]
|
||||
#![cfg_attr(all(test, target_os = "uefi"), feature(uefi_std))]
|
||||
#![cfg_attr(target_family = "wasm", feature(stdarch_wasm_atomic_wait))]
|
||||
#![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))]
|
||||
//
|
||||
// Language features:
|
||||
// tidy-alphabetical-start
|
||||
#![feature(alloc_error_handler)]
|
||||
#![feature(allocator_internals)]
|
||||
#![feature(allow_internal_unsafe)]
|
||||
#![feature(allow_internal_unstable)]
|
||||
#![feature(asm_experimental_arch)]
|
||||
#![feature(autodiff)]
|
||||
#![feature(cfg_sanitizer_cfi)]
|
||||
#![feature(cfg_target_thread_local)]
|
||||
#![feature(cfi_encoding)]
|
||||
#![feature(const_default)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(core_float_math)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(deprecated_suggestion)]
|
||||
#![feature(doc_cfg)]
|
||||
#![feature(doc_masked)]
|
||||
#![feature(doc_notable_trait)]
|
||||
#![feature(dropck_eyepatch)]
|
||||
#![feature(f16)]
|
||||
#![feature(f128)]
|
||||
#![feature(ffi_const)]
|
||||
#![feature(formatting_options)]
|
||||
#![feature(funnel_shifts)]
|
||||
#![feature(intra_doc_pointers)]
|
||||
#![feature(iter_advance_by)]
|
||||
#![feature(iter_next_chunk)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(link_cfg)]
|
||||
#![feature(linkage)]
|
||||
#![feature(macro_metavar_expr_concat)]
|
||||
#![feature(maybe_uninit_fill)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(must_not_suspend)]
|
||||
#![feature(needs_panic_runtime)]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(never_type)]
|
||||
#![feature(optimize_attribute)]
|
||||
#![feature(prelude_import)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(strict_provenance_lints)]
|
||||
#![feature(target_feature_inline_always)]
|
||||
#![feature(thread_local)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(try_trait_v2)]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![feature(uint_carryless_mul)]
|
||||
// tidy-alphabetical-end
|
||||
//
|
||||
// Library features (core):
|
||||
// tidy-alphabetical-start
|
||||
#![feature(bstr)]
|
||||
#![feature(bstr_internals)]
|
||||
#![feature(cast_maybe_uninit)]
|
||||
#![feature(char_internals)]
|
||||
#![feature(clone_to_uninit)]
|
||||
#![feature(const_convert)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(core_io_borrowed_buf)]
|
||||
#![feature(cstr_display)]
|
||||
#![feature(drop_guard)]
|
||||
#![feature(duration_constants)]
|
||||
#![feature(error_generic_member_access)]
|
||||
#![feature(error_iter)]
|
||||
#![feature(exact_size_is_empty)]
|
||||
#![feature(exclusive_wrapper)]
|
||||
#![feature(extend_one)]
|
||||
#![feature(float_algebraic)]
|
||||
#![feature(float_gamma)]
|
||||
#![feature(float_minimum_maximum)]
|
||||
#![feature(fmt_internals)]
|
||||
#![feature(fn_ptr_trait)]
|
||||
#![feature(generic_atomic)]
|
||||
#![feature(hasher_prefixfree_extras)]
|
||||
#![feature(hashmap_internals)]
|
||||
#![feature(hint_must_use)]
|
||||
#![feature(int_from_ascii)]
|
||||
#![feature(ip)]
|
||||
#![feature(maybe_uninit_array_assume_init)]
|
||||
#![feature(panic_can_unwind)]
|
||||
#![feature(panic_internals)]
|
||||
#![feature(pin_coerce_unsized_trait)]
|
||||
#![feature(pointer_is_aligned_to)]
|
||||
#![feature(portable_simd)]
|
||||
#![feature(ptr_as_uninit)]
|
||||
#![feature(ptr_mask)]
|
||||
#![feature(random)]
|
||||
#![feature(slice_internals)]
|
||||
#![feature(slice_ptr_get)]
|
||||
#![feature(slice_range)]
|
||||
#![feature(slice_split_once)]
|
||||
#![feature(std_internals)]
|
||||
#![feature(str_internals)]
|
||||
#![feature(sync_unsafe_cell)]
|
||||
#![feature(temporary_niche_types)]
|
||||
#![feature(ub_checks)]
|
||||
#![feature(used_with_arg)]
|
||||
// tidy-alphabetical-end
|
||||
//
|
||||
// Library features (alloc):
|
||||
// tidy-alphabetical-start
|
||||
#![feature(allocator_api)]
|
||||
#![feature(clone_from_ref)]
|
||||
#![feature(get_mut_unchecked)]
|
||||
#![feature(map_try_insert)]
|
||||
#![feature(slice_concat_trait)]
|
||||
#![feature(thin_box)]
|
||||
#![feature(try_reserve_kind)]
|
||||
#![feature(try_with_capacity)]
|
||||
#![feature(unique_rc_arc)]
|
||||
#![feature(wtf8_internals)]
|
||||
// tidy-alphabetical-end
|
||||
//
|
||||
// Library features (unwind):
|
||||
// tidy-alphabetical-start
|
||||
#![feature(panic_unwind)]
|
||||
// tidy-alphabetical-end
|
||||
//
|
||||
// Library features (std_detect):
|
||||
// tidy-alphabetical-start
|
||||
#![feature(stdarch_internal)]
|
||||
// tidy-alphabetical-end
|
||||
//
|
||||
// Only for re-exporting:
|
||||
// tidy-alphabetical-start
|
||||
#![feature(async_iterator)]
|
||||
#![feature(c_variadic)]
|
||||
#![feature(cfg_accessible)]
|
||||
#![feature(cfg_eval)]
|
||||
#![feature(concat_bytes)]
|
||||
#![feature(const_format_args)]
|
||||
#![feature(custom_test_frameworks)]
|
||||
#![feature(edition_panic)]
|
||||
#![feature(format_args_nl)]
|
||||
#![feature(log_syntax)]
|
||||
#![feature(test)]
|
||||
#![feature(trace_macros)]
|
||||
// tidy-alphabetical-end
|
||||
//
|
||||
// Only used in tests/benchmarks:
|
||||
//
|
||||
// Only for const-ness:
|
||||
// tidy-alphabetical-start
|
||||
#![feature(io_const_error)]
|
||||
// tidy-alphabetical-end
|
||||
//
|
||||
#![default_lib_allocator]
|
||||
|
||||
// The Rust prelude
|
||||
// The compiler expects the prelude definition to be defined before its use statement.
|
||||
pub mod prelude;
|
||||
|
||||
// Explicitly import the prelude. The compiler uses this same unstable attribute
|
||||
// to import the prelude implicitly when building crates that depend on std.
|
||||
#[prelude_import]
|
||||
#[allow(unused)]
|
||||
use prelude::rust_2024::*;
|
||||
|
||||
// Access to Bencher, etc.
|
||||
#[cfg(test)]
|
||||
extern crate test;
|
||||
|
||||
#[allow(unused_imports)] // macros from `alloc` are not used on all platforms
|
||||
#[macro_use]
|
||||
extern crate alloc as alloc_crate;
|
||||
|
||||
// Many compiler tests depend on libc being pulled in by std
|
||||
// so include it here even if it's unused.
|
||||
#[doc(masked)]
|
||||
#[allow(unused_extern_crates)]
|
||||
#[cfg(not(all(windows, target_env = "msvc")))]
|
||||
extern crate libc;
|
||||
|
||||
// We always need an unwinder currently for backtraces
|
||||
#[doc(masked)]
|
||||
#[allow(unused_extern_crates)]
|
||||
extern crate unwind;
|
||||
|
||||
// FIXME: #94122 this extern crate definition only exist here to stop
|
||||
// miniz_oxide docs leaking into std docs. Find better way to do it.
|
||||
// Remove exclusion from tidy platform check when this removed.
|
||||
#[doc(masked)]
|
||||
#[allow(unused_extern_crates)]
|
||||
#[cfg(all(
|
||||
not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))),
|
||||
feature = "miniz_oxide"
|
||||
))]
|
||||
extern crate miniz_oxide;
|
||||
|
||||
// During testing, this crate is not actually the "real" std library, but rather
|
||||
// it links to the real std library, which was compiled from this same source
|
||||
// code. So any lang items std defines are conditionally excluded (or else they
|
||||
// would generate duplicate lang item errors), and any globals it defines are
|
||||
// _not_ the globals used by "real" std. So this import, defined only during
|
||||
// testing gives test-std access to real-std lang items and globals. See #2912
|
||||
#[cfg(test)]
|
||||
extern crate std as realstd;
|
||||
|
||||
// The standard macros that are not built-in to the compiler.
|
||||
#[macro_use]
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "std_internals", issue = "none")]
|
||||
pub mod macros;
|
||||
|
||||
// The runtime entry point and a few unstable public functions used by the
|
||||
// compiler
|
||||
#[macro_use]
|
||||
pub mod rt;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::any;
|
||||
#[stable(feature = "core_array", since = "1.35.0")]
|
||||
pub use core::array;
|
||||
#[unstable(feature = "async_iterator", issue = "79024")]
|
||||
pub use core::async_iter;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::cell;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::char;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::clone;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::cmp;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::convert;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::default;
|
||||
#[unstable(feature = "field_projections", issue = "145383")]
|
||||
pub use core::field;
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub use core::future;
|
||||
#[stable(feature = "core_hint", since = "1.27.0")]
|
||||
pub use core::hint;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use core::i8;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use core::i16;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use core::i32;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use core::i64;
|
||||
#[stable(feature = "i128", since = "1.26.0")]
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use core::i128;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::intrinsics;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use core::isize;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::iter;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::marker;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::mem;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::ops;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::option;
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
pub use core::pin;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::ptr;
|
||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||
pub use core::range;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::result;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use core::u8;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use core::u16;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use core::u32;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use core::u64;
|
||||
#[stable(feature = "i128", since = "1.26.0")]
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use core::u128;
|
||||
#[unstable(feature = "unsafe_binders", issue = "130516")]
|
||||
pub use core::unsafe_binder;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use core::usize;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use alloc_crate::borrow;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use alloc_crate::boxed;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use alloc_crate::fmt;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use alloc_crate::format;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use alloc_crate::rc;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use alloc_crate::slice;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use alloc_crate::str;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use alloc_crate::string;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use alloc_crate::vec;
|
||||
|
||||
#[path = "num/f128.rs"]
|
||||
pub mod f128;
|
||||
#[path = "num/f16.rs"]
|
||||
pub mod f16;
|
||||
#[path = "num/f32.rs"]
|
||||
pub mod f32;
|
||||
#[path = "num/f64.rs"]
|
||||
pub mod f64;
|
||||
|
||||
#[macro_use]
|
||||
pub mod thread;
|
||||
pub mod ascii;
|
||||
pub mod backtrace;
|
||||
#[unstable(feature = "bstr", issue = "134915")]
|
||||
pub mod bstr;
|
||||
pub mod collections;
|
||||
pub mod env;
|
||||
pub mod error;
|
||||
pub mod ffi;
|
||||
pub mod fs;
|
||||
pub mod hash;
|
||||
pub mod io;
|
||||
pub mod net;
|
||||
pub mod num;
|
||||
pub mod os;
|
||||
pub mod panic;
|
||||
#[unstable(feature = "pattern_type_macro", issue = "123646")]
|
||||
pub mod pat;
|
||||
pub mod path;
|
||||
pub mod process;
|
||||
#[unstable(feature = "random", issue = "130703")]
|
||||
pub mod random;
|
||||
pub mod sync;
|
||||
pub mod time;
|
||||
|
||||
// Pull in `std_float` crate into std. The contents of
|
||||
// `std_float` are in a different repository: rust-lang/portable-simd.
|
||||
#[path = "../../portable-simd/crates/std_float/src/lib.rs"]
|
||||
#[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn)]
|
||||
#[allow(rustdoc::bare_urls)]
|
||||
#[unstable(feature = "portable_simd", issue = "86656")]
|
||||
mod std_float;
|
||||
|
||||
#[unstable(feature = "portable_simd", issue = "86656")]
|
||||
pub mod simd {
|
||||
#![doc = include_str!("../../portable-simd/crates/core_simd/src/core_simd_docs.md")]
|
||||
|
||||
#[doc(inline)]
|
||||
pub use core::simd::*;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use crate::std_float::StdFloat;
|
||||
}
|
||||
|
||||
#[unstable(feature = "autodiff", issue = "124509")]
|
||||
/// This module provides support for automatic differentiation.
|
||||
pub mod autodiff {
|
||||
/// This macro handles automatic differentiation.
|
||||
pub use core::autodiff::{autodiff_forward, autodiff_reverse};
|
||||
}
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub mod task {
|
||||
//! Types and Traits for working with asynchronous tasks.
|
||||
|
||||
#[doc(inline)]
|
||||
#[stable(feature = "wake_trait", since = "1.51.0")]
|
||||
pub use alloc::task::*;
|
||||
#[doc(inline)]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub use core::task::*;
|
||||
}
|
||||
|
||||
#[doc = include_str!("../../stdarch/crates/core_arch/src/core_arch_docs.md")]
|
||||
#[stable(feature = "simd_arch", since = "1.27.0")]
|
||||
pub mod arch {
|
||||
#[stable(feature = "simd_arch", since = "1.27.0")]
|
||||
// The `no_inline`-attribute is required to make the documentation of all
|
||||
// targets available.
|
||||
// See https://github.com/rust-lang/rust/pull/57808#issuecomment-457390549 for
|
||||
// more information.
|
||||
#[doc(no_inline)] // Note (#82861): required for correct documentation
|
||||
pub use core::arch::*;
|
||||
|
||||
#[stable(feature = "simd_aarch64", since = "1.60.0")]
|
||||
pub use std_detect::is_aarch64_feature_detected;
|
||||
#[unstable(feature = "stdarch_arm_feature_detection", issue = "111190")]
|
||||
pub use std_detect::is_arm_feature_detected;
|
||||
#[unstable(feature = "is_loongarch_feature_detected", issue = "117425")]
|
||||
pub use std_detect::is_loongarch_feature_detected;
|
||||
#[unstable(feature = "is_riscv_feature_detected", issue = "111192")]
|
||||
pub use std_detect::is_riscv_feature_detected;
|
||||
#[stable(feature = "stdarch_s390x_feature_detection", since = "1.93.0")]
|
||||
pub use std_detect::is_s390x_feature_detected;
|
||||
#[stable(feature = "simd_x86", since = "1.27.0")]
|
||||
pub use std_detect::is_x86_feature_detected;
|
||||
#[unstable(feature = "stdarch_mips_feature_detection", issue = "111188")]
|
||||
pub use std_detect::{is_mips_feature_detected, is_mips64_feature_detected};
|
||||
#[unstable(feature = "stdarch_powerpc_feature_detection", issue = "111191")]
|
||||
pub use std_detect::{is_powerpc_feature_detected, is_powerpc64_feature_detected};
|
||||
}
|
||||
|
||||
// This was stabilized in the crate root so we have to keep it there.
|
||||
#[stable(feature = "simd_x86", since = "1.27.0")]
|
||||
pub use std_detect::is_x86_feature_detected;
|
||||
|
||||
mod sys;
|
||||
|
||||
pub mod alloc;
|
||||
|
||||
// Private support modules
|
||||
mod panicking;
|
||||
|
||||
#[path = "../../backtrace/src/lib.rs"]
|
||||
#[allow(dead_code, unused_attributes, fuzzy_provenance_casts, unsafe_op_in_unsafe_fn)]
|
||||
mod backtrace_rs;
|
||||
|
||||
#[stable(feature = "cfg_select", since = "1.95.0")]
|
||||
pub use core::cfg_select;
|
||||
#[unstable(
|
||||
feature = "concat_bytes",
|
||||
issue = "87555",
|
||||
reason = "`concat_bytes` is not stable enough for use and is subject to change"
|
||||
)]
|
||||
pub use core::concat_bytes;
|
||||
#[stable(feature = "matches_macro", since = "1.42.0")]
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use core::matches;
|
||||
#[stable(feature = "core_primitive", since = "1.43.0")]
|
||||
pub use core::primitive;
|
||||
#[stable(feature = "todo_macro", since = "1.40.0")]
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use core::todo;
|
||||
// Re-export built-in macros defined through core.
|
||||
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||
pub use core::{
|
||||
assert, cfg, column, compile_error, concat, const_format_args, env, file, format_args,
|
||||
format_args_nl, include, include_bytes, include_str, line, log_syntax, module_path, option_env,
|
||||
stringify, trace_macros,
|
||||
};
|
||||
// Re-export macros defined in core.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use core::{
|
||||
assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, r#try, unimplemented,
|
||||
unreachable, write, writeln,
|
||||
};
|
||||
#[stable(feature = "assert_matches", since = "1.95.0")]
|
||||
pub use core::{assert_matches, debug_assert_matches};
|
||||
|
||||
// Re-export unstable derive macro defined through core.
|
||||
#[unstable(feature = "derive_from", issue = "144889")]
|
||||
/// Unstable module containing the unstable `From` derive macro.
|
||||
pub mod from {
|
||||
#[unstable(feature = "derive_from", issue = "144889")]
|
||||
pub use core::from::From;
|
||||
}
|
||||
|
||||
// Include a number of private modules that exist solely to provide
|
||||
// the rustdoc documentation for primitive types. Using `include!`
|
||||
// because rustdoc only looks for these modules at the crate level.
|
||||
include!("../../core/src/primitive_docs.rs");
|
||||
|
||||
// Include a number of private modules that exist solely to provide
|
||||
// the rustdoc documentation for the existing keywords. Using `include!`
|
||||
// because rustdoc only looks for these modules at the crate level.
|
||||
include!("keyword_docs.rs");
|
||||
|
||||
// This is required to avoid an unstable error when `restricted-std` is not
|
||||
// enabled. The use of #![feature(restricted_std)] in rustc-std-workspace-std
|
||||
// is unconditional, so the unstable feature needs to be defined somewhere.
|
||||
#[unstable(feature = "restricted_std", issue = "none")]
|
||||
mod __restricted_std_workaround {}
|
||||
|
||||
mod sealed {
|
||||
/// This trait being unreachable from outside the crate
|
||||
/// prevents outside implementations of our extension traits.
|
||||
/// This allows adding more trait methods in the future.
|
||||
#[unstable(feature = "sealed", issue = "none")]
|
||||
pub trait Sealed {}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(dead_code)] // Not used in all configurations.
|
||||
pub(crate) mod test_helpers;
|
||||
1
library/std/src/lib.rs
Symbolic link
1
library/std/src/lib.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/lib.rs
|
||||
@@ -1,416 +0,0 @@
|
||||
//! Standard library macros
|
||||
//!
|
||||
//! This module contains a set of macros which are exported from the standard
|
||||
//! library. Each macro is available for use when linking against the standard
|
||||
//! library.
|
||||
// ignore-tidy-dbg
|
||||
|
||||
#[doc = include_str!("../../core/src/macros/panic.md")]
|
||||
#[macro_export]
|
||||
#[rustc_builtin_macro(std_panic)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow_internal_unstable(edition_panic)]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_macro")]
|
||||
macro_rules! panic {
|
||||
// Expands to either `$crate::panic::panic_2015` or `$crate::panic::panic_2021`
|
||||
// depending on the edition of the caller.
|
||||
($($arg:tt)*) => {
|
||||
/* compiler built-in */
|
||||
};
|
||||
}
|
||||
|
||||
/// Prints to the standard output.
|
||||
///
|
||||
/// Equivalent to the [`println!`] macro except that a newline is not printed at
|
||||
/// the end of the message.
|
||||
///
|
||||
/// Note that stdout is frequently line-buffered by default so it may be
|
||||
/// necessary to use [`io::stdout().flush()`][flush] to ensure the output is emitted
|
||||
/// immediately.
|
||||
///
|
||||
/// The `print!` macro will lock the standard output on each call. If you call
|
||||
/// `print!` within a hot loop, this behavior may be the bottleneck of the loop.
|
||||
/// To avoid this, lock stdout with [`io::stdout().lock()`][lock]:
|
||||
/// ```
|
||||
/// use std::io::{stdout, Write};
|
||||
///
|
||||
/// let mut lock = stdout().lock();
|
||||
/// write!(lock, "hello world").unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// Use `print!` only for the primary output of your program. Use
|
||||
/// [`eprint!`] instead to print error and progress messages.
|
||||
///
|
||||
/// See the formatting documentation in [`std::fmt`](crate::fmt)
|
||||
/// for details of the macro argument syntax.
|
||||
///
|
||||
/// [flush]: crate::io::Write::flush
|
||||
/// [`println!`]: crate::println
|
||||
/// [`eprint!`]: crate::eprint
|
||||
/// [lock]: crate::io::Stdout
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if writing to `io::stdout()` fails.
|
||||
///
|
||||
/// Writing to non-blocking stdout can cause an error, which will lead
|
||||
/// this macro to panic.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::{self, Write};
|
||||
///
|
||||
/// print!("this ");
|
||||
/// print!("will ");
|
||||
/// print!("be ");
|
||||
/// print!("on ");
|
||||
/// print!("the ");
|
||||
/// print!("same ");
|
||||
/// print!("line ");
|
||||
///
|
||||
/// io::stdout().flush().unwrap();
|
||||
///
|
||||
/// print!("this string has a newline, why not choose println! instead?\n");
|
||||
///
|
||||
/// io::stdout().flush().unwrap();
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "print_macro")]
|
||||
#[allow_internal_unstable(print_internals)]
|
||||
macro_rules! print {
|
||||
($($arg:tt)*) => {{
|
||||
$crate::io::_print($crate::format_args!($($arg)*));
|
||||
}};
|
||||
}
|
||||
|
||||
/// Prints to the standard output, with a newline.
|
||||
///
|
||||
/// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone
|
||||
/// (no additional CARRIAGE RETURN (`\r`/`U+000D`)).
|
||||
///
|
||||
/// This macro uses the same syntax as [`format!`], but writes to the standard output instead.
|
||||
/// See [`std::fmt`] for more information.
|
||||
///
|
||||
/// The `println!` macro will lock the standard output on each call. If you call
|
||||
/// `println!` within a hot loop, this behavior may be the bottleneck of the loop.
|
||||
/// To avoid this, lock stdout with [`io::stdout().lock()`][lock]:
|
||||
/// ```
|
||||
/// use std::io::{stdout, Write};
|
||||
///
|
||||
/// let mut lock = stdout().lock();
|
||||
/// writeln!(lock, "hello world").unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// Use `println!` only for the primary output of your program. Use
|
||||
/// [`eprintln!`] instead to print error and progress messages.
|
||||
///
|
||||
/// See the formatting documentation in [`std::fmt`](crate::fmt)
|
||||
/// for details of the macro argument syntax.
|
||||
///
|
||||
/// [`std::fmt`]: crate::fmt
|
||||
/// [`eprintln!`]: crate::eprintln
|
||||
/// [lock]: crate::io::Stdout
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if writing to [`io::stdout`] fails.
|
||||
///
|
||||
/// Writing to non-blocking stdout can cause an error, which will lead
|
||||
/// this macro to panic.
|
||||
///
|
||||
/// [`io::stdout`]: crate::io::stdout
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// println!(); // prints just a newline
|
||||
/// println!("hello there!");
|
||||
/// println!("format {} arguments", "some");
|
||||
/// let local_variable = "some";
|
||||
/// println!("format {local_variable} arguments");
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "println_macro")]
|
||||
#[allow_internal_unstable(print_internals, format_args_nl)]
|
||||
macro_rules! println {
|
||||
() => {
|
||||
$crate::print!("\n")
|
||||
};
|
||||
($($arg:tt)*) => {{
|
||||
$crate::io::_print($crate::format_args_nl!($($arg)*));
|
||||
}};
|
||||
}
|
||||
|
||||
/// Prints to the standard error.
|
||||
///
|
||||
/// Equivalent to the [`print!`] macro, except that output goes to
|
||||
/// [`io::stderr`] instead of [`io::stdout`]. See [`print!`] for
|
||||
/// example usage.
|
||||
///
|
||||
/// Use `eprint!` only for error and progress messages. Use `print!`
|
||||
/// instead for the primary output of your program.
|
||||
///
|
||||
/// [`io::stderr`]: crate::io::stderr
|
||||
/// [`io::stdout`]: crate::io::stdout
|
||||
///
|
||||
/// See the formatting documentation in [`std::fmt`](crate::fmt)
|
||||
/// for details of the macro argument syntax.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if writing to `io::stderr` fails.
|
||||
///
|
||||
/// Writing to non-blocking stderr can cause an error, which will lead
|
||||
/// this macro to panic.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// eprint!("Error: Could not complete task");
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[stable(feature = "eprint", since = "1.19.0")]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "eprint_macro")]
|
||||
#[allow_internal_unstable(print_internals)]
|
||||
macro_rules! eprint {
|
||||
($($arg:tt)*) => {{
|
||||
$crate::io::_eprint($crate::format_args!($($arg)*));
|
||||
}};
|
||||
}
|
||||
|
||||
/// Prints to the standard error, with a newline.
|
||||
///
|
||||
/// Equivalent to the [`println!`] macro, except that output goes to
|
||||
/// [`io::stderr`] instead of [`io::stdout`]. See [`println!`] for
|
||||
/// example usage.
|
||||
///
|
||||
/// Use `eprintln!` only for error and progress messages. Use `println!`
|
||||
/// instead for the primary output of your program.
|
||||
///
|
||||
/// See the formatting documentation in [`std::fmt`](crate::fmt)
|
||||
/// for details of the macro argument syntax.
|
||||
///
|
||||
/// [`io::stderr`]: crate::io::stderr
|
||||
/// [`io::stdout`]: crate::io::stdout
|
||||
/// [`println!`]: crate::println
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if writing to `io::stderr` fails.
|
||||
///
|
||||
/// Writing to non-blocking stderr can cause an error, which will lead
|
||||
/// this macro to panic.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// eprintln!("Error: Could not complete task");
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[stable(feature = "eprint", since = "1.19.0")]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "eprintln_macro")]
|
||||
#[allow_internal_unstable(print_internals, format_args_nl)]
|
||||
macro_rules! eprintln {
|
||||
() => {
|
||||
$crate::eprint!("\n")
|
||||
};
|
||||
($($arg:tt)*) => {{
|
||||
$crate::io::_eprint($crate::format_args_nl!($($arg)*));
|
||||
}};
|
||||
}
|
||||
|
||||
/// Prints and returns the value of a given expression for quick and dirty
|
||||
/// debugging.
|
||||
///
|
||||
/// An example:
|
||||
///
|
||||
/// ```rust
|
||||
/// let a = 2;
|
||||
/// let b = dbg!(a * 2) + 1;
|
||||
/// // ^-- prints: [src/main.rs:2:9] a * 2 = 4
|
||||
/// assert_eq!(b, 5);
|
||||
/// ```
|
||||
///
|
||||
/// The macro works by using the `Debug` implementation of the type of
|
||||
/// the given expression to print the value to [stderr] along with the
|
||||
/// source location of the macro invocation as well as the source code
|
||||
/// of the expression.
|
||||
///
|
||||
/// Invoking the macro on an expression moves and takes ownership of it
|
||||
/// before returning the evaluated expression unchanged. If the type
|
||||
/// of the expression does not implement `Copy` and you don't want
|
||||
/// to give up ownership, you can instead borrow with `dbg!(&expr)`
|
||||
/// for some expression `expr`.
|
||||
///
|
||||
/// The `dbg!` macro works exactly the same in release builds.
|
||||
/// This is useful when debugging issues that only occur in release
|
||||
/// builds or when debugging in release mode is significantly faster.
|
||||
///
|
||||
/// Note that the macro is intended as a debugging tool and therefore you
|
||||
/// should avoid having uses of it in version control for long periods
|
||||
/// (other than in tests and similar).
|
||||
/// Debug output from production code is better done with other facilities
|
||||
/// such as the [`debug!`] macro from the [`log`] crate.
|
||||
///
|
||||
/// # Stability
|
||||
///
|
||||
/// The exact output printed by this macro should not be relied upon
|
||||
/// and is subject to future changes.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if writing to `io::stderr` fails.
|
||||
///
|
||||
/// # Further examples
|
||||
///
|
||||
/// With a method call:
|
||||
///
|
||||
/// ```rust
|
||||
/// fn foo(n: usize) {
|
||||
/// if let Some(_) = dbg!(n.checked_sub(4)) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// foo(3)
|
||||
/// ```
|
||||
///
|
||||
/// This prints to [stderr]:
|
||||
///
|
||||
/// ```text,ignore
|
||||
/// [src/main.rs:2:22] n.checked_sub(4) = None
|
||||
/// ```
|
||||
///
|
||||
/// Naive factorial implementation:
|
||||
///
|
||||
/// ```rust
|
||||
/// fn factorial(n: u32) -> u32 {
|
||||
/// if dbg!(n <= 1) {
|
||||
/// dbg!(1)
|
||||
/// } else {
|
||||
/// dbg!(n * factorial(n - 1))
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// dbg!(factorial(4));
|
||||
/// ```
|
||||
///
|
||||
/// This prints to [stderr]:
|
||||
///
|
||||
/// ```text,ignore
|
||||
/// [src/main.rs:2:8] n <= 1 = false
|
||||
/// [src/main.rs:2:8] n <= 1 = false
|
||||
/// [src/main.rs:2:8] n <= 1 = false
|
||||
/// [src/main.rs:2:8] n <= 1 = true
|
||||
/// [src/main.rs:3:9] 1 = 1
|
||||
/// [src/main.rs:7:9] n * factorial(n - 1) = 2
|
||||
/// [src/main.rs:7:9] n * factorial(n - 1) = 6
|
||||
/// [src/main.rs:7:9] n * factorial(n - 1) = 24
|
||||
/// [src/main.rs:9:1] factorial(4) = 24
|
||||
/// ```
|
||||
///
|
||||
/// The `dbg!(..)` macro moves the input:
|
||||
///
|
||||
/// ```compile_fail
|
||||
/// /// A wrapper around `usize` which importantly is not Copyable.
|
||||
/// #[derive(Debug)]
|
||||
/// struct NoCopy(usize);
|
||||
///
|
||||
/// let a = NoCopy(42);
|
||||
/// let _ = dbg!(a); // <-- `a` is moved here.
|
||||
/// let _ = dbg!(a); // <-- `a` is moved again; error!
|
||||
/// ```
|
||||
///
|
||||
/// You can also use `dbg!()` without a value to just print the
|
||||
/// file and line whenever it's reached.
|
||||
///
|
||||
/// Finally, if you want to `dbg!(..)` multiple values, it will treat them as
|
||||
/// a tuple (and return it, too):
|
||||
///
|
||||
/// ```
|
||||
/// assert_eq!(dbg!(1usize, 2u32), (1, 2));
|
||||
/// ```
|
||||
///
|
||||
/// However, a single argument with a trailing comma will still not be treated
|
||||
/// as a tuple, following the convention of ignoring trailing commas in macro
|
||||
/// invocations. You can use a 1-tuple directly if you need one:
|
||||
///
|
||||
/// ```
|
||||
/// assert_eq!(1, dbg!(1u32,)); // trailing comma ignored
|
||||
/// assert_eq!((1,), dbg!((1u32,))); // 1-tuple
|
||||
/// ```
|
||||
///
|
||||
/// [stderr]: https://en.wikipedia.org/wiki/Standard_streams#Standard_error_(stderr)
|
||||
/// [`debug!`]: https://docs.rs/log/*/log/macro.debug.html
|
||||
/// [`log`]: https://crates.io/crates/log
|
||||
#[macro_export]
|
||||
#[allow_internal_unstable(std_internals)]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "dbg_macro")]
|
||||
#[stable(feature = "dbg_macro", since = "1.32.0")]
|
||||
macro_rules! dbg {
|
||||
() => {
|
||||
$crate::eprintln!("[{}:{}:{}]", $crate::file!(), $crate::line!(), $crate::column!())
|
||||
};
|
||||
($($val:expr),+ $(,)?) => {
|
||||
$crate::macros::dbg_internal!(() () ($($val),+))
|
||||
};
|
||||
}
|
||||
|
||||
/// Internal macro that processes a list of expressions and produces a chain of
|
||||
/// nested `match`es, one for each expression, before finally calling `eprint!`
|
||||
/// with the collected information and returning all the evaluated expressions
|
||||
/// in a tuple.
|
||||
///
|
||||
/// E.g. `dbg_internal!(() () (1, 2))` expands into
|
||||
/// ```rust, ignore
|
||||
/// match 1 {
|
||||
/// tmp_1 => match 2 {
|
||||
/// tmp_2 => {
|
||||
/// eprint!("...", &tmp_1, &tmp_2, /* some other arguments */);
|
||||
/// (tmp_1, tmp_2)
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This is necessary so that `dbg!` outputs don't get torn, see #136703.
|
||||
#[doc(hidden)]
|
||||
#[rustc_macro_transparency = "semiopaque"]
|
||||
pub macro dbg_internal {
|
||||
(($($piece:literal),+) ($($processed:expr => $bound:expr),+) ()) => {{
|
||||
$crate::eprint!(
|
||||
$crate::concat!($($piece),+),
|
||||
$(
|
||||
$crate::stringify!($processed),
|
||||
// The `&T: Debug` check happens here (not in the format literal desugaring)
|
||||
// to avoid format literal related messages and suggestions.
|
||||
&&$bound as &dyn $crate::fmt::Debug
|
||||
),+,
|
||||
// The location returned here is that of the macro invocation, so
|
||||
// it will be the same for all expressions. Thus, label these
|
||||
// arguments so that they can be reused in every piece of the
|
||||
// formatting template.
|
||||
file=$crate::file!(),
|
||||
line=$crate::line!(),
|
||||
column=$crate::column!()
|
||||
);
|
||||
// Comma separate the variables only when necessary so that this will
|
||||
// not yield a tuple for a single expression, but rather just parenthesize
|
||||
// the expression.
|
||||
($($bound),+)
|
||||
}},
|
||||
(($($piece:literal),*) ($($processed:expr => $bound:expr),*) ($val:expr $(,$rest:expr)*)) => {
|
||||
// Use of `match` here is intentional because it affects the lifetimes
|
||||
// of temporaries - https://stackoverflow.com/a/48732525/1063961
|
||||
match $val {
|
||||
tmp => $crate::macros::dbg_internal!(
|
||||
($($piece,)* "[{file}:{line}:{column}] {} = {:#?}\n")
|
||||
($($processed => $bound,)* $val => tmp)
|
||||
($($rest),*)
|
||||
),
|
||||
}
|
||||
},
|
||||
}
|
||||
1
library/std/src/macros.rs
Symbolic link
1
library/std/src/macros.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/macros.rs
|
||||
@@ -1,198 +0,0 @@
|
||||
//! OS-specific functionality.
|
||||
|
||||
#![stable(feature = "os", since = "1.0.0")]
|
||||
#![allow(missing_docs, nonstandard_style, missing_debug_implementations)]
|
||||
#![allow(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
pub mod raw;
|
||||
|
||||
// The code below could be written clearer using `cfg_if!`. However, the items below are
|
||||
// publicly exported by `std` and external tools can have trouble analysing them because of the use
|
||||
// of a macro that is not vendored by Rust and included in the toolchain.
|
||||
// See https://github.com/rust-analyzer/rust-analyzer/issues/6038.
|
||||
|
||||
// On certain platforms right now the "main modules" modules that are
|
||||
// documented don't compile (missing things in `libc` which is empty),
|
||||
// so just omit them with an empty module and add the "unstable" attribute.
|
||||
|
||||
// darwin, unix, linux, wasi and windows are handled a bit differently.
|
||||
#[cfg(all(
|
||||
doc,
|
||||
any(
|
||||
all(target_arch = "wasm32", not(target_os = "wasi")),
|
||||
all(target_vendor = "fortanix", target_env = "sgx")
|
||||
)
|
||||
))]
|
||||
#[unstable(issue = "none", feature = "std_internals")]
|
||||
pub mod darwin {}
|
||||
#[cfg(all(
|
||||
doc,
|
||||
any(
|
||||
all(target_arch = "wasm32", not(target_os = "wasi")),
|
||||
all(target_vendor = "fortanix", target_env = "sgx")
|
||||
)
|
||||
))]
|
||||
#[unstable(issue = "none", feature = "std_internals")]
|
||||
pub mod unix {}
|
||||
#[cfg(all(
|
||||
doc,
|
||||
any(
|
||||
all(target_arch = "wasm32", not(target_os = "wasi")),
|
||||
all(target_vendor = "fortanix", target_env = "sgx")
|
||||
)
|
||||
))]
|
||||
#[unstable(issue = "none", feature = "std_internals")]
|
||||
pub mod linux {}
|
||||
#[cfg(all(
|
||||
doc,
|
||||
any(
|
||||
all(target_arch = "wasm32", not(target_os = "wasi")),
|
||||
all(target_vendor = "fortanix", target_env = "sgx")
|
||||
)
|
||||
))]
|
||||
#[unstable(issue = "none", feature = "std_internals")]
|
||||
pub mod wasi {}
|
||||
#[cfg(all(
|
||||
doc,
|
||||
any(
|
||||
all(target_arch = "wasm32", not(target_os = "wasi")),
|
||||
all(target_vendor = "fortanix", target_env = "sgx")
|
||||
)
|
||||
))]
|
||||
#[unstable(issue = "none", feature = "std_internals")]
|
||||
pub mod windows {}
|
||||
|
||||
// darwin
|
||||
#[cfg(not(all(
|
||||
doc,
|
||||
any(
|
||||
all(target_arch = "wasm32", not(target_os = "wasi")),
|
||||
all(target_vendor = "fortanix", target_env = "sgx")
|
||||
)
|
||||
)))]
|
||||
#[cfg(any(target_vendor = "apple", doc))]
|
||||
pub mod darwin;
|
||||
|
||||
// unix
|
||||
#[cfg(not(all(
|
||||
doc,
|
||||
any(
|
||||
all(target_arch = "wasm32", not(target_os = "wasi")),
|
||||
all(target_vendor = "fortanix", target_env = "sgx")
|
||||
)
|
||||
)))]
|
||||
#[cfg(all(not(target_os = "hermit"), any(unix, doc)))]
|
||||
pub mod unix;
|
||||
|
||||
// linux
|
||||
#[cfg(not(all(
|
||||
doc,
|
||||
any(
|
||||
all(target_arch = "wasm32", not(target_os = "wasi")),
|
||||
all(target_vendor = "fortanix", target_env = "sgx")
|
||||
)
|
||||
)))]
|
||||
#[cfg(any(target_os = "linux", doc))]
|
||||
pub mod linux;
|
||||
|
||||
// wasi
|
||||
#[cfg(not(all(
|
||||
doc,
|
||||
any(
|
||||
all(target_arch = "wasm32", not(target_os = "wasi")),
|
||||
all(target_vendor = "fortanix", target_env = "sgx")
|
||||
)
|
||||
)))]
|
||||
#[cfg(any(target_os = "wasi", any(target_env = "p1", target_env = "p2"), doc))]
|
||||
pub mod wasi;
|
||||
|
||||
#[cfg(any(all(target_os = "wasi", target_env = "p2"), doc))]
|
||||
pub mod wasip2;
|
||||
|
||||
// windows
|
||||
#[cfg(not(all(
|
||||
doc,
|
||||
any(
|
||||
all(target_arch = "wasm32", not(target_os = "wasi")),
|
||||
all(target_vendor = "fortanix", target_env = "sgx")
|
||||
)
|
||||
)))]
|
||||
#[cfg(any(windows, doc))]
|
||||
pub mod windows;
|
||||
|
||||
// Others.
|
||||
#[cfg(target_os = "aix")]
|
||||
pub mod aix;
|
||||
#[cfg(target_os = "android")]
|
||||
pub mod android;
|
||||
#[cfg(target_os = "cygwin")]
|
||||
pub mod cygwin;
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
pub mod dragonfly;
|
||||
#[cfg(target_os = "emscripten")]
|
||||
pub mod emscripten;
|
||||
#[cfg(target_os = "espidf")]
|
||||
pub mod espidf;
|
||||
#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
|
||||
pub mod fortanix_sgx;
|
||||
#[cfg(target_os = "freebsd")]
|
||||
pub mod freebsd;
|
||||
#[cfg(target_os = "fuchsia")]
|
||||
pub mod fuchsia;
|
||||
#[cfg(target_os = "haiku")]
|
||||
pub mod haiku;
|
||||
#[cfg(target_os = "hermit")]
|
||||
pub mod hermit;
|
||||
#[cfg(target_os = "horizon")]
|
||||
pub mod horizon;
|
||||
#[cfg(target_os = "hurd")]
|
||||
pub mod hurd;
|
||||
#[cfg(target_os = "illumos")]
|
||||
pub mod illumos;
|
||||
#[cfg(target_os = "ios")]
|
||||
pub mod ios;
|
||||
#[cfg(target_os = "l4re")]
|
||||
pub mod l4re;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod macos;
|
||||
#[cfg(target_os = "motor")]
|
||||
pub mod motor;
|
||||
#[cfg(target_os = "netbsd")]
|
||||
pub mod netbsd;
|
||||
#[cfg(target_os = "nto")]
|
||||
pub mod nto;
|
||||
#[cfg(target_os = "nuttx")]
|
||||
pub mod nuttx;
|
||||
#[cfg(target_os = "openbsd")]
|
||||
pub mod openbsd;
|
||||
#[cfg(target_os = "redox")]
|
||||
pub mod redox;
|
||||
#[cfg(target_os = "rtems")]
|
||||
pub mod rtems;
|
||||
#[cfg(target_os = "solaris")]
|
||||
pub mod solaris;
|
||||
#[cfg(target_os = "solid_asp3")]
|
||||
pub mod solid;
|
||||
#[cfg(target_os = "trusty")]
|
||||
pub mod trusty;
|
||||
#[cfg(target_os = "uefi")]
|
||||
pub mod uefi;
|
||||
#[cfg(target_os = "vita")]
|
||||
pub mod vita;
|
||||
#[cfg(target_os = "vxworks")]
|
||||
pub mod vxworks;
|
||||
#[cfg(target_os = "xous")]
|
||||
pub mod xous;
|
||||
|
||||
#[cfg(any(
|
||||
unix,
|
||||
target_os = "hermit",
|
||||
target_os = "trusty",
|
||||
target_os = "wasi",
|
||||
target_os = "motor",
|
||||
doc
|
||||
))]
|
||||
pub mod fd;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android", target_os = "cygwin", doc))]
|
||||
mod net;
|
||||
1
library/std/src/os/mod.rs
Symbolic link
1
library/std/src/os/mod.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/os/mod.rs
|
||||
@@ -1,26 +0,0 @@
|
||||
//! Compatibility module for C platform-specific types. Use [`core::ffi`] instead.
|
||||
|
||||
#![stable(feature = "raw_os", since = "1.1.0")]
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
macro_rules! alias_core_ffi {
|
||||
($($t:ident)*) => {$(
|
||||
#[stable(feature = "raw_os", since = "1.1.0")]
|
||||
#[doc = include_str!(concat!("../../../../core/src/ffi/", stringify!($t), ".md"))]
|
||||
#[doc(cfg(all()))]
|
||||
pub type $t = core::ffi::$t;
|
||||
)*}
|
||||
}
|
||||
|
||||
alias_core_ffi! {
|
||||
c_char c_schar c_uchar
|
||||
c_short c_ushort
|
||||
c_int c_uint
|
||||
c_long c_ulong
|
||||
c_longlong c_ulonglong
|
||||
c_float
|
||||
c_double
|
||||
c_void
|
||||
}
|
||||
1
library/std/src/os/raw/mod.rs
Symbolic link
1
library/std/src/os/raw/mod.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/os/raw/mod.rs
|
||||
@@ -1,17 +0,0 @@
|
||||
#![cfg(not(all(windows, target_env = "msvc")))]
|
||||
|
||||
use crate::any::TypeId;
|
||||
|
||||
macro_rules! ok {
|
||||
($($t:ident)*) => {$(
|
||||
assert!(TypeId::of::<libc::$t>() == TypeId::of::<raw::$t>(),
|
||||
"{} is wrong", stringify!($t));
|
||||
)*}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn same() {
|
||||
use crate::os::raw;
|
||||
ok!(c_char c_schar c_uchar c_short c_ushort c_int c_uint c_long c_ulong
|
||||
c_longlong c_ulonglong c_float c_double);
|
||||
}
|
||||
1
library/std/src/os/raw/tests.rs
Symbolic link
1
library/std/src/os/raw/tests.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/os/raw/tests.rs
|
||||
@@ -1,534 +0,0 @@
|
||||
//! Panic support in the standard library.
|
||||
|
||||
#![stable(feature = "std_panic", since = "1.9.0")]
|
||||
|
||||
use crate::any::Any;
|
||||
use crate::sync::atomic::{Atomic, AtomicU8, Ordering};
|
||||
use crate::sync::{Condvar, Mutex, RwLock};
|
||||
use crate::thread::Result;
|
||||
use crate::{collections, fmt, panicking};
|
||||
|
||||
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
||||
#[deprecated(
|
||||
since = "1.82.0",
|
||||
note = "use `PanicHookInfo` instead",
|
||||
suggestion = "std::panic::PanicHookInfo"
|
||||
)]
|
||||
/// A struct providing information about a panic.
|
||||
///
|
||||
/// `PanicInfo` has been renamed to [`PanicHookInfo`] to avoid confusion with
|
||||
/// [`core::panic::PanicInfo`].
|
||||
pub type PanicInfo<'a> = PanicHookInfo<'a>;
|
||||
|
||||
/// A struct providing information about a panic.
|
||||
///
|
||||
/// `PanicHookInfo` structure is passed to a panic hook set by the [`set_hook`] function.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```should_panic
|
||||
/// use std::panic;
|
||||
///
|
||||
/// panic::set_hook(Box::new(|panic_info| {
|
||||
/// println!("panic occurred: {panic_info}");
|
||||
/// }));
|
||||
///
|
||||
/// panic!("critical system failure");
|
||||
/// ```
|
||||
///
|
||||
/// [`set_hook`]: ../../std/panic/fn.set_hook.html
|
||||
#[stable(feature = "panic_hook_info", since = "1.81.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct PanicHookInfo<'a> {
|
||||
payload: &'a (dyn Any + Send),
|
||||
location: &'a Location<'a>,
|
||||
can_unwind: bool,
|
||||
force_no_backtrace: bool,
|
||||
}
|
||||
|
||||
impl<'a> PanicHookInfo<'a> {
|
||||
#[inline]
|
||||
pub(crate) fn new(
|
||||
location: &'a Location<'a>,
|
||||
payload: &'a (dyn Any + Send),
|
||||
can_unwind: bool,
|
||||
force_no_backtrace: bool,
|
||||
) -> Self {
|
||||
PanicHookInfo { payload, location, can_unwind, force_no_backtrace }
|
||||
}
|
||||
|
||||
/// Returns the payload associated with the panic.
|
||||
///
|
||||
/// This will commonly, but not always, be a `&'static str` or [`String`].
|
||||
/// If you only care about such payloads, use [`payload_as_str`] instead.
|
||||
///
|
||||
/// 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
|
||||
/// [`payload_as_str`]: PanicHookInfo::payload_as_str
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```should_panic
|
||||
/// use std::panic;
|
||||
///
|
||||
/// panic::set_hook(Box::new(|panic_info| {
|
||||
/// if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
|
||||
/// println!("panic occurred: {s:?}");
|
||||
/// } else if let Some(s) = panic_info.payload().downcast_ref::<String>() {
|
||||
/// println!("panic occurred: {s:?}");
|
||||
/// } else {
|
||||
/// println!("panic occurred");
|
||||
/// }
|
||||
/// }));
|
||||
///
|
||||
/// panic!("Normal panic");
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[inline]
|
||||
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
||||
pub fn payload(&self) -> &(dyn Any + Send) {
|
||||
self.payload
|
||||
}
|
||||
|
||||
/// Returns the payload associated with the panic, if it is a string.
|
||||
///
|
||||
/// This returns the payload if it is of type `&'static str` or `String`.
|
||||
///
|
||||
/// A invocation of the `panic!()` macro in Rust 2021 or later will always result in a
|
||||
/// panic payload where `payload_as_str` returns `Some`.
|
||||
///
|
||||
/// Only an invocation of [`panic_any`]
|
||||
/// (or, in Rust 2018 and earlier, `panic!(x)` where `x` is something other than a string)
|
||||
/// can result in a panic payload where `payload_as_str` returns `None`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```should_panic
|
||||
/// 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]
|
||||
#[stable(feature = "panic_payload_as_str", since = "1.91.0")]
|
||||
pub fn payload_as_str(&self) -> Option<&str> {
|
||||
if let Some(s) = self.payload.downcast_ref::<&str>() {
|
||||
Some(s)
|
||||
} else if let Some(s) = self.payload.downcast_ref::<String>() {
|
||||
Some(s)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns information about the location from which the panic originated,
|
||||
/// if available.
|
||||
///
|
||||
/// This method will currently always return [`Some`], but this may change
|
||||
/// in future versions.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```should_panic
|
||||
/// use std::panic;
|
||||
///
|
||||
/// panic::set_hook(Box::new(|panic_info| {
|
||||
/// if let Some(location) = panic_info.location() {
|
||||
/// println!("panic occurred in file '{}' at line {}",
|
||||
/// location.file(),
|
||||
/// location.line(),
|
||||
/// );
|
||||
/// } else {
|
||||
/// println!("panic occurred but can't get location information...");
|
||||
/// }
|
||||
/// }));
|
||||
///
|
||||
/// panic!("Normal panic");
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[inline]
|
||||
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
||||
pub fn location(&self) -> Option<&Location<'_>> {
|
||||
// NOTE: If this is changed to sometimes return None,
|
||||
// deal with that case in std::panicking::default_hook and core::panicking::panic_fmt.
|
||||
Some(&self.location)
|
||||
}
|
||||
|
||||
/// Returns whether the panic handler is allowed to unwind the stack from
|
||||
/// the point where the panic occurred.
|
||||
///
|
||||
/// This is true for most kinds of panics with the exception of panics
|
||||
/// caused by trying to unwind out of a `Drop` implementation or a function
|
||||
/// whose ABI does not support unwinding.
|
||||
///
|
||||
/// It is safe for a panic handler to unwind even when this function returns
|
||||
/// false, however this will simply cause the panic handler to be called
|
||||
/// again.
|
||||
#[must_use]
|
||||
#[inline]
|
||||
#[unstable(feature = "panic_can_unwind", issue = "92988")]
|
||||
pub fn can_unwind(&self) -> bool {
|
||||
self.can_unwind
|
||||
}
|
||||
|
||||
#[unstable(
|
||||
feature = "panic_internals",
|
||||
reason = "internal details of the implementation of the `panic!` and related macros",
|
||||
issue = "none"
|
||||
)]
|
||||
#[doc(hidden)]
|
||||
#[inline]
|
||||
pub fn force_no_backtrace(&self) -> bool {
|
||||
self.force_no_backtrace
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "panic_hook_display", since = "1.26.0")]
|
||||
impl fmt::Display for PanicHookInfo<'_> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter.write_str("panicked at ")?;
|
||||
self.location.fmt(formatter)?;
|
||||
if let Some(payload) = self.payload_as_str() {
|
||||
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)]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_2015_macro")]
|
||||
#[rustc_macro_transparency = "semiopaque"]
|
||||
pub macro panic_2015 {
|
||||
() => ({
|
||||
$crate::rt::begin_panic("explicit panic")
|
||||
}),
|
||||
($msg:expr $(,)?) => ({
|
||||
$crate::rt::begin_panic($msg);
|
||||
}),
|
||||
// Special-case the single-argument case for const_panic.
|
||||
("{}", $arg:expr $(,)?) => ({
|
||||
$crate::rt::panic_display(&$arg);
|
||||
}),
|
||||
($fmt:expr, $($arg:tt)+) => ({
|
||||
// Semicolon to prevent temporaries inside the formatting machinery from
|
||||
// being considered alive in the caller after the panic_fmt call.
|
||||
$crate::rt::panic_fmt($crate::const_format_args!($fmt, $($arg)+));
|
||||
}),
|
||||
}
|
||||
|
||||
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
||||
pub use core::panic::Location;
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
|
||||
pub use core::panic::panic_2021;
|
||||
#[stable(feature = "catch_unwind", since = "1.9.0")]
|
||||
pub use core::panic::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe};
|
||||
|
||||
#[unstable(feature = "panic_update_hook", issue = "92649")]
|
||||
pub use crate::panicking::update_hook;
|
||||
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
||||
pub use crate::panicking::{set_hook, take_hook};
|
||||
|
||||
/// Panics the current thread with the given message as the panic payload.
|
||||
///
|
||||
/// 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 [`PanicHookInfo::payload`].
|
||||
///
|
||||
/// See the [`panic!`] macro for more information about panicking.
|
||||
#[stable(feature = "panic_any", since = "1.51.0")]
|
||||
#[inline]
|
||||
#[track_caller]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "panic_any")]
|
||||
pub fn panic_any<M: 'static + Any + Send>(msg: M) -> ! {
|
||||
crate::panicking::begin_panic(msg);
|
||||
}
|
||||
|
||||
#[stable(feature = "catch_unwind", since = "1.9.0")]
|
||||
impl<T: ?Sized> UnwindSafe for Mutex<T> {}
|
||||
#[stable(feature = "catch_unwind", since = "1.9.0")]
|
||||
impl<T: ?Sized> UnwindSafe for RwLock<T> {}
|
||||
#[stable(feature = "catch_unwind", since = "1.9.0")]
|
||||
impl UnwindSafe for Condvar {}
|
||||
|
||||
#[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")]
|
||||
impl<T: ?Sized> RefUnwindSafe for Mutex<T> {}
|
||||
#[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")]
|
||||
impl<T: ?Sized> RefUnwindSafe for RwLock<T> {}
|
||||
#[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")]
|
||||
impl RefUnwindSafe for Condvar {}
|
||||
|
||||
// https://github.com/rust-lang/rust/issues/62301
|
||||
#[stable(feature = "hashbrown", since = "1.36.0")]
|
||||
impl<K, V, S> UnwindSafe for collections::HashMap<K, V, S>
|
||||
where
|
||||
K: UnwindSafe,
|
||||
V: UnwindSafe,
|
||||
S: UnwindSafe,
|
||||
{
|
||||
}
|
||||
|
||||
#[unstable(feature = "abort_unwind", issue = "130338")]
|
||||
pub use core::panic::abort_unwind;
|
||||
|
||||
/// Invokes a closure, capturing the cause of an unwinding panic if one occurs.
|
||||
///
|
||||
/// This function will return `Ok` with the closure's result if the closure does
|
||||
/// not panic, and will return `Err(cause)` if the closure panics. The `cause`
|
||||
/// returned is the object with which panic was originally invoked.
|
||||
///
|
||||
/// Rust functions that are expected to be called from foreign code that does
|
||||
/// not support unwinding (such as C compiled with `-fno-exceptions`) should be
|
||||
/// defined using `extern "C"`, which ensures that if the Rust code panics, it
|
||||
/// is automatically caught and the process is aborted. If this is the desired
|
||||
/// behavior, it is not necessary to use `catch_unwind` explicitly. This
|
||||
/// function should instead be used when more graceful error-handling is needed.
|
||||
///
|
||||
/// It is **not** recommended to use this function for a general try/catch
|
||||
/// mechanism. The [`Result`] type is more appropriate to use for functions that
|
||||
/// can fail on a regular basis. Additionally, this function is not guaranteed
|
||||
/// to catch all panics, see the "Notes" section below.
|
||||
///
|
||||
/// The closure provided is required to adhere to the [`UnwindSafe`] trait to
|
||||
/// ensure that all captured variables are safe to cross this boundary. The
|
||||
/// purpose of this bound is to encode the concept of [exception safety][rfc] in
|
||||
/// the type system. Most usage of this function should not need to worry about
|
||||
/// this bound as programs are naturally unwind safe without `unsafe` code. If
|
||||
/// it becomes a problem the [`AssertUnwindSafe`] wrapper struct can be used to
|
||||
/// quickly assert that the usage here is indeed unwind safe.
|
||||
///
|
||||
/// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// This function **might not catch all Rust panics**. A Rust panic is not
|
||||
/// always implemented via unwinding, but can be implemented by aborting the
|
||||
/// process as well. This function *only* catches unwinding panics, not those
|
||||
/// that abort the process.
|
||||
///
|
||||
/// If a custom panic hook has been set, it will be invoked before the panic is
|
||||
/// caught, before unwinding.
|
||||
///
|
||||
/// Although unwinding into Rust code with a foreign exception (e.g. an
|
||||
/// exception thrown from C++ code, or a `panic!` in Rust code compiled or
|
||||
/// linked with a different runtime) via an appropriate ABI (e.g. `"C-unwind"`)
|
||||
/// is permitted, catching such an exception using this function will have one
|
||||
/// of two behaviors, and it is unspecified which will occur:
|
||||
///
|
||||
/// * The process aborts, after executing all destructors of `f` and the
|
||||
/// functions it called.
|
||||
/// * The function returns a `Result::Err` containing an opaque type.
|
||||
///
|
||||
/// Finally, be **careful in how you drop the result of this function**. If it
|
||||
/// is `Err`, it contains the panic payload, and dropping that may in turn
|
||||
/// panic!
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::panic;
|
||||
///
|
||||
/// let result = panic::catch_unwind(|| {
|
||||
/// println!("hello!");
|
||||
/// });
|
||||
/// assert!(result.is_ok());
|
||||
///
|
||||
/// let result = panic::catch_unwind(|| {
|
||||
/// panic!("oh no!");
|
||||
/// });
|
||||
/// assert!(result.is_err());
|
||||
/// ```
|
||||
#[stable(feature = "catch_unwind", since = "1.9.0")]
|
||||
pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
|
||||
unsafe { panicking::catch_unwind(f) }
|
||||
}
|
||||
|
||||
/// Triggers a panic without invoking the panic hook.
|
||||
///
|
||||
/// This is designed to be used in conjunction with [`catch_unwind`] to, for
|
||||
/// example, carry a panic across a layer of C code.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// Note that panics in Rust are not always implemented via unwinding, but they
|
||||
/// may be implemented by aborting the process. If this function is called when
|
||||
/// panics are implemented this way then this function will abort the process,
|
||||
/// not trigger an unwind.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```should_panic
|
||||
/// use std::panic;
|
||||
///
|
||||
/// let result = panic::catch_unwind(|| {
|
||||
/// if 1 != 2 {
|
||||
/// panic!("oh no!");
|
||||
/// }
|
||||
/// });
|
||||
///
|
||||
/// if let Err(err) = result {
|
||||
/// panic::resume_unwind(err);
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "resume_unwind", since = "1.9.0")]
|
||||
pub fn resume_unwind(payload: Box<dyn Any + Send>) -> ! {
|
||||
panicking::resume_unwind(payload)
|
||||
}
|
||||
|
||||
/// Makes all future panics abort directly without running the panic hook or unwinding.
|
||||
///
|
||||
/// There is no way to undo this; the effect lasts until the process exits or
|
||||
/// execs (or the equivalent).
|
||||
///
|
||||
/// # Use after fork
|
||||
///
|
||||
/// This function is particularly useful for calling after `libc::fork`. After `fork`, in a
|
||||
/// multithreaded program it is (on many platforms) not safe to call the allocator. It is also
|
||||
/// generally highly undesirable for an unwind to unwind past the `fork`, because that results in
|
||||
/// the unwind propagating to code that was only ever expecting to run in the parent.
|
||||
///
|
||||
/// `panic::always_abort()` helps avoid both of these. It directly avoids any further unwinding,
|
||||
/// and if there is a panic, the abort will occur without allocating provided that the arguments to
|
||||
/// panic can be formatted without allocating.
|
||||
///
|
||||
/// Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// #![feature(panic_always_abort)]
|
||||
/// use std::panic;
|
||||
///
|
||||
/// panic::always_abort();
|
||||
///
|
||||
/// let _ = panic::catch_unwind(|| {
|
||||
/// panic!("inside the catch");
|
||||
/// });
|
||||
///
|
||||
/// // We will have aborted already, due to the panic.
|
||||
/// unreachable!();
|
||||
/// ```
|
||||
#[unstable(feature = "panic_always_abort", issue = "84438")]
|
||||
pub fn always_abort() {
|
||||
crate::panicking::panic_count::set_always_abort();
|
||||
}
|
||||
|
||||
/// The configuration for whether and how the default panic hook will capture
|
||||
/// and display the backtrace.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
#[unstable(feature = "panic_backtrace_config", issue = "93346")]
|
||||
#[non_exhaustive]
|
||||
pub enum BacktraceStyle {
|
||||
/// Prints a terser backtrace which ideally only contains relevant
|
||||
/// information.
|
||||
Short,
|
||||
/// Prints a backtrace with all possible information.
|
||||
Full,
|
||||
/// Disable collecting and displaying backtraces.
|
||||
Off,
|
||||
}
|
||||
|
||||
impl BacktraceStyle {
|
||||
pub(crate) fn full() -> Option<Self> {
|
||||
if cfg!(feature = "backtrace") { Some(BacktraceStyle::Full) } else { None }
|
||||
}
|
||||
|
||||
fn as_u8(self) -> u8 {
|
||||
match self {
|
||||
BacktraceStyle::Short => 1,
|
||||
BacktraceStyle::Full => 2,
|
||||
BacktraceStyle::Off => 3,
|
||||
}
|
||||
}
|
||||
|
||||
fn from_u8(s: u8) -> Option<Self> {
|
||||
match s {
|
||||
1 => Some(BacktraceStyle::Short),
|
||||
2 => Some(BacktraceStyle::Full),
|
||||
3 => Some(BacktraceStyle::Off),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tracks whether we should/can capture a backtrace, and how we should display
|
||||
// that backtrace.
|
||||
//
|
||||
// Internally stores equivalent of an Option<BacktraceStyle>.
|
||||
static SHOULD_CAPTURE: Atomic<u8> = AtomicU8::new(0);
|
||||
|
||||
/// Configures whether the default panic hook will capture and display a
|
||||
/// backtrace.
|
||||
///
|
||||
/// The default value for this setting may be set by the `RUST_BACKTRACE`
|
||||
/// environment variable; see the details in [`get_backtrace_style`].
|
||||
#[unstable(feature = "panic_backtrace_config", issue = "93346")]
|
||||
pub fn set_backtrace_style(style: BacktraceStyle) {
|
||||
if cfg!(feature = "backtrace") {
|
||||
// If the `backtrace` feature of this crate is enabled, set the backtrace style.
|
||||
SHOULD_CAPTURE.store(style.as_u8(), Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks whether the standard library's panic hook will capture and print a
|
||||
/// backtrace.
|
||||
///
|
||||
/// This function will, if a backtrace style has not been set via
|
||||
/// [`set_backtrace_style`], read the environment variable `RUST_BACKTRACE` to
|
||||
/// determine a default value for the backtrace formatting:
|
||||
///
|
||||
/// The first call to `get_backtrace_style` may read the `RUST_BACKTRACE`
|
||||
/// environment variable if `set_backtrace_style` has not been called to
|
||||
/// override the default value. After a call to `set_backtrace_style` or
|
||||
/// `get_backtrace_style`, any changes to `RUST_BACKTRACE` will have no effect.
|
||||
///
|
||||
/// `RUST_BACKTRACE` is read according to these rules:
|
||||
///
|
||||
/// * `0` for `BacktraceStyle::Off`
|
||||
/// * `full` for `BacktraceStyle::Full`
|
||||
/// * `1` for `BacktraceStyle::Short`
|
||||
/// * Other values are currently `BacktraceStyle::Short`, but this may change in
|
||||
/// the future
|
||||
///
|
||||
/// Returns `None` if backtraces aren't currently supported.
|
||||
#[unstable(feature = "panic_backtrace_config", issue = "93346")]
|
||||
pub fn get_backtrace_style() -> Option<BacktraceStyle> {
|
||||
if !cfg!(feature = "backtrace") {
|
||||
// If the `backtrace` feature of this crate isn't enabled quickly return
|
||||
// `Unsupported` so this can be constant propagated all over the place
|
||||
// to optimize away callers.
|
||||
return None;
|
||||
}
|
||||
|
||||
let current = SHOULD_CAPTURE.load(Ordering::Relaxed);
|
||||
if let Some(style) = BacktraceStyle::from_u8(current) {
|
||||
return Some(style);
|
||||
}
|
||||
|
||||
let format = match crate::env::var_os("RUST_BACKTRACE") {
|
||||
Some(x) if &x == "0" => BacktraceStyle::Off,
|
||||
Some(x) if &x == "full" => BacktraceStyle::Full,
|
||||
Some(_) => BacktraceStyle::Short,
|
||||
None if crate::sys::backtrace::FULL_BACKTRACE_DEFAULT => BacktraceStyle::Full,
|
||||
None => BacktraceStyle::Off,
|
||||
};
|
||||
|
||||
match SHOULD_CAPTURE.compare_exchange(0, format.as_u8(), Ordering::Relaxed, Ordering::Relaxed) {
|
||||
Ok(_) => Some(format),
|
||||
Err(new) => BacktraceStyle::from_u8(new),
|
||||
}
|
||||
}
|
||||
1
library/std/src/panic.rs
Symbolic link
1
library/std/src/panic.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs
|
||||
@@ -1,894 +0,0 @@
|
||||
//! Implementation of various bits and pieces of the `panic!` macro and
|
||||
//! associated runtime pieces.
|
||||
//!
|
||||
//! Specifically, this module contains the implementation of:
|
||||
//!
|
||||
//! * Panic hooks
|
||||
//! * Executing a panic up to doing the actual implementation
|
||||
//! * Shims around "try"
|
||||
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
use core::panic::{Location, PanicPayload};
|
||||
|
||||
// make sure to use the stderr output configured
|
||||
// by libtest in the real copy of std
|
||||
#[cfg(test)]
|
||||
use realstd::io::try_set_output_capture;
|
||||
|
||||
use crate::any::Any;
|
||||
#[cfg(not(test))]
|
||||
use crate::io::try_set_output_capture;
|
||||
use crate::mem::{self, ManuallyDrop};
|
||||
use crate::panic::{BacktraceStyle, PanicHookInfo};
|
||||
use crate::sync::atomic::{Atomic, AtomicBool, Ordering};
|
||||
use crate::sync::nonpoison::RwLock;
|
||||
use crate::sys::backtrace;
|
||||
use crate::sys::stdio::panic_output;
|
||||
use crate::{fmt, intrinsics, process, thread};
|
||||
|
||||
// This forces codegen of the function called by panic!() inside the std crate, rather than in
|
||||
// downstream crates. Primarily this is useful for rustc's codegen tests, which rely on noticing
|
||||
// complete removal of panic from generated IR. Since begin_panic is inline(never), it's only
|
||||
// codegen'd once per crate-graph so this pushes that to std rather than our codegen test crates.
|
||||
//
|
||||
// (See https://github.com/rust-lang/rust/pull/123244 for more info on why).
|
||||
//
|
||||
// If this is causing problems we can also modify those codegen tests to use a crate type like
|
||||
// cdylib which doesn't export "Rust" symbols to downstream linkage units.
|
||||
#[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "none")]
|
||||
#[doc(hidden)]
|
||||
#[allow(dead_code)]
|
||||
#[used(compiler)]
|
||||
pub static EMPTY_PANIC: fn(&'static str) -> ! =
|
||||
begin_panic::<&'static str> as fn(&'static str) -> !;
|
||||
|
||||
// Binary interface to the panic runtime that the standard library depends on.
|
||||
//
|
||||
// The standard library is tagged with `#![needs_panic_runtime]` (introduced in
|
||||
// RFC 1513) to indicate that it requires some other crate tagged with
|
||||
// `#![panic_runtime]` to exist somewhere. Each panic runtime is intended to
|
||||
// implement these symbols (with the same signatures) so we can get matched up
|
||||
// to them.
|
||||
//
|
||||
// One day this may look a little less ad-hoc with the compiler helping out to
|
||||
// hook up these functions, but it is not this day!
|
||||
#[allow(improper_ctypes)]
|
||||
unsafe extern "C" {
|
||||
#[rustc_std_internal_symbol]
|
||||
fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static);
|
||||
}
|
||||
|
||||
unsafe extern "Rust" {
|
||||
/// `PanicPayload` lazily performs allocation only when needed (this avoids
|
||||
/// allocations when using the "abort" panic runtime).
|
||||
#[rustc_std_internal_symbol]
|
||||
fn __rust_start_panic(payload: &mut dyn PanicPayload) -> u32;
|
||||
}
|
||||
|
||||
/// This function is called by the panic runtime if FFI code catches a Rust
|
||||
/// panic but doesn't rethrow it. We don't support this case since it messes
|
||||
/// with our panic count.
|
||||
#[cfg(not(test))]
|
||||
#[rustc_std_internal_symbol]
|
||||
extern "C" fn __rust_drop_panic() -> ! {
|
||||
rtabort!("Rust panics must be rethrown");
|
||||
}
|
||||
|
||||
/// This function is called by the panic runtime if it catches an exception
|
||||
/// object which does not correspond to a Rust panic.
|
||||
#[cfg(not(test))]
|
||||
#[rustc_std_internal_symbol]
|
||||
extern "C" fn __rust_foreign_exception() -> ! {
|
||||
rtabort!("Rust cannot catch foreign exceptions");
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
enum Hook {
|
||||
#[default]
|
||||
Default,
|
||||
Custom(Box<dyn Fn(&PanicHookInfo<'_>) + 'static + Sync + Send>),
|
||||
}
|
||||
|
||||
impl Hook {
|
||||
#[inline]
|
||||
fn into_box(self) -> Box<dyn Fn(&PanicHookInfo<'_>) + 'static + Sync + Send> {
|
||||
match self {
|
||||
Hook::Default => Box::new(default_hook),
|
||||
Hook::Custom(hook) => hook,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static HOOK: RwLock<Hook> = RwLock::new(Hook::Default);
|
||||
|
||||
/// Registers a custom panic hook, replacing the previously registered hook.
|
||||
///
|
||||
/// The panic hook is invoked when a thread panics, but before the panic runtime
|
||||
/// is invoked. As such, the hook will run with both the aborting and unwinding
|
||||
/// runtimes.
|
||||
///
|
||||
/// The default hook, which is registered at startup, prints a message to standard error and
|
||||
/// generates a backtrace if requested. This behavior can be customized using the `set_hook` function.
|
||||
/// The current hook can be retrieved while reinstating the default hook with the [`take_hook`]
|
||||
/// function.
|
||||
///
|
||||
/// [`take_hook`]: ./fn.take_hook.html
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// The panic hook is a global resource.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if called from a panicking thread.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// The following will print "Custom panic hook":
|
||||
///
|
||||
/// ```should_panic
|
||||
/// use std::panic;
|
||||
///
|
||||
/// panic::set_hook(Box::new(|_| {
|
||||
/// println!("Custom panic hook");
|
||||
/// }));
|
||||
///
|
||||
/// panic!("Normal panic");
|
||||
/// ```
|
||||
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
||||
pub fn set_hook(hook: Box<dyn Fn(&PanicHookInfo<'_>) + 'static + Sync + Send>) {
|
||||
if thread::panicking() {
|
||||
panic!("cannot modify the panic hook from a panicking thread");
|
||||
}
|
||||
|
||||
// Drop the old hook after changing the hook to avoid deadlocking if its
|
||||
// destructor panics.
|
||||
drop(HOOK.replace(Hook::Custom(hook)));
|
||||
}
|
||||
|
||||
/// Unregisters the current panic hook and returns it, registering the default hook
|
||||
/// in its place.
|
||||
///
|
||||
/// *See also the function [`set_hook`].*
|
||||
///
|
||||
/// [`set_hook`]: ./fn.set_hook.html
|
||||
///
|
||||
/// If the default hook is registered it will be returned, but remain registered.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if called from a panicking thread.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// The following will print "Normal panic":
|
||||
///
|
||||
/// ```should_panic
|
||||
/// use std::panic;
|
||||
///
|
||||
/// panic::set_hook(Box::new(|_| {
|
||||
/// println!("Custom panic hook");
|
||||
/// }));
|
||||
///
|
||||
/// let _ = panic::take_hook();
|
||||
///
|
||||
/// panic!("Normal panic");
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
||||
pub fn take_hook() -> Box<dyn Fn(&PanicHookInfo<'_>) + 'static + Sync + Send> {
|
||||
if thread::panicking() {
|
||||
panic!("cannot modify the panic hook from a panicking thread");
|
||||
}
|
||||
|
||||
HOOK.replace(Hook::Default).into_box()
|
||||
}
|
||||
|
||||
/// Atomic combination of [`take_hook`] and [`set_hook`]. Use this to replace the panic handler with
|
||||
/// a new panic handler that does something and then executes the old handler.
|
||||
///
|
||||
/// [`take_hook`]: ./fn.take_hook.html
|
||||
/// [`set_hook`]: ./fn.set_hook.html
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if called from a panicking thread.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// The following will print the custom message, and then the normal output of panic.
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(panic_update_hook)]
|
||||
/// use std::panic;
|
||||
///
|
||||
/// // Equivalent to
|
||||
/// // let prev = panic::take_hook();
|
||||
/// // panic::set_hook(Box::new(move |info| {
|
||||
/// // println!("...");
|
||||
/// // prev(info);
|
||||
/// // }));
|
||||
/// panic::update_hook(move |prev, info| {
|
||||
/// println!("Print custom message and execute panic handler as usual");
|
||||
/// prev(info);
|
||||
/// });
|
||||
///
|
||||
/// panic!("Custom and then normal");
|
||||
/// ```
|
||||
#[unstable(feature = "panic_update_hook", issue = "92649")]
|
||||
pub fn update_hook<F>(hook_fn: F)
|
||||
where
|
||||
F: Fn(&(dyn Fn(&PanicHookInfo<'_>) + Send + Sync + 'static), &PanicHookInfo<'_>)
|
||||
+ Sync
|
||||
+ Send
|
||||
+ 'static,
|
||||
{
|
||||
if thread::panicking() {
|
||||
panic!("cannot modify the panic hook from a panicking thread");
|
||||
}
|
||||
|
||||
let mut hook = HOOK.write();
|
||||
let prev = mem::take(&mut *hook).into_box();
|
||||
*hook = Hook::Custom(Box::new(move |info| hook_fn(&prev, info)));
|
||||
}
|
||||
|
||||
/// The default panic handler.
|
||||
#[optimize(size)]
|
||||
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() {
|
||||
None
|
||||
} else if panic_count::get_count() >= 2 {
|
||||
BacktraceStyle::full()
|
||||
} else {
|
||||
crate::panic::get_backtrace_style()
|
||||
};
|
||||
|
||||
// The current implementation always returns `Some`.
|
||||
let location = info.location().unwrap();
|
||||
|
||||
let msg = payload_as_str(info.payload());
|
||||
|
||||
let write = #[optimize(size)]
|
||||
|err: &mut dyn crate::io::Write| {
|
||||
// Use a lock to prevent mixed output in multithreading context.
|
||||
// Some platforms also require it when printing a backtrace, like `SymFromAddr` on Windows.
|
||||
let mut lock = backtrace::lock();
|
||||
|
||||
thread::with_current_name(|name| {
|
||||
let name = name.unwrap_or("<unnamed>");
|
||||
let tid = thread::current_os_id();
|
||||
|
||||
// Try to write the panic message to a buffer first to prevent other concurrent outputs
|
||||
// interleaving with it.
|
||||
let mut buffer = [0u8; 512];
|
||||
let mut cursor = crate::io::Cursor::new(&mut buffer[..]);
|
||||
|
||||
let write_msg = |dst: &mut dyn crate::io::Write| {
|
||||
// We add a newline to ensure the panic message appears at the start of a line.
|
||||
writeln!(dst, "\nthread '{name}' ({tid}) panicked at {location}:\n{msg}")
|
||||
};
|
||||
|
||||
if write_msg(&mut cursor).is_ok() {
|
||||
let pos = cursor.position() as usize;
|
||||
let _ = err.write_all(&buffer[0..pos]);
|
||||
} else {
|
||||
// The message did not fit into the buffer, write it directly instead.
|
||||
let _ = write_msg(err);
|
||||
};
|
||||
});
|
||||
|
||||
static FIRST_PANIC: Atomic<bool> = AtomicBool::new(true);
|
||||
|
||||
match backtrace {
|
||||
Some(BacktraceStyle::Short) => {
|
||||
drop(lock.print(err, crate::backtrace_rs::PrintFmt::Short))
|
||||
}
|
||||
Some(BacktraceStyle::Full) => {
|
||||
drop(lock.print(err, crate::backtrace_rs::PrintFmt::Full))
|
||||
}
|
||||
Some(BacktraceStyle::Off) => {
|
||||
if FIRST_PANIC.swap(false, Ordering::Relaxed) {
|
||||
let _ = writeln!(
|
||||
err,
|
||||
"note: run with `RUST_BACKTRACE=1` environment variable to display a \
|
||||
backtrace"
|
||||
);
|
||||
if cfg!(miri) {
|
||||
let _ = writeln!(
|
||||
err,
|
||||
"note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` \
|
||||
for the environment variable to have an effect"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If backtraces aren't supported or are forced-off, do nothing.
|
||||
None => {}
|
||||
}
|
||||
};
|
||||
|
||||
if let Ok(Some(local)) = try_set_output_capture(None) {
|
||||
write(&mut *local.lock().unwrap_or_else(|e| e.into_inner()));
|
||||
try_set_output_capture(Some(local)).ok();
|
||||
} else if let Some(mut out) = panic_output() {
|
||||
write(&mut out);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[doc(hidden)]
|
||||
#[cfg(panic = "immediate-abort")]
|
||||
#[unstable(feature = "update_panic_count", issue = "none")]
|
||||
pub mod panic_count {
|
||||
/// A reason for forcing an immediate abort on panic.
|
||||
#[derive(Debug)]
|
||||
pub enum MustAbort {
|
||||
AlwaysAbort,
|
||||
PanicInHook,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn increase(run_panic_hook: bool) -> Option<MustAbort> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn finished_panic_hook() {}
|
||||
|
||||
#[inline]
|
||||
pub fn decrease() {}
|
||||
|
||||
#[inline]
|
||||
pub fn set_always_abort() {}
|
||||
|
||||
// Disregards ALWAYS_ABORT_FLAG
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn get_count() -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub fn count_is_zero() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[doc(hidden)]
|
||||
#[cfg(not(panic = "immediate-abort"))]
|
||||
#[unstable(feature = "update_panic_count", issue = "none")]
|
||||
pub mod panic_count {
|
||||
use crate::cell::Cell;
|
||||
use crate::sync::atomic::{Atomic, AtomicUsize, Ordering};
|
||||
|
||||
const ALWAYS_ABORT_FLAG: usize = 1 << (usize::BITS - 1);
|
||||
|
||||
/// A reason for forcing an immediate abort on panic.
|
||||
#[derive(Debug)]
|
||||
pub enum MustAbort {
|
||||
AlwaysAbort,
|
||||
PanicInHook,
|
||||
}
|
||||
|
||||
// Panic count for the current thread and whether a panic hook is currently
|
||||
// being executed..
|
||||
thread_local! {
|
||||
static LOCAL_PANIC_COUNT: Cell<(usize, bool)> = const { Cell::new((0, false)) }
|
||||
}
|
||||
|
||||
// Sum of panic counts from all threads. The purpose of this is to have
|
||||
// a fast path in `count_is_zero` (which is used by `panicking`). In any particular
|
||||
// thread, if that thread currently views `GLOBAL_PANIC_COUNT` as being zero,
|
||||
// then `LOCAL_PANIC_COUNT` in that thread is zero. This invariant holds before
|
||||
// and after increase and decrease, but not necessarily during their execution.
|
||||
//
|
||||
// Additionally, the top bit of GLOBAL_PANIC_COUNT (GLOBAL_ALWAYS_ABORT_FLAG)
|
||||
// records whether panic::always_abort() has been called. This can only be
|
||||
// set, never cleared.
|
||||
// panic::always_abort() is usually called to prevent memory allocations done by
|
||||
// the panic handling in the child created by `libc::fork`.
|
||||
// Memory allocations performed in a child created with `libc::fork` are undefined
|
||||
// behavior in most operating systems.
|
||||
// Accessing LOCAL_PANIC_COUNT in a child created by `libc::fork` would lead to a memory
|
||||
// allocation. Only GLOBAL_PANIC_COUNT can be accessed in this situation. This is
|
||||
// sufficient because a child process will always have exactly one thread only.
|
||||
// See also #85261 for details.
|
||||
//
|
||||
// This could be viewed as a struct containing a single bit and an n-1-bit
|
||||
// value, but if we wrote it like that it would be more than a single word,
|
||||
// and even a newtype around usize would be clumsy because we need atomics.
|
||||
// But we use such a tuple for the return type of increase().
|
||||
//
|
||||
// Stealing a bit is fine because it just amounts to assuming that each
|
||||
// panicking thread consumes at least 2 bytes of address space.
|
||||
static GLOBAL_PANIC_COUNT: Atomic<usize> = AtomicUsize::new(0);
|
||||
|
||||
// Increases the global and local panic count, and returns whether an
|
||||
// immediate abort is required.
|
||||
//
|
||||
// This also updates thread-local state to keep track of whether a panic
|
||||
// hook is currently executing.
|
||||
pub fn increase(run_panic_hook: bool) -> Option<MustAbort> {
|
||||
let global_count = GLOBAL_PANIC_COUNT.fetch_add(1, Ordering::Relaxed);
|
||||
if global_count & ALWAYS_ABORT_FLAG != 0 {
|
||||
// Do *not* access thread-local state, we might be after a `fork`.
|
||||
return Some(MustAbort::AlwaysAbort);
|
||||
}
|
||||
|
||||
LOCAL_PANIC_COUNT.with(|c| {
|
||||
let (count, in_panic_hook) = c.get();
|
||||
if in_panic_hook {
|
||||
return Some(MustAbort::PanicInHook);
|
||||
}
|
||||
c.set((count + 1, run_panic_hook));
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
pub fn finished_panic_hook() {
|
||||
LOCAL_PANIC_COUNT.with(|c| {
|
||||
let (count, _) = c.get();
|
||||
c.set((count, false));
|
||||
});
|
||||
}
|
||||
|
||||
pub fn decrease() {
|
||||
GLOBAL_PANIC_COUNT.fetch_sub(1, Ordering::Relaxed);
|
||||
LOCAL_PANIC_COUNT.with(|c| {
|
||||
let (count, _) = c.get();
|
||||
c.set((count - 1, false));
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_always_abort() {
|
||||
GLOBAL_PANIC_COUNT.fetch_or(ALWAYS_ABORT_FLAG, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
// Disregards ALWAYS_ABORT_FLAG
|
||||
#[must_use]
|
||||
pub fn get_count() -> usize {
|
||||
LOCAL_PANIC_COUNT.with(|c| c.get().0)
|
||||
}
|
||||
|
||||
// Disregards ALWAYS_ABORT_FLAG
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub fn count_is_zero() -> bool {
|
||||
if GLOBAL_PANIC_COUNT.load(Ordering::Relaxed) & !ALWAYS_ABORT_FLAG == 0 {
|
||||
// Fast path: if `GLOBAL_PANIC_COUNT` is zero, all threads
|
||||
// (including the current one) will have `LOCAL_PANIC_COUNT`
|
||||
// equal to zero, so TLS access can be avoided.
|
||||
//
|
||||
// In terms of performance, a relaxed atomic load is similar to a normal
|
||||
// aligned memory read (e.g., a mov instruction in x86), but with some
|
||||
// compiler optimization restrictions. On the other hand, a TLS access
|
||||
// might require calling a non-inlinable function (such as `__tls_get_addr`
|
||||
// when using the GD TLS model).
|
||||
true
|
||||
} else {
|
||||
is_zero_slow_path()
|
||||
}
|
||||
}
|
||||
|
||||
// Slow path is in a separate function to reduce the amount of code
|
||||
// inlined from `count_is_zero`.
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
fn is_zero_slow_path() -> bool {
|
||||
LOCAL_PANIC_COUNT.with(|c| c.get().0 == 0)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub use realstd::rt::panic_count;
|
||||
|
||||
/// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
|
||||
#[cfg(panic = "immediate-abort")]
|
||||
pub unsafe fn catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
|
||||
Ok(f())
|
||||
}
|
||||
|
||||
/// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
|
||||
#[cfg(not(panic = "immediate-abort"))]
|
||||
pub unsafe fn catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
|
||||
union Data<F, R> {
|
||||
f: ManuallyDrop<F>,
|
||||
r: ManuallyDrop<R>,
|
||||
p: ManuallyDrop<Box<dyn Any + Send>>,
|
||||
}
|
||||
|
||||
// We do some sketchy operations with ownership here for the sake of
|
||||
// performance. We can only pass pointers down to `do_call` (can't pass
|
||||
// objects by value), so we do all the ownership tracking here manually
|
||||
// using a union.
|
||||
//
|
||||
// We go through a transition where:
|
||||
//
|
||||
// * First, we set the data field `f` to be the argumentless closure that we're going to call.
|
||||
// * When we make the function call, the `do_call` function below, we take
|
||||
// ownership of the function pointer. At this point the `data` union is
|
||||
// entirely uninitialized.
|
||||
// * If the closure successfully returns, we write the return value into the
|
||||
// data's return slot (field `r`).
|
||||
// * If the closure panics (`do_catch` below), we write the panic payload into field `p`.
|
||||
// * Finally, when we come back out of the `try` intrinsic we're
|
||||
// in one of two states:
|
||||
//
|
||||
// 1. The closure didn't panic, in which case the return value was
|
||||
// filled in. We move it out of `data.r` and return it.
|
||||
// 2. The closure panicked, in which case the panic payload was
|
||||
// filled in. We move it out of `data.p` and return it.
|
||||
//
|
||||
// Once we stack all that together we should have the "most efficient'
|
||||
// method of calling a catch panic whilst juggling ownership.
|
||||
let mut data = Data { f: ManuallyDrop::new(f) };
|
||||
|
||||
let data_ptr = (&raw mut data) as *mut u8;
|
||||
// SAFETY:
|
||||
//
|
||||
// Access to the union's fields: this is `std` and we know that the `catch_unwind`
|
||||
// intrinsic fills in the `r` or `p` union field based on its return value.
|
||||
//
|
||||
// The call to `intrinsics::catch_unwind` is made safe by:
|
||||
// - `do_call`, the first argument, can be called with the initial `data_ptr`.
|
||||
// - `do_catch`, the second argument, can be called with the `data_ptr` as well.
|
||||
// See their safety preconditions for more information
|
||||
unsafe {
|
||||
return if intrinsics::catch_unwind(do_call::<F, R>, data_ptr, do_catch::<F, R>) == 0 {
|
||||
Ok(ManuallyDrop::into_inner(data.r))
|
||||
} else {
|
||||
Err(ManuallyDrop::into_inner(data.p))
|
||||
};
|
||||
}
|
||||
|
||||
// We consider unwinding to be rare, so mark this function as cold. However,
|
||||
// do not mark it no-inline -- that decision is best to leave to the
|
||||
// optimizer (in most cases this function is not inlined even as a normal,
|
||||
// non-cold function, though, as of the writing of this comment).
|
||||
#[cold]
|
||||
#[optimize(size)]
|
||||
unsafe fn cleanup(payload: *mut u8) -> Box<dyn Any + Send + 'static> {
|
||||
// SAFETY: The whole unsafe block hinges on a correct implementation of
|
||||
// the panic handler `__rust_panic_cleanup`. As such we can only
|
||||
// assume it returns the correct thing for `Box::from_raw` to work
|
||||
// without undefined behavior.
|
||||
let obj = unsafe { Box::from_raw(__rust_panic_cleanup(payload)) };
|
||||
panic_count::decrease();
|
||||
obj
|
||||
}
|
||||
|
||||
// SAFETY:
|
||||
// data must be non-NUL, correctly aligned, and a pointer to a `Data<F, R>`
|
||||
// Its must contains a valid `f` (type: F) value that can be use to fill
|
||||
// `data.r`.
|
||||
//
|
||||
// This function cannot be marked as `unsafe` because `intrinsics::catch_unwind`
|
||||
// expects normal function pointers.
|
||||
#[inline]
|
||||
fn do_call<F: FnOnce() -> R, R>(data: *mut u8) {
|
||||
// SAFETY: this is the responsibility of the caller, see above.
|
||||
unsafe {
|
||||
let data = data as *mut Data<F, R>;
|
||||
let data = &mut (*data);
|
||||
let f = ManuallyDrop::take(&mut data.f);
|
||||
data.r = ManuallyDrop::new(f());
|
||||
}
|
||||
}
|
||||
|
||||
// We *do* want this part of the catch to be inlined: this allows the
|
||||
// compiler to properly track accesses to the Data union and optimize it
|
||||
// away most of the time.
|
||||
//
|
||||
// SAFETY:
|
||||
// data must be non-NUL, correctly aligned, and a pointer to a `Data<F, R>`
|
||||
// Since this uses `cleanup` it also hinges on a correct implementation of
|
||||
// `__rustc_panic_cleanup`.
|
||||
//
|
||||
// This function cannot be marked as `unsafe` because `intrinsics::catch_unwind`
|
||||
// expects normal function pointers.
|
||||
#[inline]
|
||||
#[rustc_nounwind] // `intrinsic::catch_unwind` requires catch fn to be nounwind
|
||||
fn do_catch<F: FnOnce() -> R, R>(data: *mut u8, payload: *mut u8) {
|
||||
// SAFETY: this is the responsibility of the caller, see above.
|
||||
//
|
||||
// When `__rustc_panic_cleaner` is correctly implemented we can rely
|
||||
// on `obj` being the correct thing to pass to `data.p` (after wrapping
|
||||
// in `ManuallyDrop`).
|
||||
unsafe {
|
||||
let data = data as *mut Data<F, R>;
|
||||
let data = &mut (*data);
|
||||
let obj = cleanup(payload);
|
||||
data.p = ManuallyDrop::new(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines whether the current thread is unwinding because of panic.
|
||||
#[inline]
|
||||
pub fn panicking() -> bool {
|
||||
!panic_count::count_is_zero()
|
||||
}
|
||||
|
||||
/// Entry point of panics from the core crate (`panic_impl` lang item).
|
||||
#[cfg(not(any(test, doctest)))]
|
||||
#[panic_handler]
|
||||
pub fn panic_handler(info: &core::panic::PanicInfo<'_>) -> ! {
|
||||
struct FormatStringPayload<'a> {
|
||||
inner: &'a core::panic::PanicMessage<'a>,
|
||||
string: Option<String>,
|
||||
}
|
||||
|
||||
impl FormatStringPayload<'_> {
|
||||
fn fill(&mut self) -> &mut String {
|
||||
let inner = self.inner;
|
||||
// Lazily, the first time this gets called, run the actual string formatting.
|
||||
self.string.get_or_insert_with(|| {
|
||||
let mut s = String::new();
|
||||
let mut fmt = fmt::Formatter::new(&mut s, fmt::FormattingOptions::new());
|
||||
let _err = fmt::Display::fmt(&inner, &mut fmt);
|
||||
s
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// begin_panic below).
|
||||
let contents = mem::take(self.fill());
|
||||
Box::into_raw(Box::new(contents))
|
||||
}
|
||||
|
||||
fn get(&mut self) -> &(dyn Any + Send) {
|
||||
self.fill()
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
fmt::Display::fmt(&self.inner, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct StaticStrPayload(&'static str);
|
||||
|
||||
unsafe impl PanicPayload for StaticStrPayload {
|
||||
fn take_box(&mut self) -> *mut (dyn Any + Send) {
|
||||
Box::into_raw(Box::new(self.0))
|
||||
}
|
||||
|
||||
fn get(&mut self) -> &(dyn Any + Send) {
|
||||
&self.0
|
||||
}
|
||||
|
||||
fn as_str(&mut self) -> Option<&str> {
|
||||
Some(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for StaticStrPayload {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
let loc = info.location().unwrap(); // The current implementation always returns Some
|
||||
let msg = info.message();
|
||||
crate::sys::backtrace::__rust_end_short_backtrace(move || {
|
||||
if let Some(s) = msg.as_str() {
|
||||
panic_with_hook(
|
||||
&mut StaticStrPayload(s),
|
||||
loc,
|
||||
info.can_unwind(),
|
||||
info.force_no_backtrace(),
|
||||
);
|
||||
} else {
|
||||
panic_with_hook(
|
||||
&mut FormatStringPayload { inner: &msg, string: None },
|
||||
loc,
|
||||
info.can_unwind(),
|
||||
info.force_no_backtrace(),
|
||||
);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// This is the entry point of panicking for the non-format-string variants of
|
||||
/// panic!() and assert!(). In particular, this is the only entry point that supports
|
||||
/// arbitrary payloads, not just format strings.
|
||||
#[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "none")]
|
||||
#[cfg_attr(not(any(test, doctest)), lang = "begin_panic")]
|
||||
// lang item for CTFE panic support
|
||||
// never inline unless panic=immediate-abort to avoid code
|
||||
// bloat at the call sites as much as possible
|
||||
#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(panic = "immediate-abort", inline)]
|
||||
#[track_caller]
|
||||
#[rustc_do_not_const_check] // hooked by const-eval
|
||||
pub const fn begin_panic<M: Any + Send>(msg: M) -> ! {
|
||||
if cfg!(panic = "immediate-abort") {
|
||||
intrinsics::abort()
|
||||
}
|
||||
|
||||
struct Payload<A> {
|
||||
inner: Option<A>,
|
||||
}
|
||||
|
||||
unsafe impl<A: Send + 'static> PanicPayload for Payload<A> {
|
||||
fn take_box(&mut self) -> *mut (dyn Any + Send) {
|
||||
// Note that this should be the only allocation performed in this code path. Currently
|
||||
// this means that panic!() on OOM will invoke this code path, but then again we're not
|
||||
// really ready for panic on OOM anyway. If we do start doing this, then we should
|
||||
// propagate this allocation to be performed in the parent of this thread instead of the
|
||||
// thread that's panicking.
|
||||
let data = match self.inner.take() {
|
||||
Some(a) => Box::new(a) as Box<dyn Any + Send>,
|
||||
None => process::abort(),
|
||||
};
|
||||
Box::into_raw(data)
|
||||
}
|
||||
|
||||
fn get(&mut self) -> &(dyn Any + Send) {
|
||||
match self.inner {
|
||||
Some(ref a) => a,
|
||||
None => process::abort(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: 'static> fmt::Display for Payload<A> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match &self.inner {
|
||||
Some(a) => f.write_str(payload_as_str(a)),
|
||||
None => process::abort(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let loc = Location::caller();
|
||||
crate::sys::backtrace::__rust_end_short_backtrace(move || {
|
||||
panic_with_hook(
|
||||
&mut Payload { inner: Some(msg) },
|
||||
loc,
|
||||
/* can_unwind */ true,
|
||||
/* force_no_backtrace */ false,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn payload_as_str(payload: &dyn Any) -> &str {
|
||||
if let Some(&s) = payload.downcast_ref::<&'static str>() {
|
||||
s
|
||||
} else if let Some(s) = payload.downcast_ref::<String>() {
|
||||
s.as_str()
|
||||
} else {
|
||||
"Box<dyn Any>"
|
||||
}
|
||||
}
|
||||
|
||||
/// Central point for dispatching panics.
|
||||
///
|
||||
/// Executes the primary logic for a panic, including checking for recursive
|
||||
/// panics, panic hooks, and finally dispatching to the panic runtime to either
|
||||
/// abort or unwind.
|
||||
#[optimize(size)]
|
||||
fn panic_with_hook(
|
||||
payload: &mut dyn PanicPayload,
|
||||
location: &Location<'_>,
|
||||
can_unwind: bool,
|
||||
force_no_backtrace: bool,
|
||||
) -> ! {
|
||||
let must_abort = panic_count::increase(true);
|
||||
|
||||
// Check if we need to abort immediately.
|
||||
if let Some(must_abort) = must_abort {
|
||||
match must_abort {
|
||||
panic_count::MustAbort::PanicInHook => {
|
||||
// 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 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
|
||||
// a `Backtrace` will allocate, which we must avoid here.
|
||||
rtprintpanic!("aborting due to panic at {location}:\n{payload}\n");
|
||||
}
|
||||
}
|
||||
crate::process::abort();
|
||||
}
|
||||
|
||||
match *HOOK.read() {
|
||||
// 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`
|
||||
// methods, this means we avoid formatting the string at all!
|
||||
// (The panic runtime might still call `payload.take_box()` though and trigger
|
||||
// formatting.)
|
||||
Hook::Default if panic_output().is_none() => {}
|
||||
Hook::Default => {
|
||||
default_hook(&PanicHookInfo::new(
|
||||
location,
|
||||
payload.get(),
|
||||
can_unwind,
|
||||
force_no_backtrace,
|
||||
));
|
||||
}
|
||||
Hook::Custom(ref hook) => {
|
||||
hook(&PanicHookInfo::new(location, payload.get(), can_unwind, force_no_backtrace));
|
||||
}
|
||||
}
|
||||
|
||||
// Indicate that we have finished executing the panic hook. After this point
|
||||
// it is fine if there is a panic while executing destructors, as long as it
|
||||
// it contained within a `catch_unwind`.
|
||||
panic_count::finished_panic_hook();
|
||||
|
||||
if !can_unwind {
|
||||
// If a thread panics while running destructors or tries to unwind
|
||||
// through a nounwind function (e.g. extern "C") then we cannot continue
|
||||
// unwinding and have to abort immediately.
|
||||
rtprintpanic!("thread caused non-unwinding panic. aborting.\n");
|
||||
crate::process::abort();
|
||||
}
|
||||
|
||||
rust_panic(payload)
|
||||
}
|
||||
|
||||
/// This is the entry point for `resume_unwind`.
|
||||
/// It just forwards the payload to the panic runtime.
|
||||
#[cfg_attr(panic = "immediate-abort", inline)]
|
||||
pub fn resume_unwind(payload: Box<dyn Any + Send>) -> ! {
|
||||
panic_count::increase(false);
|
||||
|
||||
struct RewrapBox(Box<dyn Any + Send>);
|
||||
|
||||
unsafe impl PanicPayload for RewrapBox {
|
||||
fn take_box(&mut self) -> *mut (dyn Any + Send) {
|
||||
Box::into_raw(mem::replace(&mut self.0, Box::new(())))
|
||||
}
|
||||
|
||||
fn get(&mut self) -> &(dyn Any + Send) {
|
||||
&*self.0
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
/// A function with a fixed suffix (through `rustc_std_internal_symbol`)
|
||||
/// on which to slap yer breakpoints.
|
||||
#[inline(never)]
|
||||
#[cfg_attr(not(test), rustc_std_internal_symbol)]
|
||||
#[cfg(not(panic = "immediate-abort"))]
|
||||
fn rust_panic(msg: &mut dyn PanicPayload) -> ! {
|
||||
let code = unsafe { __rust_start_panic(msg) };
|
||||
rtabort!("failed to initiate panic, error {code}")
|
||||
}
|
||||
|
||||
#[cfg_attr(not(test), rustc_std_internal_symbol)]
|
||||
#[cfg(panic = "immediate-abort")]
|
||||
fn rust_panic(_: &mut dyn PanicPayload) -> ! {
|
||||
crate::intrinsics::abort();
|
||||
}
|
||||
1
library/std/src/panicking.rs
Symbolic link
1
library/std/src/panicking.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs
|
||||
@@ -1,3 +0,0 @@
|
||||
//! Helper module for exporting the `pattern_type` macro
|
||||
|
||||
pub use core::pattern_type;
|
||||
1
library/std/src/pat.rs
Symbolic link
1
library/std/src/pat.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/pat.rs
|
||||
File diff suppressed because it is too large
Load Diff
1
library/std/src/path.rs
Symbolic link
1
library/std/src/path.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/path.rs
|
||||
File diff suppressed because it is too large
Load Diff
1
library/std/src/process.rs
Symbolic link
1
library/std/src/process.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/process.rs
|
||||
@@ -1,96 +0,0 @@
|
||||
//! Random value generation.
|
||||
|
||||
#[unstable(feature = "random", issue = "130703")]
|
||||
pub use core::random::*;
|
||||
|
||||
use crate::sys::random as sys;
|
||||
|
||||
/// The default random source.
|
||||
///
|
||||
/// This asks the system for random data suitable for cryptographic purposes
|
||||
/// such as key generation. If security is a concern, consult the platform
|
||||
/// documentation below for the specific guarantees your target provides.
|
||||
///
|
||||
/// The high quality of randomness provided by this source means it can be quite
|
||||
/// slow on some targets. If you need a large quantity of random numbers and
|
||||
/// security is not a concern, consider using an alternative random number
|
||||
/// generator (potentially seeded from this one).
|
||||
///
|
||||
/// # Underlying sources
|
||||
///
|
||||
/// Platform | Source
|
||||
/// -----------------------|---------------------------------------------------------------
|
||||
/// Linux | [`getrandom`] or [`/dev/urandom`] after polling `/dev/random`
|
||||
/// Windows | [`ProcessPrng`](https://learn.microsoft.com/en-us/windows/win32/seccng/processprng)
|
||||
/// Apple | `CCRandomGenerateBytes`
|
||||
/// DragonFly | [`arc4random_buf`](https://man.dragonflybsd.org/?command=arc4random)
|
||||
/// ESP-IDF | [`esp_fill_random`](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/random.html#_CPPv415esp_fill_randomPv6size_t)
|
||||
/// FreeBSD | [`arc4random_buf`](https://man.freebsd.org/cgi/man.cgi?query=arc4random)
|
||||
/// Fuchsia | [`cprng_draw`](https://fuchsia.dev/reference/syscalls/cprng_draw)
|
||||
/// Haiku | `arc4random_buf`
|
||||
/// Illumos | [`arc4random_buf`](https://www.illumos.org/man/3C/arc4random)
|
||||
/// NetBSD | [`arc4random_buf`](https://man.netbsd.org/arc4random.3)
|
||||
/// OpenBSD | [`arc4random_buf`](https://man.openbsd.org/arc4random.3)
|
||||
/// Solaris | [`arc4random_buf`](https://docs.oracle.com/cd/E88353_01/html/E37843/arc4random-3c.html)
|
||||
/// Vita | `arc4random_buf`
|
||||
/// Hermit | `read_entropy`
|
||||
/// Horizon, Cygwin | `getrandom`
|
||||
/// AIX, Hurd, L4Re, QNX | `/dev/urandom`
|
||||
/// Redox | `/scheme/rand`
|
||||
/// RTEMS | [`arc4random_buf`](https://docs.rtems.org/branches/main/bsp-howto/getentropy.html)
|
||||
/// SGX | [`rdrand`](https://en.wikipedia.org/wiki/RDRAND)
|
||||
/// SOLID | `SOLID_RNG_SampleRandomBytes`
|
||||
/// TEEOS | `TEE_GenerateRandom`
|
||||
/// UEFI | [`EFI_RNG_PROTOCOL`](https://uefi.org/specs/UEFI/2.10/37_Secure_Technologies.html#random-number-generator-protocol)
|
||||
/// VxWorks | `randABytes` after waiting for `randSecure` to become ready
|
||||
/// WASI | [`random_get`](https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#-random_getbuf-pointeru8-buf_len-size---result-errno)
|
||||
/// ZKVM | `sys_rand`
|
||||
///
|
||||
/// Note that the sources used might change over time.
|
||||
///
|
||||
/// Consult the documentation for the underlying operations on your supported
|
||||
/// targets to determine whether they provide any particular desired properties,
|
||||
/// such as support for reseeding on VM fork operations.
|
||||
///
|
||||
/// [`getrandom`]: https://www.man7.org/linux/man-pages/man2/getrandom.2.html
|
||||
/// [`/dev/urandom`]: https://www.man7.org/linux/man-pages/man4/random.4.html
|
||||
#[derive(Default, Debug, Clone, Copy)]
|
||||
#[unstable(feature = "random", issue = "130703")]
|
||||
pub struct DefaultRandomSource;
|
||||
|
||||
#[unstable(feature = "random", issue = "130703")]
|
||||
impl RandomSource for DefaultRandomSource {
|
||||
fn fill_bytes(&mut self, bytes: &mut [u8]) {
|
||||
sys::fill_bytes(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a random value from a distribution, using the default random source.
|
||||
///
|
||||
/// This is a convenience function for `dist.sample(&mut DefaultRandomSource)` and will sample
|
||||
/// according to the same distribution as the underlying [`Distribution`] trait implementation. See
|
||||
/// [`DefaultRandomSource`] for more information about how randomness is sourced.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Generating a [version 4/variant 1 UUID] represented as text:
|
||||
/// ```
|
||||
/// #![feature(random)]
|
||||
///
|
||||
/// use std::random::random;
|
||||
///
|
||||
/// let bits: u128 = random(..);
|
||||
/// let g1 = (bits >> 96) as u32;
|
||||
/// let g2 = (bits >> 80) as u16;
|
||||
/// let g3 = (0x4000 | (bits >> 64) & 0x0fff) as u16;
|
||||
/// let g4 = (0x8000 | (bits >> 48) & 0x3fff) as u16;
|
||||
/// let g5 = (bits & 0xffffffffffff) as u64;
|
||||
/// let uuid = format!("{g1:08x}-{g2:04x}-{g3:04x}-{g4:04x}-{g5:012x}");
|
||||
/// println!("{uuid}");
|
||||
/// ```
|
||||
///
|
||||
/// [version 4/variant 1 UUID]: https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)
|
||||
#[unstable(feature = "random", issue = "130703")]
|
||||
pub fn random<T>(dist: impl Distribution<T>) -> T {
|
||||
dist.sample(&mut DefaultRandomSource)
|
||||
}
|
||||
1
library/std/src/random.rs
Symbolic link
1
library/std/src/random.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/random.rs
|
||||
@@ -1,211 +0,0 @@
|
||||
//! Runtime services
|
||||
//!
|
||||
//! The `rt` module provides a narrow set of runtime services,
|
||||
//! including the global heap (exported in `heap`) and unwinding and
|
||||
//! backtrace support. The APIs in this module are highly unstable,
|
||||
//! and should be considered as private implementation details for the
|
||||
//! time being.
|
||||
|
||||
#![unstable(
|
||||
feature = "rt",
|
||||
reason = "this public module should not exist and is highly likely \
|
||||
to disappear",
|
||||
issue = "none"
|
||||
)]
|
||||
#![doc(hidden)]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
#![allow(unused_macros)]
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub use crate::panicking::{begin_panic, panic_count};
|
||||
pub use core::panicking::{panic_display, panic_fmt};
|
||||
|
||||
#[rustfmt::skip]
|
||||
use crate::any::Any;
|
||||
use crate::sync::Once;
|
||||
use crate::thread::{self, main_thread};
|
||||
use crate::{mem, panic, sys};
|
||||
|
||||
// This function is needed by the panic runtime.
|
||||
#[cfg(not(test))]
|
||||
#[rustc_std_internal_symbol]
|
||||
fn __rust_abort() {
|
||||
crate::process::abort();
|
||||
}
|
||||
|
||||
// Prints to the "panic output", depending on the platform this may be:
|
||||
// - the standard error output
|
||||
// - some dedicated platform specific output
|
||||
// - nothing (so this macro is a no-op)
|
||||
macro_rules! rtprintpanic {
|
||||
($($t:tt)*) => {
|
||||
#[cfg(not(panic = "immediate-abort"))]
|
||||
if let Some(mut out) = crate::sys::stdio::panic_output() {
|
||||
let _ = crate::io::Write::write_fmt(&mut out, format_args!($($t)*));
|
||||
}
|
||||
#[cfg(panic = "immediate-abort")]
|
||||
{
|
||||
let _ = format_args!($($t)*);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! rtabort {
|
||||
($($t:tt)*) => {
|
||||
{
|
||||
rtprintpanic!("fatal runtime error: {}, aborting\n", format_args!($($t)*));
|
||||
crate::process::abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! rtassert {
|
||||
($e:expr) => {
|
||||
if !$e {
|
||||
rtabort!(concat!("assertion failed: ", stringify!($e)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! rtunwrap {
|
||||
($ok:ident, $e:expr) => {
|
||||
match $e {
|
||||
$ok(v) => v,
|
||||
ref err => {
|
||||
let err = err.as_ref().map(drop); // map Ok/Some which might not be Debug
|
||||
rtabort!(concat!("unwrap failed: ", stringify!($e), " = {:?}"), err)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn handle_rt_panic<T>(e: Box<dyn Any + Send>) -> T {
|
||||
mem::forget(e);
|
||||
rtabort!("initialization or cleanup bug");
|
||||
}
|
||||
|
||||
// One-time runtime initialization.
|
||||
// Runs before `main`.
|
||||
// SAFETY: must be called only once during runtime initialization.
|
||||
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
|
||||
//
|
||||
// # The `sigpipe` parameter
|
||||
//
|
||||
// Since 2014, the Rust runtime on Unix has set the `SIGPIPE` handler to
|
||||
// `SIG_IGN`. Applications have good reasons to want a different behavior
|
||||
// though, so there is a `-Zon-broken-pipe` compiler flag that
|
||||
// can be used to select how `SIGPIPE` shall be setup (if changed at all) before
|
||||
// `fn main()` is called. See <https://github.com/rust-lang/rust/issues/97889>
|
||||
// for more info.
|
||||
//
|
||||
// The `sigpipe` parameter to this function gets its value via the code that
|
||||
// rustc generates to invoke `fn lang_start()`. The reason we have `sigpipe` for
|
||||
// all platforms and not only Unix, is because std is not allowed to have `cfg`
|
||||
// directives as this high level. See the module docs in
|
||||
// `src/tools/tidy/src/pal.rs` for more info. On all other platforms, `sigpipe`
|
||||
// has a value, but its value is ignored.
|
||||
//
|
||||
// Even though it is an `u8`, it only ever has 4 values. These are documented in
|
||||
// `compiler/rustc_session/src/config/sigpipe.rs`.
|
||||
#[cfg_attr(test, allow(dead_code))]
|
||||
unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
|
||||
// Remember the main thread ID to give it the correct name.
|
||||
// SAFETY: this is the only time and place where we call this function.
|
||||
unsafe { main_thread::set(thread::current_id()) };
|
||||
|
||||
#[cfg_attr(target_os = "teeos", allow(unused_unsafe))]
|
||||
unsafe {
|
||||
sys::init(argc, argv, sigpipe)
|
||||
};
|
||||
}
|
||||
|
||||
/// Clean up the thread-local runtime state. This *should* be run after all other
|
||||
/// code managed by the Rust runtime, but will not cause UB if that condition is
|
||||
/// not fulfilled. Also note that this function is not guaranteed to be run, but
|
||||
/// skipping it will cause leaks and therefore is to be avoided.
|
||||
pub(crate) fn thread_cleanup() {
|
||||
// This function is run in situations where unwinding leads to an abort
|
||||
// (think `extern "C"` functions). Abort here instead so that we can
|
||||
// print a nice message.
|
||||
panic::catch_unwind(|| {
|
||||
crate::thread::drop_current();
|
||||
})
|
||||
.unwrap_or_else(handle_rt_panic);
|
||||
}
|
||||
|
||||
// One-time runtime cleanup.
|
||||
// Runs after `main` or at program exit.
|
||||
// NOTE: this is not guaranteed to run, for example when the program aborts.
|
||||
pub(crate) fn cleanup() {
|
||||
static CLEANUP: Once = Once::new();
|
||||
CLEANUP.call_once(|| unsafe {
|
||||
// Flush stdout and disable buffering.
|
||||
crate::io::cleanup();
|
||||
// SAFETY: Only called once during runtime cleanup.
|
||||
sys::cleanup();
|
||||
});
|
||||
}
|
||||
|
||||
// To reduce the generated code of the new `lang_start`, this function is doing
|
||||
// the real work.
|
||||
#[cfg(not(test))]
|
||||
fn lang_start_internal(
|
||||
main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindSafe),
|
||||
argc: isize,
|
||||
argv: *const *const u8,
|
||||
sigpipe: u8,
|
||||
) -> isize {
|
||||
// Guard against the code called by this function from unwinding outside of the Rust-controlled
|
||||
// code, which is UB. This is a requirement imposed by a combination of how the
|
||||
// `#[lang="start"]` attribute is implemented as well as by the implementation of the panicking
|
||||
// mechanism itself.
|
||||
//
|
||||
// There are a couple of instances where unwinding can begin. First is inside of the
|
||||
// `rt::init`, `rt::cleanup` and similar functions controlled by std. In those instances a
|
||||
// panic is a std implementation bug. A quite likely one too, as there isn't any way to
|
||||
// prevent std from accidentally introducing a panic to these functions. Another is from
|
||||
// user code from `main` or, more nefariously, as described in e.g. issue #86030.
|
||||
//
|
||||
// We use `catch_unwind` with `handle_rt_panic` instead of `abort_unwind` to make the error in
|
||||
// case of a panic a bit nicer.
|
||||
panic::catch_unwind(move || {
|
||||
// SAFETY: Only called once during runtime initialization.
|
||||
unsafe { init(argc, argv, sigpipe) };
|
||||
|
||||
let ret_code = panic::catch_unwind(main).unwrap_or_else(move |payload| {
|
||||
// Carefully dispose of the panic payload.
|
||||
let payload = panic::AssertUnwindSafe(payload);
|
||||
panic::catch_unwind(move || drop({ payload }.0)).unwrap_or_else(move |e| {
|
||||
mem::forget(e); // do *not* drop the 2nd payload
|
||||
rtabort!("drop of the panic payload panicked");
|
||||
});
|
||||
// Return error code for panicking programs.
|
||||
101
|
||||
});
|
||||
let ret_code = ret_code as isize;
|
||||
|
||||
cleanup();
|
||||
// Guard against multiple threads calling `libc::exit` concurrently.
|
||||
// See the documentation for `unique_thread_exit` for more information.
|
||||
crate::sys::exit::unique_thread_exit();
|
||||
|
||||
ret_code
|
||||
})
|
||||
.unwrap_or_else(handle_rt_panic)
|
||||
}
|
||||
|
||||
#[cfg(not(any(test, doctest)))]
|
||||
#[lang = "start"]
|
||||
fn lang_start<T: crate::process::Termination + 'static>(
|
||||
main: fn() -> T,
|
||||
argc: isize,
|
||||
argv: *const *const u8,
|
||||
sigpipe: u8,
|
||||
) -> isize {
|
||||
lang_start_internal(
|
||||
&move || crate::sys::backtrace::__rust_begin_short_backtrace(main).report().to_i32(),
|
||||
argc,
|
||||
argv,
|
||||
sigpipe,
|
||||
)
|
||||
}
|
||||
1
library/std/src/rt.rs
Symbolic link
1
library/std/src/rt.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/rt.rs
|
||||
@@ -1,42 +0,0 @@
|
||||
use crate::ffi::OsString;
|
||||
use crate::fmt;
|
||||
|
||||
pub struct Args {}
|
||||
|
||||
pub fn args() -> Args {
|
||||
Args {}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Args {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_list().finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Args {
|
||||
type Item = OsString;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<OsString> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(0, Some(0))
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Args {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<OsString> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Args {
|
||||
#[inline]
|
||||
fn len(&self) -> usize {
|
||||
0
|
||||
}
|
||||
}
|
||||
1
library/std/src/sys/args/unsupported.rs
Symbolic link
1
library/std/src/sys/args/unsupported.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/args/unsupported.rs
|
||||
@@ -1,238 +0,0 @@
|
||||
//! Common code for printing backtraces.
|
||||
#![forbid(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
use crate::backtrace_rs::{self, BacktraceFmt, BytesOrWideString, PrintFmt};
|
||||
use crate::borrow::Cow;
|
||||
use crate::io::prelude::*;
|
||||
use crate::path::{self, Path, PathBuf};
|
||||
use crate::sync::{Mutex, MutexGuard, PoisonError};
|
||||
use crate::{env, fmt, io};
|
||||
|
||||
/// Max number of frames to print.
|
||||
const MAX_NB_FRAMES: usize = 100;
|
||||
|
||||
pub(crate) const FULL_BACKTRACE_DEFAULT: bool = cfg_select! {
|
||||
// Fuchsia components default to full backtrace.
|
||||
target_os = "fuchsia" => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
pub(crate) struct BacktraceLock<'a>(#[allow(dead_code)] MutexGuard<'a, ()>);
|
||||
|
||||
pub(crate) fn lock<'a>() -> BacktraceLock<'a> {
|
||||
static LOCK: Mutex<()> = Mutex::new(());
|
||||
BacktraceLock(LOCK.lock().unwrap_or_else(PoisonError::into_inner))
|
||||
}
|
||||
|
||||
impl BacktraceLock<'_> {
|
||||
/// Prints the current backtrace.
|
||||
pub(crate) fn print(&mut self, w: &mut dyn Write, format: PrintFmt) -> io::Result<()> {
|
||||
// There are issues currently linking libbacktrace into tests, and in
|
||||
// general during std's own unit tests we're not testing this path. In
|
||||
// test mode immediately return here to optimize away any references to the
|
||||
// libbacktrace symbols
|
||||
if cfg!(test) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
struct DisplayBacktrace {
|
||||
format: PrintFmt,
|
||||
}
|
||||
impl fmt::Display for DisplayBacktrace {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// SAFETY: the backtrace lock is held
|
||||
unsafe { _print_fmt(fmt, self.format) }
|
||||
}
|
||||
}
|
||||
write!(w, "{}", DisplayBacktrace { format })
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is not Sync. The caller must hold a mutex lock, or there must be only one thread in the program.
|
||||
unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::Result {
|
||||
// Always 'fail' to get the cwd when running under Miri -
|
||||
// this allows Miri to display backtraces in isolation mode
|
||||
let cwd = if !cfg!(miri) { env::current_dir().ok() } else { None };
|
||||
|
||||
let mut print_path = move |fmt: &mut fmt::Formatter<'_>, bows: BytesOrWideString<'_>| {
|
||||
output_filename(fmt, bows, print_fmt, cwd.as_ref())
|
||||
};
|
||||
writeln!(fmt, "stack backtrace:")?;
|
||||
let mut bt_fmt = BacktraceFmt::new(fmt, print_fmt, &mut print_path);
|
||||
bt_fmt.add_context()?;
|
||||
let mut idx = 0;
|
||||
let mut res = Ok(());
|
||||
let mut omitted_count: usize = 0;
|
||||
let mut first_omit = true;
|
||||
// If we're using a short backtrace, ignore all frames until we're told to start printing.
|
||||
let mut print = print_fmt != PrintFmt::Short;
|
||||
set_image_base();
|
||||
// SAFETY: we roll our own locking in this town
|
||||
unsafe {
|
||||
backtrace_rs::trace_unsynchronized(|frame| {
|
||||
if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES {
|
||||
return false;
|
||||
}
|
||||
|
||||
if cfg!(feature = "backtrace-trace-only") {
|
||||
const HEX_WIDTH: usize = 2 + 2 * size_of::<usize>();
|
||||
let frame_ip = frame.ip();
|
||||
res = writeln!(bt_fmt.formatter(), "{idx:4}: {frame_ip:HEX_WIDTH$?}");
|
||||
} else {
|
||||
let mut hit = false;
|
||||
backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
|
||||
hit = true;
|
||||
|
||||
// `__rust_end_short_backtrace` means we are done hiding symbols
|
||||
// for now. Print until we see `__rust_begin_short_backtrace`.
|
||||
if print_fmt == PrintFmt::Short {
|
||||
if let Some(sym) = symbol.name().and_then(|s| s.as_str()) {
|
||||
if sym.contains("__rust_end_short_backtrace") {
|
||||
print = true;
|
||||
return;
|
||||
}
|
||||
if print && sym.contains("__rust_begin_short_backtrace") {
|
||||
print = false;
|
||||
return;
|
||||
}
|
||||
if !print {
|
||||
omitted_count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if print {
|
||||
if omitted_count > 0 {
|
||||
debug_assert!(print_fmt == PrintFmt::Short);
|
||||
// only print the message between the middle of frames
|
||||
if !first_omit {
|
||||
let _ = writeln!(
|
||||
bt_fmt.formatter(),
|
||||
" [... omitted {} frame{} ...]",
|
||||
omitted_count,
|
||||
if omitted_count > 1 { "s" } else { "" }
|
||||
);
|
||||
}
|
||||
first_omit = false;
|
||||
omitted_count = 0;
|
||||
}
|
||||
res = bt_fmt.frame().symbol(frame, symbol);
|
||||
}
|
||||
});
|
||||
#[cfg(all(target_os = "nto", any(target_env = "nto70", target_env = "nto71")))]
|
||||
if libc::__my_thread_exit as *mut libc::c_void == frame.ip() {
|
||||
if !hit && print {
|
||||
use crate::backtrace_rs::SymbolName;
|
||||
res = bt_fmt.frame().print_raw(
|
||||
frame.ip(),
|
||||
Some(SymbolName::new("__my_thread_exit".as_bytes())),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if !hit && print {
|
||||
res = bt_fmt.frame().print_raw(frame.ip(), None, None, None);
|
||||
}
|
||||
}
|
||||
|
||||
idx += 1;
|
||||
res.is_ok()
|
||||
})
|
||||
};
|
||||
res?;
|
||||
bt_fmt.finish()?;
|
||||
if print_fmt == PrintFmt::Short {
|
||||
writeln!(
|
||||
fmt,
|
||||
"note: Some details are omitted, \
|
||||
run with `RUST_BACKTRACE=full` for a verbose backtrace."
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. Note that
|
||||
/// this is only inline(never) when backtraces in std are enabled, otherwise
|
||||
/// it's fine to optimize away.
|
||||
#[cfg_attr(feature = "backtrace", inline(never))]
|
||||
pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
let result = f();
|
||||
|
||||
// prevent this frame from being tail-call optimised away
|
||||
crate::hint::black_box(());
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. Note that
|
||||
/// this is only inline(never) when backtraces in std are enabled, otherwise
|
||||
/// it's fine to optimize away.
|
||||
#[cfg_attr(feature = "backtrace", inline(never))]
|
||||
pub fn __rust_end_short_backtrace<F, T>(f: F) -> T
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
let result = f();
|
||||
|
||||
// prevent this frame from being tail-call optimised away
|
||||
crate::hint::black_box(());
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Prints the filename of the backtrace frame.
|
||||
///
|
||||
/// See also `output`.
|
||||
pub fn output_filename(
|
||||
fmt: &mut fmt::Formatter<'_>,
|
||||
bows: BytesOrWideString<'_>,
|
||||
print_fmt: PrintFmt,
|
||||
cwd: Option<&PathBuf>,
|
||||
) -> fmt::Result {
|
||||
let file: Cow<'_, Path> = match bows {
|
||||
#[cfg(unix)]
|
||||
BytesOrWideString::Bytes(bytes) => {
|
||||
use crate::os::unix::prelude::*;
|
||||
Path::new(crate::ffi::OsStr::from_bytes(bytes)).into()
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
BytesOrWideString::Bytes(bytes) => {
|
||||
Path::new(crate::str::from_utf8(bytes).unwrap_or("<unknown>")).into()
|
||||
}
|
||||
#[cfg(windows)]
|
||||
BytesOrWideString::Wide(wide) => {
|
||||
use crate::os::windows::prelude::*;
|
||||
Cow::Owned(crate::ffi::OsString::from_wide(wide).into())
|
||||
}
|
||||
#[cfg(not(windows))]
|
||||
BytesOrWideString::Wide(_wide) => Path::new("<unknown>").into(),
|
||||
};
|
||||
if print_fmt == PrintFmt::Short && file.is_absolute() {
|
||||
if let Some(cwd) = cwd {
|
||||
if let Ok(stripped) = file.strip_prefix(&cwd) {
|
||||
if let Some(s) = stripped.to_str() {
|
||||
return write!(fmt, ".{}{s}", path::MAIN_SEPARATOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt::Display::fmt(&file.display(), fmt)
|
||||
}
|
||||
|
||||
#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
|
||||
pub fn set_image_base() {
|
||||
let image_base = crate::os::fortanix_sgx::mem::image_base();
|
||||
backtrace_rs::set_image_base(crate::ptr::without_provenance_mut(image_base as _));
|
||||
}
|
||||
|
||||
#[cfg(not(all(target_vendor = "fortanix", target_env = "sgx")))]
|
||||
pub fn set_image_base() {
|
||||
// nothing to do for platforms other than SGX
|
||||
}
|
||||
1
library/std/src/sys/backtrace.rs
Symbolic link
1
library/std/src/sys/backtrace.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/backtrace.rs
|
||||
@@ -1,114 +0,0 @@
|
||||
#![cfg(not(test))]
|
||||
|
||||
// These symbols are all defined by `libm`,
|
||||
// or by `compiler-builtins` on unsupported platforms.
|
||||
unsafe extern "C" {
|
||||
pub safe fn acos(n: f64) -> f64;
|
||||
pub safe fn asin(n: f64) -> f64;
|
||||
pub safe fn atan(n: f64) -> f64;
|
||||
pub safe fn atan2(a: f64, b: f64) -> f64;
|
||||
pub safe fn cosh(n: f64) -> f64;
|
||||
pub safe fn expm1(n: f64) -> f64;
|
||||
pub safe fn expm1f(n: f32) -> f32;
|
||||
#[cfg_attr(target_env = "msvc", link_name = "_hypot")]
|
||||
pub safe fn hypot(x: f64, y: f64) -> f64;
|
||||
#[cfg_attr(target_env = "msvc", link_name = "_hypotf")]
|
||||
pub safe fn hypotf(x: f32, y: f32) -> f32;
|
||||
pub safe fn log1p(n: f64) -> f64;
|
||||
pub safe fn log1pf(n: f32) -> f32;
|
||||
pub safe fn sinh(n: f64) -> f64;
|
||||
pub safe fn tan(n: f64) -> f64;
|
||||
pub safe fn tanh(n: f64) -> f64;
|
||||
pub safe fn tgamma(n: f64) -> f64;
|
||||
pub safe fn tgammaf(n: f32) -> f32;
|
||||
pub safe fn lgamma_r(n: f64, s: &mut i32) -> f64;
|
||||
#[cfg(not(target_os = "aix"))]
|
||||
pub safe fn lgammaf_r(n: f32, s: &mut i32) -> f32;
|
||||
pub safe fn erf(n: f64) -> f64;
|
||||
pub safe fn erff(n: f32) -> f32;
|
||||
pub safe fn erfc(n: f64) -> f64;
|
||||
pub safe fn erfcf(n: f32) -> f32;
|
||||
|
||||
pub safe fn acosf128(n: f128) -> f128;
|
||||
pub safe fn asinf128(n: f128) -> f128;
|
||||
pub safe fn atanf128(n: f128) -> f128;
|
||||
pub safe fn atan2f128(a: f128, b: f128) -> f128;
|
||||
pub safe fn cbrtf128(n: f128) -> f128;
|
||||
pub safe fn coshf128(n: f128) -> f128;
|
||||
pub safe fn expm1f128(n: f128) -> f128;
|
||||
pub safe fn hypotf128(x: f128, y: f128) -> f128;
|
||||
pub safe fn log1pf128(n: f128) -> f128;
|
||||
pub safe fn sinhf128(n: f128) -> f128;
|
||||
pub safe fn tanf128(n: f128) -> f128;
|
||||
pub safe fn tanhf128(n: f128) -> f128;
|
||||
pub safe fn tgammaf128(n: f128) -> f128;
|
||||
pub safe fn lgammaf128_r(n: f128, s: &mut i32) -> f128;
|
||||
pub safe fn erff128(n: f128) -> f128;
|
||||
pub safe fn erfcf128(n: f128) -> f128;
|
||||
}
|
||||
|
||||
cfg_select! {
|
||||
all(target_os = "windows", target_env = "msvc", target_arch = "x86") => {
|
||||
// On 32-bit x86 MSVC these functions aren't defined, so we just define shims
|
||||
// which promote everything to f64, perform the calculation, and then demote
|
||||
// back to f32. While not precisely correct should be "correct enough" for now.
|
||||
#[inline]
|
||||
pub fn acosf(n: f32) -> f32 {
|
||||
f64::acos(n as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn asinf(n: f32) -> f32 {
|
||||
f64::asin(n as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn atan2f(n: f32, b: f32) -> f32 {
|
||||
f64::atan2(n as f64, b as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn atanf(n: f32) -> f32 {
|
||||
f64::atan(n as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn coshf(n: f32) -> f32 {
|
||||
f64::cosh(n as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn sinhf(n: f32) -> f32 {
|
||||
f64::sinh(n as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn tanf(n: f32) -> f32 {
|
||||
f64::tan(n as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn tanhf(n: f32) -> f32 {
|
||||
f64::tanh(n as f64) as f32
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unsafe extern "C" {
|
||||
pub safe fn acosf(n: f32) -> f32;
|
||||
pub safe fn asinf(n: f32) -> f32;
|
||||
pub safe fn atan2f(a: f32, b: f32) -> f32;
|
||||
pub safe fn atanf(n: f32) -> f32;
|
||||
pub safe fn coshf(n: f32) -> f32;
|
||||
pub safe fn sinhf(n: f32) -> f32;
|
||||
pub safe fn tanf(n: f32) -> f32;
|
||||
pub safe fn tanhf(n: f32) -> f32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// On AIX, we don't have lgammaf_r only the f64 version, so we can
|
||||
// use the f64 version lgamma_r
|
||||
#[cfg(target_os = "aix")]
|
||||
pub fn lgammaf_r(n: f32, s: &mut i32) -> f32 {
|
||||
lgamma_r(n.into(), s) as f32
|
||||
}
|
||||
1
library/std/src/sys/cmath.rs
Symbolic link
1
library/std/src/sys/cmath.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/cmath.rs
|
||||
@@ -1,62 +0,0 @@
|
||||
//! The configure builtins provides runtime support compiler-builtin features
|
||||
//! which require dynamic initialization to work as expected, e.g. aarch64
|
||||
//! outline-atomics.
|
||||
|
||||
/// Enable LSE atomic operations at startup, if supported.
|
||||
///
|
||||
/// Linker sections are based on what [`ctor`] does, with priorities to run slightly before user
|
||||
/// code:
|
||||
///
|
||||
/// - Apple uses the section `__mod_init_func`, `mod_init_funcs` is needed to set
|
||||
/// `S_MOD_INIT_FUNC_POINTERS`. There doesn't seem to be a way to indicate priorities.
|
||||
/// - Windows uses `.CRT$XCT`, which is run before user constructors (these should use `.CRT$XCU`).
|
||||
/// - ELF uses `.init_array` with a priority of 90, which runs before our `ARGV_INIT_ARRAY`
|
||||
/// initializer (priority 99). Both are within the 0-100 implementation-reserved range, per docs
|
||||
/// for the [`prio-ctor-dtor`] warning, and this matches compiler-rt's `CONSTRUCTOR_PRIORITY`.
|
||||
///
|
||||
/// To save startup time, the initializer is only run if outline atomic routines from
|
||||
/// compiler-builtins may be used. If LSE is known to be available then the calls are never
|
||||
/// emitted, and if we build the C intrinsics then it has its own initializer using the symbol
|
||||
/// `__aarch64_have_lse_atomics`.
|
||||
///
|
||||
/// Initialization is done in a global constructor to so we get the same behavior regardless of
|
||||
/// whether Rust's `init` is used, or if we are in a `dylib` or `no_main` situation (as opposed
|
||||
/// to doing it as part of pre-main startup). This also matches C implementations.
|
||||
///
|
||||
/// Ideally `core` would have something similar, but detecting the CPU features requires the
|
||||
/// auxiliary vector from the OS. We do the initialization in `std` rather than as part of
|
||||
/// `compiler-builtins` because a builtins->std dependency isn't possible, and inlining parts of
|
||||
/// `std-detect` would be much messier.
|
||||
///
|
||||
/// [`ctor`]: https://github.com/mmastrac/rust-ctor/blob/63382b833ddcbfb8b064f4e86bfa1ed4026ff356/shared/src/macros/mod.rs#L522-L534
|
||||
/// [`prio-ctor-dtor`]: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
|
||||
#[cfg(all(
|
||||
target_arch = "aarch64",
|
||||
target_feature = "outline-atomics",
|
||||
not(target_feature = "lse"),
|
||||
not(feature = "compiler-builtins-c"),
|
||||
))]
|
||||
#[used]
|
||||
#[cfg_attr(target_vendor = "apple", unsafe(link_section = "__DATA,__mod_init_func,mod_init_funcs"))]
|
||||
#[cfg_attr(target_os = "windows", unsafe(link_section = ".CRT$XCT"))]
|
||||
#[cfg_attr(
|
||||
not(any(target_vendor = "apple", target_os = "windows")),
|
||||
unsafe(link_section = ".init_array.90")
|
||||
)]
|
||||
static RUST_LSE_INIT: extern "C" fn() = {
|
||||
extern "C" fn init_lse() {
|
||||
use crate::arch;
|
||||
|
||||
// This is provided by compiler-builtins::aarch64_outline_atomics.
|
||||
unsafe extern "C" {
|
||||
fn __rust_enable_lse();
|
||||
}
|
||||
|
||||
if arch::is_aarch64_feature_detected!("lse") {
|
||||
unsafe {
|
||||
__rust_enable_lse();
|
||||
}
|
||||
}
|
||||
}
|
||||
init_lse
|
||||
};
|
||||
1
library/std/src/sys/configure_builtins.rs
Symbolic link
1
library/std/src/sys/configure_builtins.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/configure_builtins.rs
|
||||
31
library/std/src/sys/env/common.rs
vendored
31
library/std/src/sys/env/common.rs
vendored
@@ -1,31 +0,0 @@
|
||||
use crate::ffi::OsString;
|
||||
use crate::{fmt, vec};
|
||||
|
||||
pub struct Env {
|
||||
iter: vec::IntoIter<(OsString, OsString)>,
|
||||
}
|
||||
|
||||
impl Env {
|
||||
pub(super) fn new(env: Vec<(OsString, OsString)>) -> Self {
|
||||
Env { iter: env.into_iter() }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_list().entries(self.iter.as_slice()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl !Send for Env {}
|
||||
impl !Sync for Env {}
|
||||
|
||||
impl Iterator for Env {
|
||||
type Item = (OsString, OsString);
|
||||
fn next(&mut self) -> Option<(OsString, OsString)> {
|
||||
self.iter.next()
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
1
library/std/src/sys/env/common.rs
vendored
Symbolic link
1
library/std/src/sys/env/common.rs
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/env/common.rs
|
||||
62
library/std/src/sys/env/mod.rs
vendored
62
library/std/src/sys/env/mod.rs
vendored
@@ -1,62 +0,0 @@
|
||||
//! Platform-dependent environment variables abstraction.
|
||||
|
||||
#![forbid(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
#[cfg(any(
|
||||
target_family = "unix",
|
||||
target_os = "hermit",
|
||||
target_os = "motor",
|
||||
all(target_vendor = "fortanix", target_env = "sgx"),
|
||||
target_os = "solid_asp3",
|
||||
target_os = "uefi",
|
||||
target_os = "wasi",
|
||||
target_os = "xous",
|
||||
))]
|
||||
mod common;
|
||||
|
||||
cfg_select! {
|
||||
target_family = "unix" => {
|
||||
mod unix;
|
||||
pub use unix::*;
|
||||
}
|
||||
target_family = "windows" => {
|
||||
mod windows;
|
||||
pub use windows::*;
|
||||
}
|
||||
target_os = "hermit" => {
|
||||
mod hermit;
|
||||
pub use hermit::*;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
pub use motor::*;
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
mod sgx;
|
||||
pub use sgx::*;
|
||||
}
|
||||
target_os = "solid_asp3" => {
|
||||
mod solid;
|
||||
pub use solid::*;
|
||||
}
|
||||
target_os = "uefi" => {
|
||||
mod uefi;
|
||||
pub use uefi::*;
|
||||
}
|
||||
target_os = "wasi" => {
|
||||
mod wasi;
|
||||
pub use wasi::*;
|
||||
}
|
||||
target_os = "xous" => {
|
||||
mod xous;
|
||||
pub use xous::*;
|
||||
}
|
||||
target_os = "zkvm" => {
|
||||
mod zkvm;
|
||||
pub use zkvm::*;
|
||||
}
|
||||
_ => {
|
||||
mod unsupported;
|
||||
pub use unsupported::*;
|
||||
}
|
||||
}
|
||||
1
library/std/src/sys/env/mod.rs
vendored
Symbolic link
1
library/std/src/sys/env/mod.rs
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/env/mod.rs
|
||||
33
library/std/src/sys/env/unsupported.rs
vendored
33
library/std/src/sys/env/unsupported.rs
vendored
@@ -1,33 +0,0 @@
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::{fmt, io};
|
||||
|
||||
pub struct Env(!);
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Env {
|
||||
type Item = (OsString, OsString);
|
||||
fn next(&mut self) -> Option<(OsString, OsString)> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn env() -> Env {
|
||||
panic!("not supported on this platform")
|
||||
}
|
||||
|
||||
pub fn getenv(_: &OsStr) -> Option<OsString> {
|
||||
None
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
|
||||
Err(io::const_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform"))
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> {
|
||||
Err(io::const_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform"))
|
||||
}
|
||||
1
library/std/src/sys/env/unsupported.rs
vendored
Symbolic link
1
library/std/src/sys/env/unsupported.rs
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/env/unsupported.rs
|
||||
@@ -1,426 +0,0 @@
|
||||
//! Constants associated with each target.
|
||||
|
||||
// Replaces the #[else] gate with #[cfg(not(any(…)))] of all the other gates.
|
||||
// This ensures that they must be mutually exclusive and do not have precedence
|
||||
// like cfg_select!.
|
||||
macro cfg_unordered(
|
||||
$(#[cfg($cfg:meta)] $os:item)*
|
||||
#[else] $fallback:item
|
||||
) {
|
||||
$(#[cfg($cfg)] $os)*
|
||||
#[cfg(not(any($($cfg),*)))] $fallback
|
||||
}
|
||||
|
||||
// Keep entries sorted alphabetically and mutually exclusive.
|
||||
|
||||
cfg_unordered! {
|
||||
|
||||
#[cfg(target_os = "aix")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "aix";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".a";
|
||||
pub const DLL_EXTENSION: &str = "a";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "android";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "cygwin")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "cygwin";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = ".dll";
|
||||
pub const DLL_EXTENSION: &str = "dll";
|
||||
pub const EXE_SUFFIX: &str = ".exe";
|
||||
pub const EXE_EXTENSION: &str = "exe";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "dragonfly";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "emscripten")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "emscripten";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = ".js";
|
||||
pub const EXE_EXTENSION: &str = "js";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "espidf")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "espidf";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "freebsd";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "fuchsia")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "fuchsia";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "haiku")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "haiku";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "hermit")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "hermit";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = "";
|
||||
pub const DLL_EXTENSION: &str = "";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "horizon")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "horizon";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = ".elf";
|
||||
pub const EXE_EXTENSION: &str = "elf";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "hurd")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "hurd";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "illumos")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "illumos";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "ios")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "ios";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".dylib";
|
||||
pub const DLL_EXTENSION: &str = "dylib";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "l4re")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "l4re";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "linux";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "macos";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".dylib";
|
||||
pub const DLL_EXTENSION: &str = "dylib";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "netbsd")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "netbsd";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "nto")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "nto";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "nuttx")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "nuttx";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "openbsd")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "openbsd";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "redox";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "rtems")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "rtems";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = ".sgxs";
|
||||
pub const DLL_EXTENSION: &str = "sgxs";
|
||||
pub const EXE_SUFFIX: &str = ".sgxs";
|
||||
pub const EXE_EXTENSION: &str = "sgxs";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "solaris")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "solaris";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "solid_asp3")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "itron";
|
||||
pub const OS: &str = "solid";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "tvos")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "tvos";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".dylib";
|
||||
pub const DLL_EXTENSION: &str = "dylib";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "uefi")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "uefi";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = "";
|
||||
pub const DLL_EXTENSION: &str = "";
|
||||
pub const EXE_SUFFIX: &str = ".efi";
|
||||
pub const EXE_EXTENSION: &str = "efi";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "vexos")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "vexos";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = "";
|
||||
pub const DLL_EXTENSION: &str = "";
|
||||
pub const EXE_SUFFIX: &str = ".bin";
|
||||
pub const EXE_EXTENSION: &str = "bin";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "visionos")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "visionos";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".dylib";
|
||||
pub const DLL_EXTENSION: &str = "dylib";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "vita")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "vita";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = ".elf";
|
||||
pub const EXE_EXTENSION: &str = "elf";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "vxworks")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "vxworks";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(all(target_family = "wasm", not(any(target_os = "emscripten", target_os = "linux"))))]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = ".wasm";
|
||||
pub const DLL_EXTENSION: &str = "wasm";
|
||||
pub const EXE_SUFFIX: &str = ".wasm";
|
||||
pub const EXE_EXTENSION: &str = "wasm";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "watchos")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "watchos";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".dylib";
|
||||
pub const DLL_EXTENSION: &str = "dylib";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "windows";
|
||||
pub const OS: &str = "windows";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = ".dll";
|
||||
pub const DLL_EXTENSION: &str = "dll";
|
||||
pub const EXE_SUFFIX: &str = ".exe";
|
||||
pub const EXE_EXTENSION: &str = "exe";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "zkvm")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = ".elf";
|
||||
pub const DLL_EXTENSION: &str = "elf";
|
||||
pub const EXE_SUFFIX: &str = ".elf";
|
||||
pub const EXE_EXTENSION: &str = "elf";
|
||||
}
|
||||
|
||||
// The fallback when none of the other gates match.
|
||||
#[else]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = "";
|
||||
pub const DLL_EXTENSION: &str = "";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
}
|
||||
1
library/std/src/sys/env_consts.rs
Symbolic link
1
library/std/src/sys/env_consts.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/env_consts.rs
|
||||
@@ -1,143 +0,0 @@
|
||||
cfg_select! {
|
||||
target_os = "linux" => {
|
||||
/// Mitigation for <https://github.com/rust-lang/rust/issues/126600>
|
||||
///
|
||||
/// On glibc, `libc::exit` has been observed to not always be thread-safe.
|
||||
/// It is currently unclear whether that is a glibc bug or allowed by the standard.
|
||||
/// To mitigate this problem, we ensure that only one
|
||||
/// Rust thread calls `libc::exit` (or returns from `main`) by calling this function before
|
||||
/// calling `libc::exit` (or returning from `main`).
|
||||
///
|
||||
/// Technically, this is not enough to ensure soundness, since other code directly calling
|
||||
/// `libc::exit` will still race with this.
|
||||
///
|
||||
/// *This function does not itself call `libc::exit`.* This is so it can also be used
|
||||
/// to guard returning from `main`.
|
||||
///
|
||||
/// This function will return only the first time it is called in a process.
|
||||
///
|
||||
/// * If it is called again on the same thread as the first call, it will abort.
|
||||
/// * If it is called again on a different thread, it will wait in a loop
|
||||
/// (waiting for the process to exit).
|
||||
pub fn unique_thread_exit() {
|
||||
use crate::ffi::c_int;
|
||||
use crate::ptr;
|
||||
use crate::sync::atomic::AtomicPtr;
|
||||
use crate::sync::atomic::Ordering::{Acquire, Relaxed};
|
||||
|
||||
static EXITING_THREAD_ID: AtomicPtr<c_int> = AtomicPtr::new(ptr::null_mut());
|
||||
|
||||
// We use the address of `errno` as a cheap and safe way to identify
|
||||
// threads. As the C standard mandates that `errno` must have thread
|
||||
// storage duration, we can rely on its address not changing over the
|
||||
// lifetime of the thread. Additionally, accesses to `errno` are
|
||||
// async-signal-safe, so this function is available in all imaginable
|
||||
// circumstances.
|
||||
let this_thread_id = crate::sys::io::errno_location();
|
||||
match EXITING_THREAD_ID.compare_exchange(ptr::null_mut(), this_thread_id, Acquire, Relaxed) {
|
||||
Ok(_) => {
|
||||
// This is the first thread to call `unique_thread_exit`,
|
||||
// and this is the first time it is called. Continue exiting.
|
||||
}
|
||||
Err(exiting_thread_id) if exiting_thread_id == this_thread_id => {
|
||||
// This is the first thread to call `unique_thread_exit`,
|
||||
// but this is the second time it is called.
|
||||
// Abort the process.
|
||||
core::panicking::panic_nounwind("std::process::exit called re-entrantly")
|
||||
}
|
||||
Err(_) => {
|
||||
// This is not the first thread to call `unique_thread_exit`.
|
||||
// Pause until the process exits.
|
||||
loop {
|
||||
// Safety: libc::pause is safe to call.
|
||||
unsafe { libc::pause(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
/// Mitigation for <https://github.com/rust-lang/rust/issues/126600>
|
||||
///
|
||||
/// Mitigation is ***NOT*** implemented on this platform, either because this platform
|
||||
/// is not affected, or because mitigation is not yet implemented for this platform.
|
||||
#[cfg_attr(any(test, doctest), expect(dead_code))]
|
||||
pub fn unique_thread_exit() {
|
||||
// Mitigation not required on platforms where `exit` is thread-safe.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exit(code: i32) -> ! {
|
||||
cfg_select! {
|
||||
target_os = "hermit" => {
|
||||
unsafe { hermit_abi::exit(code) }
|
||||
}
|
||||
target_os = "linux" => {
|
||||
unsafe {
|
||||
unique_thread_exit();
|
||||
libc::exit(code)
|
||||
}
|
||||
}
|
||||
target_os = "motor" => {
|
||||
moto_rt::process::exit(code)
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
crate::sys::pal::abi::exit_with_code(code as _)
|
||||
}
|
||||
target_os = "solid_asp3" => {
|
||||
rtabort!("exit({}) called", code)
|
||||
}
|
||||
target_os = "teeos" => {
|
||||
let _ = code;
|
||||
panic!("TA should not call `exit`")
|
||||
}
|
||||
target_os = "uefi" => {
|
||||
use r_efi::base::Status;
|
||||
|
||||
use crate::os::uefi::env;
|
||||
|
||||
if let (Some(boot_services), Some(handle)) =
|
||||
(env::boot_services(), env::try_image_handle())
|
||||
{
|
||||
let boot_services = boot_services.cast::<r_efi::efi::BootServices>();
|
||||
let _ = unsafe {
|
||||
((*boot_services.as_ptr()).exit)(
|
||||
handle.as_ptr(),
|
||||
Status::from_usize(code as usize),
|
||||
0,
|
||||
crate::ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
}
|
||||
crate::intrinsics::abort()
|
||||
}
|
||||
any(
|
||||
target_family = "unix",
|
||||
target_os = "wasi",
|
||||
) => {
|
||||
unsafe { libc::exit(code as crate::ffi::c_int) }
|
||||
}
|
||||
target_os = "vexos" => {
|
||||
let _ = code;
|
||||
|
||||
unsafe {
|
||||
vex_sdk::vexSystemExitRequest();
|
||||
|
||||
loop {
|
||||
vex_sdk::vexTasksRun();
|
||||
}
|
||||
}
|
||||
}
|
||||
target_os = "windows" => {
|
||||
unsafe { crate::sys::pal::c::ExitProcess(code as u32) }
|
||||
}
|
||||
target_os = "xous" => {
|
||||
crate::os::xous::ffi::exit(code as u32)
|
||||
}
|
||||
_ => {
|
||||
let _ = code;
|
||||
crate::intrinsics::abort()
|
||||
}
|
||||
}
|
||||
}
|
||||
1
library/std/src/sys/exit.rs
Symbolic link
1
library/std/src/sys/exit.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/exit.rs
|
||||
@@ -1,23 +0,0 @@
|
||||
//! Platform-dependent file descriptor abstraction.
|
||||
|
||||
#![forbid(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
cfg_select! {
|
||||
any(target_family = "unix", target_os = "wasi") => {
|
||||
mod unix;
|
||||
pub use unix::*;
|
||||
}
|
||||
target_os = "hermit" => {
|
||||
mod hermit;
|
||||
pub use hermit::*;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
pub use motor::*;
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
mod sgx;
|
||||
pub use sgx::*;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
1
library/std/src/sys/fd/mod.rs
Symbolic link
1
library/std/src/sys/fd/mod.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/fd/mod.rs
|
||||
@@ -1,81 +0,0 @@
|
||||
#![allow(dead_code)] // not used on all platforms
|
||||
|
||||
use crate::io::{self, Error, ErrorKind};
|
||||
use crate::path::{Path, PathBuf};
|
||||
use crate::sys::fs::{File, OpenOptions};
|
||||
use crate::sys::helpers::ignore_notfound;
|
||||
use crate::{fmt, fs};
|
||||
|
||||
pub(crate) const NOT_FILE_ERROR: Error = io::const_error!(
|
||||
ErrorKind::InvalidInput,
|
||||
"the source path is neither a regular file nor a symlink to a regular file",
|
||||
);
|
||||
|
||||
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
||||
let mut reader = fs::File::open(from)?;
|
||||
let metadata = reader.metadata()?;
|
||||
|
||||
if !metadata.is_file() {
|
||||
return Err(NOT_FILE_ERROR);
|
||||
}
|
||||
|
||||
let mut writer = fs::File::create(to)?;
|
||||
let perm = metadata.permissions();
|
||||
|
||||
let ret = io::copy(&mut reader, &mut writer)?;
|
||||
writer.set_permissions(perm)?;
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
pub fn remove_dir_all(path: &Path) -> io::Result<()> {
|
||||
let filetype = fs::symlink_metadata(path)?.file_type();
|
||||
if filetype.is_symlink() { fs::remove_file(path) } else { remove_dir_all_recursive(path) }
|
||||
}
|
||||
|
||||
fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
|
||||
for child in fs::read_dir(path)? {
|
||||
let result: io::Result<()> = try {
|
||||
let child = child?;
|
||||
if child.file_type()?.is_dir() {
|
||||
remove_dir_all_recursive(&child.path())?;
|
||||
} else {
|
||||
fs::remove_file(&child.path())?;
|
||||
}
|
||||
};
|
||||
// ignore internal NotFound errors to prevent race conditions
|
||||
if let Err(err) = &result
|
||||
&& err.kind() != io::ErrorKind::NotFound
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
ignore_notfound(fs::remove_dir(path))
|
||||
}
|
||||
|
||||
pub fn exists(path: &Path) -> io::Result<bool> {
|
||||
match fs::metadata(path) {
|
||||
Ok(_) => Ok(true),
|
||||
Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false),
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Dir {
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
impl Dir {
|
||||
pub fn open(path: &Path, _opts: &OpenOptions) -> io::Result<Self> {
|
||||
path.canonicalize().map(|path| Self { path })
|
||||
}
|
||||
|
||||
pub fn open_file(&self, path: &Path, opts: &OpenOptions) -> io::Result<File> {
|
||||
File::open(&self.path.join(path), &opts)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Dir {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Dir").field("path", &self.path).finish()
|
||||
}
|
||||
}
|
||||
1
library/std/src/sys/fs/common.rs
Symbolic link
1
library/std/src/sys/fs/common.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/fs/common.rs
|
||||
@@ -1,173 +0,0 @@
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
use crate::io;
|
||||
use crate::path::{Path, PathBuf};
|
||||
|
||||
pub mod common;
|
||||
|
||||
cfg_select! {
|
||||
any(target_family = "unix", target_os = "wasi") => {
|
||||
mod unix;
|
||||
use unix as imp;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub use unix::{chown, fchown, lchown, mkfifo};
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
|
||||
pub use unix::chroot;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) use unix::debug_assert_fd_is_open;
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub(super) use unix::CachedFileMetadata;
|
||||
use crate::sys::helpers::run_path_with_cstr as with_native_path;
|
||||
}
|
||||
target_os = "windows" => {
|
||||
mod windows;
|
||||
use windows as imp;
|
||||
pub use windows::{symlink_inner, junction_point};
|
||||
use crate::sys::path::with_native_path;
|
||||
}
|
||||
target_os = "hermit" => {
|
||||
mod hermit;
|
||||
use hermit as imp;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
use motor as imp;
|
||||
}
|
||||
target_os = "solid_asp3" => {
|
||||
mod solid;
|
||||
use solid as imp;
|
||||
}
|
||||
target_os = "uefi" => {
|
||||
mod uefi;
|
||||
use uefi as imp;
|
||||
}
|
||||
target_os = "vexos" => {
|
||||
mod vexos;
|
||||
use vexos as imp;
|
||||
}
|
||||
_ => {
|
||||
mod unsupported;
|
||||
use unsupported as imp;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Replace this with platform-specific path conversion functions.
|
||||
#[cfg(not(any(target_family = "unix", target_os = "windows", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub fn with_native_path<T>(path: &Path, f: &dyn Fn(&Path) -> io::Result<T>) -> io::Result<T> {
|
||||
f(path)
|
||||
}
|
||||
|
||||
pub use imp::{
|
||||
Dir, DirBuilder, DirEntry, File, FileAttr, FilePermissions, FileTimes, FileType, OpenOptions,
|
||||
ReadDir,
|
||||
};
|
||||
|
||||
pub fn read_dir(path: &Path) -> io::Result<ReadDir> {
|
||||
// FIXME: use with_native_path on all platforms
|
||||
imp::readdir(path)
|
||||
}
|
||||
|
||||
pub fn remove_file(path: &Path) -> io::Result<()> {
|
||||
with_native_path(path, &imp::unlink)
|
||||
}
|
||||
|
||||
pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
|
||||
with_native_path(old, &|old| with_native_path(new, &|new| imp::rename(old, new)))
|
||||
}
|
||||
|
||||
pub fn remove_dir(path: &Path) -> io::Result<()> {
|
||||
with_native_path(path, &imp::rmdir)
|
||||
}
|
||||
|
||||
pub fn remove_dir_all(path: &Path) -> io::Result<()> {
|
||||
// FIXME: use with_native_path on all platforms
|
||||
#[cfg(not(windows))]
|
||||
return imp::remove_dir_all(path);
|
||||
#[cfg(windows)]
|
||||
with_native_path(path, &imp::remove_dir_all)
|
||||
}
|
||||
|
||||
pub fn read_link(path: &Path) -> io::Result<PathBuf> {
|
||||
with_native_path(path, &imp::readlink)
|
||||
}
|
||||
|
||||
pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
|
||||
// FIXME: use with_native_path on all platforms
|
||||
#[cfg(windows)]
|
||||
return imp::symlink(original, link);
|
||||
#[cfg(not(windows))]
|
||||
with_native_path(original, &|original| {
|
||||
with_native_path(link, &|link| imp::symlink(original, link))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn hard_link(original: &Path, link: &Path) -> io::Result<()> {
|
||||
with_native_path(original, &|original| {
|
||||
with_native_path(link, &|link| imp::link(original, link))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn metadata(path: &Path) -> io::Result<FileAttr> {
|
||||
with_native_path(path, &imp::stat)
|
||||
}
|
||||
|
||||
pub fn symlink_metadata(path: &Path) -> io::Result<FileAttr> {
|
||||
with_native_path(path, &imp::lstat)
|
||||
}
|
||||
|
||||
pub fn set_permissions(path: &Path, perm: FilePermissions) -> io::Result<()> {
|
||||
with_native_path(path, &|path| imp::set_perm(path, perm.clone()))
|
||||
}
|
||||
|
||||
#[cfg(all(unix, not(target_os = "vxworks")))]
|
||||
pub fn set_permissions_nofollow(path: &Path, perm: crate::fs::Permissions) -> io::Result<()> {
|
||||
use crate::fs::OpenOptions;
|
||||
|
||||
let mut options = OpenOptions::new();
|
||||
|
||||
// ESP-IDF and Horizon do not support O_NOFOLLOW, so we skip setting it.
|
||||
// Their filesystems do not have symbolic links, so no special handling is required.
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "horizon")))]
|
||||
{
|
||||
use crate::os::unix::fs::OpenOptionsExt;
|
||||
options.custom_flags(libc::O_NOFOLLOW);
|
||||
}
|
||||
|
||||
options.open(path)?.set_permissions(perm)
|
||||
}
|
||||
|
||||
#[cfg(any(not(unix), target_os = "vxworks"))]
|
||||
pub fn set_permissions_nofollow(_path: &Path, _perm: crate::fs::Permissions) -> io::Result<()> {
|
||||
crate::unimplemented!(
|
||||
"`set_permissions_nofollow` is currently only implemented on Unix platforms"
|
||||
)
|
||||
}
|
||||
|
||||
pub fn canonicalize(path: &Path) -> io::Result<PathBuf> {
|
||||
with_native_path(path, &imp::canonicalize)
|
||||
}
|
||||
|
||||
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
||||
// FIXME: use with_native_path on all platforms
|
||||
#[cfg(not(windows))]
|
||||
return imp::copy(from, to);
|
||||
#[cfg(windows)]
|
||||
with_native_path(from, &|from| with_native_path(to, &|to| imp::copy(from, to)))
|
||||
}
|
||||
|
||||
pub fn exists(path: &Path) -> io::Result<bool> {
|
||||
// FIXME: use with_native_path on all platforms
|
||||
#[cfg(not(windows))]
|
||||
return imp::exists(path);
|
||||
#[cfg(windows)]
|
||||
with_native_path(path, &imp::exists)
|
||||
}
|
||||
|
||||
pub fn set_times(path: &Path, times: FileTimes) -> io::Result<()> {
|
||||
with_native_path(path, &|path| imp::set_times(path, times.clone()))
|
||||
}
|
||||
|
||||
pub fn set_times_nofollow(path: &Path, times: FileTimes) -> io::Result<()> {
|
||||
with_native_path(path, &|path| imp::set_times_nofollow(path, times.clone()))
|
||||
}
|
||||
1
library/std/src/sys/fs/mod.rs
Symbolic link
1
library/std/src/sys/fs/mod.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/fs/mod.rs
|
||||
@@ -1,362 +0,0 @@
|
||||
use crate::ffi::OsString;
|
||||
use crate::fmt;
|
||||
use crate::fs::TryLockError;
|
||||
use crate::hash::{Hash, Hasher};
|
||||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
|
||||
use crate::path::{Path, PathBuf};
|
||||
pub use crate::sys::fs::common::Dir;
|
||||
use crate::sys::time::SystemTime;
|
||||
use crate::sys::unsupported;
|
||||
|
||||
pub struct File(!);
|
||||
|
||||
pub struct FileAttr(!);
|
||||
|
||||
pub struct ReadDir(!);
|
||||
|
||||
pub struct DirEntry(!);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OpenOptions {}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
pub struct FileTimes {}
|
||||
|
||||
pub struct FilePermissions(!);
|
||||
|
||||
pub struct FileType(!);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DirBuilder {}
|
||||
|
||||
impl FileAttr {
|
||||
pub fn size(&self) -> u64 {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn perm(&self) -> FilePermissions {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn file_type(&self) -> FileType {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn modified(&self) -> io::Result<SystemTime> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn accessed(&self) -> io::Result<SystemTime> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn created(&self) -> io::Result<SystemTime> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FileAttr {
|
||||
fn clone(&self) -> FileAttr {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FilePermissions {
|
||||
pub fn readonly(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_readonly(&mut self, _readonly: bool) {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FilePermissions {
|
||||
fn clone(&self) -> FilePermissions {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for FilePermissions {
|
||||
fn eq(&self, _other: &FilePermissions) -> bool {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for FilePermissions {}
|
||||
|
||||
impl fmt::Debug for FilePermissions {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FileTimes {
|
||||
pub fn set_accessed(&mut self, _t: SystemTime) {}
|
||||
pub fn set_modified(&mut self, _t: SystemTime) {}
|
||||
}
|
||||
|
||||
impl FileType {
|
||||
pub fn is_dir(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn is_file(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn is_symlink(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FileType {
|
||||
fn clone(&self) -> FileType {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Copy for FileType {}
|
||||
|
||||
impl PartialEq for FileType {
|
||||
fn eq(&self, _other: &FileType) -> bool {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for FileType {}
|
||||
|
||||
impl Hash for FileType {
|
||||
fn hash<H: Hasher>(&self, _h: &mut H) {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for FileType {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ReadDir {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for ReadDir {
|
||||
type Item = io::Result<DirEntry>;
|
||||
|
||||
fn next(&mut self) -> Option<io::Result<DirEntry>> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DirEntry {
|
||||
pub fn path(&self) -> PathBuf {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn file_name(&self) -> OsString {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> io::Result<FileAttr> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn file_type(&self) -> io::Result<FileType> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl OpenOptions {
|
||||
pub fn new() -> OpenOptions {
|
||||
OpenOptions {}
|
||||
}
|
||||
|
||||
pub fn read(&mut self, _read: bool) {}
|
||||
pub fn write(&mut self, _write: bool) {}
|
||||
pub fn append(&mut self, _append: bool) {}
|
||||
pub fn truncate(&mut self, _truncate: bool) {}
|
||||
pub fn create(&mut self, _create: bool) {}
|
||||
pub fn create_new(&mut self, _create_new: bool) {}
|
||||
}
|
||||
|
||||
impl File {
|
||||
pub fn open(_path: &Path, _opts: &OpenOptions) -> io::Result<File> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn file_attr(&self) -> io::Result<FileAttr> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn fsync(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn datasync(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn lock(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn lock_shared(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn try_lock(&self) -> Result<(), TryLockError> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn try_lock_shared(&self) -> Result<(), TryLockError> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn unlock(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn truncate(&self, _size: u64) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn is_read_vectored(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn read_buf(&self, _cursor: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn size(&self) -> Option<io::Result<u64>> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn tell(&self) -> io::Result<u64> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<File> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_times(&self, _times: FileTimes) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DirBuilder {
|
||||
pub fn new() -> DirBuilder {
|
||||
DirBuilder {}
|
||||
}
|
||||
|
||||
pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for File {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn unlink(_p: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
|
||||
match perm.0 {}
|
||||
}
|
||||
|
||||
pub fn set_times(_p: &Path, _times: FileTimes) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn set_times_nofollow(_p: &Path, _times: FileTimes) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn rmdir(_p: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn exists(_path: &Path) -> io::Result<bool> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn symlink(_original: &Path, _link: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn stat(_p: &Path) -> io::Result<FileAttr> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> {
|
||||
unsupported()
|
||||
}
|
||||
1
library/std/src/sys/fs/unsupported.rs
Symbolic link
1
library/std/src/sys/fs/unsupported.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/fs/unsupported.rs
|
||||
@@ -1,39 +0,0 @@
|
||||
//! Small helper functions used inside `sys`.
|
||||
//!
|
||||
//! If any of these have uses outside of `sys`, please move them to a different
|
||||
//! module.
|
||||
|
||||
#[cfg_attr(not(target_os = "linux"), allow(unused))] // Not used on all platforms.
|
||||
mod small_c_string;
|
||||
#[cfg_attr(not(target_os = "windows"), allow(unused))] // Not used on all platforms.
|
||||
mod wstr;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[cfg_attr(not(target_os = "linux"), allow(unused))] // Not used on all platforms.
|
||||
pub use small_c_string::{run_path_with_cstr, run_with_cstr};
|
||||
#[cfg_attr(not(target_os = "windows"), allow(unused))] // Not used on all platforms.
|
||||
pub use wstr::WStrUnits;
|
||||
|
||||
/// Computes `(value*numerator)/denom` without overflow, as long as both
|
||||
/// `numerator*denom` and the overall result fit into `u64` (which is the case
|
||||
/// for our time conversions).
|
||||
#[cfg_attr(not(target_os = "windows"), allow(unused))] // Not used on all platforms.
|
||||
pub fn mul_div_u64(value: u64, numerator: u64, denom: u64) -> u64 {
|
||||
let q = value / denom;
|
||||
let r = value % denom;
|
||||
// Decompose value as (value/denom*denom + value%denom),
|
||||
// substitute into (value*numerator)/denom and simplify.
|
||||
// r < denom, so (denom*numerator) is the upper bound of (r*numerator)
|
||||
q * numerator + r * numerator / denom
|
||||
}
|
||||
|
||||
#[cfg_attr(not(target_os = "linux"), allow(unused))] // Not used on all platforms.
|
||||
pub fn ignore_notfound<T>(result: crate::io::Result<T>) -> crate::io::Result<()> {
|
||||
match result {
|
||||
Err(err) if err.kind() == crate::io::ErrorKind::NotFound => Ok(()),
|
||||
Ok(_) => Ok(()),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
1
library/std/src/sys/helpers/mod.rs
Symbolic link
1
library/std/src/sys/helpers/mod.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/helpers/mod.rs
|
||||
@@ -1,60 +0,0 @@
|
||||
use crate::ffi::{CStr, CString};
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::path::Path;
|
||||
use crate::{io, ptr, slice};
|
||||
|
||||
// Make sure to stay under 4096 so the compiler doesn't insert a probe frame:
|
||||
// https://docs.rs/compiler_builtins/latest/compiler_builtins/probestack/index.html
|
||||
#[cfg(not(target_os = "espidf"))]
|
||||
const MAX_STACK_ALLOCATION: usize = 384;
|
||||
#[cfg(target_os = "espidf")]
|
||||
const MAX_STACK_ALLOCATION: usize = 32;
|
||||
|
||||
const NUL_ERR: io::Error =
|
||||
io::const_error!(io::ErrorKind::InvalidInput, "file name contained an unexpected NUL byte");
|
||||
|
||||
#[inline]
|
||||
pub fn run_path_with_cstr<T>(path: &Path, f: &dyn Fn(&CStr) -> io::Result<T>) -> io::Result<T> {
|
||||
run_with_cstr(path.as_os_str().as_encoded_bytes(), f)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn run_with_cstr<T>(bytes: &[u8], f: &dyn Fn(&CStr) -> io::Result<T>) -> io::Result<T> {
|
||||
// Dispatch and dyn erase the closure type to prevent mono bloat.
|
||||
// See https://github.com/rust-lang/rust/pull/121101.
|
||||
if bytes.len() >= MAX_STACK_ALLOCATION {
|
||||
run_with_cstr_allocating(bytes, f)
|
||||
} else {
|
||||
unsafe { run_with_cstr_stack(bytes, f) }
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// `bytes` must have a length less than `MAX_STACK_ALLOCATION`.
|
||||
unsafe fn run_with_cstr_stack<T>(
|
||||
bytes: &[u8],
|
||||
f: &dyn Fn(&CStr) -> io::Result<T>,
|
||||
) -> io::Result<T> {
|
||||
let mut buf = MaybeUninit::<[u8; MAX_STACK_ALLOCATION]>::uninit();
|
||||
let buf_ptr = buf.as_mut_ptr() as *mut u8;
|
||||
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(bytes.as_ptr(), buf_ptr, bytes.len());
|
||||
buf_ptr.add(bytes.len()).write(0);
|
||||
}
|
||||
|
||||
match CStr::from_bytes_with_nul(unsafe { slice::from_raw_parts(buf_ptr, bytes.len() + 1) }) {
|
||||
Ok(s) => f(s),
|
||||
Err(_) => Err(NUL_ERR),
|
||||
}
|
||||
}
|
||||
|
||||
#[cold]
|
||||
#[inline(never)]
|
||||
fn run_with_cstr_allocating<T>(bytes: &[u8], f: &dyn Fn(&CStr) -> io::Result<T>) -> io::Result<T> {
|
||||
match CString::new(bytes) {
|
||||
Ok(s) => f(&s),
|
||||
Err(_) => Err(NUL_ERR),
|
||||
}
|
||||
}
|
||||
1
library/std/src/sys/helpers/small_c_string.rs
Symbolic link
1
library/std/src/sys/helpers/small_c_string.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/helpers/small_c_string.rs
|
||||
@@ -1,73 +0,0 @@
|
||||
use core::iter::repeat;
|
||||
|
||||
use super::mul_div_u64;
|
||||
use super::small_c_string::run_path_with_cstr;
|
||||
use crate::ffi::CString;
|
||||
use crate::hint::black_box;
|
||||
use crate::path::Path;
|
||||
|
||||
#[test]
|
||||
fn stack_allocation_works() {
|
||||
let path = Path::new("abc");
|
||||
let result = run_path_with_cstr(path, &|p| {
|
||||
assert_eq!(p, &*CString::new(path.as_os_str().as_encoded_bytes()).unwrap());
|
||||
Ok(42)
|
||||
});
|
||||
assert_eq!(result.unwrap(), 42);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stack_allocation_fails() {
|
||||
let path = Path::new("ab\0");
|
||||
assert!(run_path_with_cstr::<()>(path, &|_| unreachable!()).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn heap_allocation_works() {
|
||||
let path = repeat("a").take(384).collect::<String>();
|
||||
let path = Path::new(&path);
|
||||
let result = run_path_with_cstr(path, &|p| {
|
||||
assert_eq!(p, &*CString::new(path.as_os_str().as_encoded_bytes()).unwrap());
|
||||
Ok(42)
|
||||
});
|
||||
assert_eq!(result.unwrap(), 42);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn heap_allocation_fails() {
|
||||
let mut path = repeat("a").take(384).collect::<String>();
|
||||
path.push('\0');
|
||||
let path = Path::new(&path);
|
||||
assert!(run_path_with_cstr::<()>(path, &|_| unreachable!()).is_err());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_stack_path_alloc(b: &mut test::Bencher) {
|
||||
let path = repeat("a").take(383).collect::<String>();
|
||||
let p = Path::new(&path);
|
||||
b.iter(|| {
|
||||
run_path_with_cstr(p, &|cstr| {
|
||||
black_box(cstr);
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_heap_path_alloc(b: &mut test::Bencher) {
|
||||
let path = repeat("a").take(384).collect::<String>();
|
||||
let p = Path::new(&path);
|
||||
b.iter(|| {
|
||||
run_path_with_cstr(p, &|cstr| {
|
||||
black_box(cstr);
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_muldiv() {
|
||||
assert_eq!(mul_div_u64(1_000_000_000_001, 1_000_000_000, 1_000_000), 1_000_000_000_001_000);
|
||||
}
|
||||
1
library/std/src/sys/helpers/tests.rs
Symbolic link
1
library/std/src/sys/helpers/tests.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/helpers/tests.rs
|
||||
@@ -1,59 +0,0 @@
|
||||
//! This module contains constructs to work with 16-bit characters (UCS-2 or UTF-16)
|
||||
|
||||
use crate::marker::PhantomData;
|
||||
use crate::num::NonZero;
|
||||
use crate::ptr::NonNull;
|
||||
|
||||
/// A safe iterator over a LPWSTR
|
||||
/// (aka a pointer to a series of UTF-16 code units terminated by a NULL).
|
||||
pub struct WStrUnits<'a> {
|
||||
// The pointer must never be null...
|
||||
lpwstr: NonNull<u16>,
|
||||
// ...and the memory it points to must be valid for this lifetime.
|
||||
lifetime: PhantomData<&'a [u16]>,
|
||||
}
|
||||
|
||||
impl WStrUnits<'_> {
|
||||
/// Creates the iterator. Returns `None` if `lpwstr` is null.
|
||||
///
|
||||
/// SAFETY: `lpwstr` must point to a null-terminated wide string that lives
|
||||
/// at least as long as the lifetime of this struct.
|
||||
pub unsafe fn new(lpwstr: *const u16) -> Option<Self> {
|
||||
Some(Self { lpwstr: NonNull::new(lpwstr as _)?, lifetime: PhantomData })
|
||||
}
|
||||
|
||||
pub fn peek(&self) -> Option<NonZero<u16>> {
|
||||
// SAFETY: It's always safe to read the current item because we don't
|
||||
// ever move out of the array's bounds.
|
||||
unsafe { NonZero::new(*self.lpwstr.as_ptr()) }
|
||||
}
|
||||
|
||||
/// Advance the iterator while `predicate` returns true.
|
||||
/// Returns the number of items it advanced by.
|
||||
pub fn advance_while<P: FnMut(NonZero<u16>) -> bool>(&mut self, mut predicate: P) -> usize {
|
||||
let mut counter = 0;
|
||||
while let Some(w) = self.peek() {
|
||||
if !predicate(w) {
|
||||
break;
|
||||
}
|
||||
counter += 1;
|
||||
self.next();
|
||||
}
|
||||
counter
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for WStrUnits<'_> {
|
||||
// This can never return zero as that marks the end of the string.
|
||||
type Item = NonZero<u16>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
// SAFETY: If NULL is reached we immediately return.
|
||||
// Therefore it's safe to advance the pointer after that.
|
||||
unsafe {
|
||||
let next = self.peek()?;
|
||||
self.lpwstr = NonNull::new_unchecked(self.lpwstr.as_ptr().add(1));
|
||||
Some(next)
|
||||
}
|
||||
}
|
||||
}
|
||||
1
library/std/src/sys/helpers/wstr.rs
Symbolic link
1
library/std/src/sys/helpers/wstr.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/helpers/wstr.rs
|
||||
@@ -1,15 +0,0 @@
|
||||
pub fn errno() -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
pub fn is_interrupted(_code: i32) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind {
|
||||
crate::io::ErrorKind::Uncategorized
|
||||
}
|
||||
|
||||
pub fn error_string(_errno: i32) -> String {
|
||||
"operation successful".to_string()
|
||||
}
|
||||
1
library/std/src/sys/io/error/generic.rs
Symbolic link
1
library/std/src/sys/io/error/generic.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/io/error/generic.rs
|
||||
@@ -1,52 +0,0 @@
|
||||
use crate::mem;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct IoSlice<'a>(&'a [u8]);
|
||||
|
||||
impl<'a> IoSlice<'a> {
|
||||
#[inline]
|
||||
pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
|
||||
IoSlice(buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn advance(&mut self, n: usize) {
|
||||
self.0 = &self.0[n..]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn as_slice(&self) -> &'a [u8] {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IoSliceMut<'a>(&'a mut [u8]);
|
||||
|
||||
impl<'a> IoSliceMut<'a> {
|
||||
#[inline]
|
||||
pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
|
||||
IoSliceMut(buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn advance(&mut self, n: usize) {
|
||||
let slice = mem::take(&mut self.0);
|
||||
let (_, remaining) = slice.split_at_mut(n);
|
||||
self.0 = remaining;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn into_slice(self) -> &'a mut [u8] {
|
||||
self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_mut_slice(&mut self) -> &mut [u8] {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
1
library/std/src/sys/io/io_slice/unsupported.rs
Symbolic link
1
library/std/src/sys/io/io_slice/unsupported.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/io/io_slice/unsupported.rs
|
||||
@@ -1,3 +0,0 @@
|
||||
pub fn is_terminal<T>(_: &T) -> bool {
|
||||
false
|
||||
}
|
||||
1
library/std/src/sys/io/is_terminal/unsupported.rs
Symbolic link
1
library/std/src/sys/io/is_terminal/unsupported.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/io/is_terminal/unsupported.rs
|
||||
@@ -1,23 +0,0 @@
|
||||
pub enum CopyState {
|
||||
#[cfg_attr(not(any(target_os = "linux", target_os = "android")), expect(dead_code))]
|
||||
Ended(u64),
|
||||
Fallback(u64),
|
||||
}
|
||||
|
||||
cfg_select! {
|
||||
any(target_os = "linux", target_os = "android") => {
|
||||
mod linux;
|
||||
pub use linux::kernel_copy;
|
||||
}
|
||||
_ => {
|
||||
use crate::io::{Result, Read, Write};
|
||||
|
||||
pub fn kernel_copy<R: ?Sized, W: ?Sized>(_reader: &mut R, _writer: &mut W) -> Result<CopyState>
|
||||
where
|
||||
R: Read,
|
||||
W: Write,
|
||||
{
|
||||
Ok(CopyState::Fallback(0))
|
||||
}
|
||||
}
|
||||
}
|
||||
1
library/std/src/sys/io/kernel_copy/mod.rs
Symbolic link
1
library/std/src/sys/io/kernel_copy/mod.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/io/kernel_copy/mod.rs
|
||||
@@ -1,72 +0,0 @@
|
||||
#![forbid(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
mod error;
|
||||
|
||||
mod io_slice {
|
||||
cfg_select! {
|
||||
any(target_family = "unix", target_os = "hermit", target_os = "solid_asp3", target_os = "trusty", target_os = "wasi") => {
|
||||
mod iovec;
|
||||
pub use iovec::*;
|
||||
}
|
||||
target_os = "windows" => {
|
||||
mod windows;
|
||||
pub use windows::*;
|
||||
}
|
||||
target_os = "uefi" => {
|
||||
mod uefi;
|
||||
pub use uefi::*;
|
||||
}
|
||||
_ => {
|
||||
mod unsupported;
|
||||
pub use unsupported::*;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod is_terminal {
|
||||
cfg_select! {
|
||||
any(target_family = "unix", target_os = "wasi") => {
|
||||
mod isatty;
|
||||
pub use isatty::*;
|
||||
}
|
||||
target_os = "windows" => {
|
||||
mod windows;
|
||||
pub use windows::*;
|
||||
}
|
||||
target_os = "hermit" => {
|
||||
mod hermit;
|
||||
pub use hermit::*;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
pub use motor::*;
|
||||
}
|
||||
_ => {
|
||||
mod unsupported;
|
||||
pub use unsupported::*;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod kernel_copy;
|
||||
|
||||
#[cfg_attr(not(target_os = "linux"), allow(unused_imports))]
|
||||
#[cfg(all(
|
||||
target_family = "unix",
|
||||
not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems"))
|
||||
))]
|
||||
pub use error::errno_location;
|
||||
#[cfg_attr(not(target_os = "linux"), allow(unused_imports))]
|
||||
#[cfg(any(
|
||||
all(target_family = "unix", not(any(target_os = "vxworks", target_os = "rtems"))),
|
||||
target_os = "wasi",
|
||||
))]
|
||||
pub use error::set_errno;
|
||||
pub use error::{RawOsError, decode_error_kind, errno, error_string, is_interrupted};
|
||||
pub use io_slice::{IoSlice, IoSliceMut};
|
||||
pub use is_terminal::is_terminal;
|
||||
pub use kernel_copy::{CopyState, kernel_copy};
|
||||
|
||||
// Bare metal platforms usually have very small amounts of RAM
|
||||
// (in the order of hundreds of KB)
|
||||
pub const DEFAULT_BUF_SIZE: usize = if cfg!(target_os = "espidf") { 512 } else { 8 * 1024 };
|
||||
1
library/std/src/sys/io/mod.rs
Symbolic link
1
library/std/src/sys/io/mod.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/io/mod.rs
|
||||
@@ -1,55 +0,0 @@
|
||||
#![allow(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
mod alloc;
|
||||
mod configure_builtins;
|
||||
mod helpers;
|
||||
mod pal;
|
||||
mod personality;
|
||||
|
||||
pub mod args;
|
||||
pub mod backtrace;
|
||||
pub mod cmath;
|
||||
pub mod env;
|
||||
pub mod env_consts;
|
||||
pub mod exit;
|
||||
pub mod fd;
|
||||
pub mod fs;
|
||||
pub mod io;
|
||||
pub mod net;
|
||||
pub mod os_str;
|
||||
pub mod path;
|
||||
pub mod pipe;
|
||||
pub mod platform_version;
|
||||
pub mod process;
|
||||
pub mod random;
|
||||
pub mod stdio;
|
||||
pub mod sync;
|
||||
pub mod thread;
|
||||
pub mod thread_local;
|
||||
pub mod time;
|
||||
|
||||
// FIXME(117276): remove this, move feature implementations into individual
|
||||
// submodules.
|
||||
pub use pal::*;
|
||||
|
||||
/// A trait for viewing representations from std types.
|
||||
#[cfg_attr(not(target_os = "linux"), allow(unused))]
|
||||
pub(crate) trait AsInner<Inner: ?Sized> {
|
||||
fn as_inner(&self) -> &Inner;
|
||||
}
|
||||
|
||||
/// A trait for viewing representations from std types.
|
||||
#[cfg_attr(not(target_os = "linux"), allow(unused))]
|
||||
pub(crate) trait AsInnerMut<Inner: ?Sized> {
|
||||
fn as_inner_mut(&mut self) -> &mut Inner;
|
||||
}
|
||||
|
||||
/// A trait for extracting representations from std types.
|
||||
pub(crate) trait IntoInner<Inner> {
|
||||
fn into_inner(self) -> Inner;
|
||||
}
|
||||
|
||||
/// A trait for creating std types from internal representations.
|
||||
pub(crate) trait FromInner<Inner> {
|
||||
fn from_inner(inner: Inner) -> Self;
|
||||
}
|
||||
1
library/std/src/sys/mod.rs
Symbolic link
1
library/std/src/sys/mod.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/mod.rs
|
||||
@@ -1,61 +0,0 @@
|
||||
cfg_select! {
|
||||
any(
|
||||
all(target_family = "unix", not(target_os = "l4re")),
|
||||
target_os = "windows",
|
||||
target_os = "hermit",
|
||||
all(target_os = "wasi", any(target_env = "p2", target_env = "p3")),
|
||||
target_os = "solid_asp3",
|
||||
) => {
|
||||
mod socket;
|
||||
pub use socket::*;
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
mod sgx;
|
||||
pub use sgx::*;
|
||||
}
|
||||
all(target_os = "wasi", target_env = "p1") => {
|
||||
mod wasip1;
|
||||
pub use wasip1::*;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
pub use motor::*;
|
||||
}
|
||||
target_os = "xous" => {
|
||||
mod xous;
|
||||
pub use xous::*;
|
||||
}
|
||||
target_os = "uefi" => {
|
||||
mod uefi;
|
||||
pub use uefi::*;
|
||||
}
|
||||
_ => {
|
||||
mod unsupported;
|
||||
pub use unsupported::*;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
// Make sure that this is used on some platforms at least.
|
||||
not(any(target_os = "linux", target_os = "windows")),
|
||||
allow(dead_code)
|
||||
)]
|
||||
fn each_addr<A: crate::net::ToSocketAddrs, F, T>(addr: A, mut f: F) -> crate::io::Result<T>
|
||||
where
|
||||
F: FnMut(&crate::net::SocketAddr) -> crate::io::Result<T>,
|
||||
{
|
||||
use crate::io::Error;
|
||||
|
||||
let mut last_err = None;
|
||||
for addr in addr.to_socket_addrs()? {
|
||||
match f(&addr) {
|
||||
Ok(l) => return Ok(l),
|
||||
Err(e) => last_err = Some(e),
|
||||
}
|
||||
}
|
||||
|
||||
match last_err {
|
||||
Some(err) => Err(err),
|
||||
None => Err(Error::NO_ADDRESSES),
|
||||
}
|
||||
}
|
||||
1
library/std/src/sys/net/connection/mod.rs
Symbolic link
1
library/std/src/sys/net/connection/mod.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/net/connection/mod.rs
|
||||
@@ -1,316 +0,0 @@
|
||||
use crate::fmt;
|
||||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
||||
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
|
||||
use crate::sys::unsupported;
|
||||
use crate::time::Duration;
|
||||
|
||||
pub struct TcpStream(!);
|
||||
|
||||
impl TcpStream {
|
||||
pub fn connect<A: ToSocketAddrs>(_: A) -> io::Result<TcpStream> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn read_buf(&self, _buf: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn is_read_vectored(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn write(&self, _: &[u8]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<TcpStream> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn linger(&self) -> io::Result<Option<Duration>> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn nodelay(&self) -> io::Result<bool> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_ttl(&self, _: u32) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn ttl(&self) -> io::Result<u32> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for TcpStream {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TcpListener(!);
|
||||
|
||||
impl TcpListener {
|
||||
pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<TcpListener> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<TcpListener> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_ttl(&self, _: u32) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn ttl(&self) -> io::Result<u32> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn only_v6(&self) -> io::Result<bool> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for TcpListener {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UdpSocket(!);
|
||||
|
||||
impl UdpSocket {
|
||||
pub fn bind<A: ToSocketAddrs>(_: A) -> io::Result<UdpSocket> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<UdpSocket> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn broadcast(&self) -> io::Result<bool> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn multicast_loop_v4(&self) -> io::Result<bool> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn multicast_loop_v6(&self) -> io::Result<bool> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_ttl(&self, _: u32) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn ttl(&self) -> io::Result<u32> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn send(&self, _: &[u8]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn connect<A: ToSocketAddrs>(&self, _: A) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for UdpSocket {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LookupHost(!);
|
||||
|
||||
impl Iterator for LookupHost {
|
||||
type Item = SocketAddr;
|
||||
fn next(&mut self) -> Option<SocketAddr> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lookup_host(_host: &str, _port: u16) -> io::Result<LookupHost> {
|
||||
unsupported()
|
||||
}
|
||||
1
library/std/src/sys/net/connection/unsupported.rs
Symbolic link
1
library/std/src/sys/net/connection/unsupported.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/net/connection/unsupported.rs
|
||||
@@ -1,15 +0,0 @@
|
||||
cfg_select! {
|
||||
all(target_family = "unix", not(target_os = "espidf")) => {
|
||||
mod unix;
|
||||
pub use unix::hostname;
|
||||
}
|
||||
// `GetHostNameW` is only available starting with Windows 8.
|
||||
all(target_os = "windows", not(target_vendor = "win7")) => {
|
||||
mod windows;
|
||||
pub use windows::hostname;
|
||||
}
|
||||
_ => {
|
||||
mod unsupported;
|
||||
pub use unsupported::hostname;
|
||||
}
|
||||
}
|
||||
1
library/std/src/sys/net/hostname/mod.rs
Symbolic link
1
library/std/src/sys/net/hostname/mod.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/net/hostname/mod.rs
|
||||
@@ -1,6 +0,0 @@
|
||||
use crate::ffi::OsString;
|
||||
use crate::io::{Error, Result};
|
||||
|
||||
pub fn hostname() -> Result<OsString> {
|
||||
Err(Error::UNSUPPORTED_PLATFORM)
|
||||
}
|
||||
1
library/std/src/sys/net/hostname/unsupported.rs
Symbolic link
1
library/std/src/sys/net/hostname/unsupported.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/net/hostname/unsupported.rs
|
||||
@@ -1,7 +0,0 @@
|
||||
/// This module contains the implementations of `TcpStream`, `TcpListener` and
|
||||
/// `UdpSocket` as well as related functionality like DNS resolving.
|
||||
mod connection;
|
||||
pub use connection::*;
|
||||
|
||||
mod hostname;
|
||||
pub use hostname::hostname;
|
||||
1
library/std/src/sys/net/mod.rs
Symbolic link
1
library/std/src/sys/net/mod.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/net/mod.rs
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user