Add more from the std

This commit is contained in:
2026-03-20 10:30:23 +01:00
parent 48a75485b6
commit a134536d2f
92 changed files with 440 additions and 25793 deletions

2
library/.gitignore vendored
View File

@@ -12,3 +12,5 @@ rustc-std-workspace-alloc
rustc-std-workspace-core
rustc-std-workspace-std
windows_link
test
proc_macro

View File

@@ -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
View 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

View File

@@ -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))
}

View File

@@ -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
View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/alloc.rs

View File

@@ -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
View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/ascii.rs

View File

@@ -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),
}
}
}

View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/backtrace.rs

View File

@@ -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
View File

@@ -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
View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/env.rs

View File

@@ -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
View File

@@ -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
View File

@@ -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

View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/keyword_docs.rs

View File

@@ -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>&nbsp;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
View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/lib.rs

View File

@@ -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
View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/macros.rs

View File

@@ -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
View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/os/mod.rs

View File

@@ -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
}

View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/os/raw/mod.rs

View File

@@ -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);
}

View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/os/raw/tests.rs

View File

@@ -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
View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs

View File

@@ -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();
}

View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs

View File

@@ -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
View File

@@ -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
View File

@@ -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
View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/process.rs

View File

@@ -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
View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/random.rs

View File

@@ -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
View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/rt.rs

View File

@@ -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
}
}

View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/args/unsupported.rs

View File

@@ -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
}

View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/backtrace.rs

View File

@@ -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
}

View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/cmath.rs

View File

@@ -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
};

View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/configure_builtins.rs

View File

@@ -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
View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/env/common.rs

View File

@@ -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
View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/env/mod.rs

View File

@@ -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
View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/env/unsupported.rs

View File

@@ -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 = "";
}
}

View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/env_consts.rs

View File

@@ -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
View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/exit.rs

View File

@@ -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::*;
}
_ => {}
}

View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/fd/mod.rs

View File

@@ -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()
}
}

View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/fs/common.rs

View File

@@ -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()))
}

View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/fs/mod.rs

View File

@@ -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()
}

View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/fs/unsupported.rs

View File

@@ -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),
}
}

View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/helpers/mod.rs

View File

@@ -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),
}
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/helpers/tests.rs

View File

@@ -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)
}
}
}

View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/helpers/wstr.rs

View File

@@ -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()
}

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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

View File

@@ -1,3 +0,0 @@
pub fn is_terminal<T>(_: &T) -> bool {
false
}

View File

@@ -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

View File

@@ -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))
}
}
}

View File

@@ -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

View File

@@ -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 };

View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/io/mod.rs

View File

@@ -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
View File

@@ -0,0 +1 @@
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/mod.rs

View File

@@ -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),
}
}

View File

@@ -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

View File

@@ -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()
}

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -1,6 +0,0 @@
use crate::ffi::OsString;
use crate::io::{Error, Result};
pub fn hostname() -> Result<OsString> {
Err(Error::UNSUPPORTED_PLATFORM)
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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