mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-15 00:13:02 +00:00
Auto merge of #136533 - jhpratt:rollup-s0ign8n, r=jhpratt
Rollup of 5 pull requests Successful merges: - #134777 (Enable more tests on Windows) - #135621 (Move some std tests to integration tests) - #135844 ( Add new tool for dumping feature status based on tidy ) - #136167 (Implement unstable `new_range` feature) - #136334 (Extract `core::ffi` primitives to a separate (internal) module) Failed merges: - #136201 (Removed dependency on the field-offset crate, alternate approach) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
7b31983d55
15
Cargo.lock
15
Cargo.lock
@ -186,6 +186,9 @@ name = "anyhow"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ar_archive_writer"
|
||||
@ -1195,6 +1198,17 @@ version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||
|
||||
[[package]]
|
||||
name = "features-status-dump"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tidy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "field-offset"
|
||||
version = "0.3.6"
|
||||
@ -5418,6 +5432,7 @@ dependencies = [
|
||||
"regex",
|
||||
"rustc-hash 2.1.0",
|
||||
"semver",
|
||||
"serde",
|
||||
"similar",
|
||||
"termcolor",
|
||||
"walkdir",
|
||||
|
@ -47,6 +47,7 @@ members = [
|
||||
"src/tools/coverage-dump",
|
||||
"src/tools/rustc-perf-wrapper",
|
||||
"src/tools/wasm-component-ld",
|
||||
"src/tools/features-status-dump",
|
||||
]
|
||||
|
||||
exclude = [
|
||||
|
@ -284,9 +284,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
ExprKind::Index(el, er, brackets_span) => {
|
||||
hir::ExprKind::Index(self.lower_expr(el), self.lower_expr(er), *brackets_span)
|
||||
}
|
||||
ExprKind::Range(Some(e1), Some(e2), RangeLimits::Closed) => {
|
||||
self.lower_expr_range_closed(e.span, e1, e2)
|
||||
}
|
||||
ExprKind::Range(e1, e2, lims) => {
|
||||
self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), *lims)
|
||||
}
|
||||
@ -1512,15 +1509,39 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
|
||||
let lang_item = match (e1, e2, lims) {
|
||||
(None, None, HalfOpen) => hir::LangItem::RangeFull,
|
||||
(Some(..), None, HalfOpen) => hir::LangItem::RangeFrom,
|
||||
(Some(..), None, HalfOpen) => {
|
||||
if self.tcx.features().new_range() {
|
||||
hir::LangItem::RangeFromCopy
|
||||
} else {
|
||||
hir::LangItem::RangeFrom
|
||||
}
|
||||
}
|
||||
(None, Some(..), HalfOpen) => hir::LangItem::RangeTo,
|
||||
(Some(..), Some(..), HalfOpen) => hir::LangItem::Range,
|
||||
(Some(..), Some(..), HalfOpen) => {
|
||||
if self.tcx.features().new_range() {
|
||||
hir::LangItem::RangeCopy
|
||||
} else {
|
||||
hir::LangItem::Range
|
||||
}
|
||||
}
|
||||
(None, Some(..), Closed) => hir::LangItem::RangeToInclusive,
|
||||
(Some(..), Some(..), Closed) => unreachable!(),
|
||||
(Some(e1), Some(e2), Closed) => {
|
||||
if self.tcx.features().new_range() {
|
||||
hir::LangItem::RangeInclusiveCopy
|
||||
} else {
|
||||
return self.lower_expr_range_closed(span, e1, e2);
|
||||
}
|
||||
}
|
||||
(start, None, Closed) => {
|
||||
self.dcx().emit_err(InclusiveRangeWithNoEnd { span });
|
||||
match start {
|
||||
Some(..) => hir::LangItem::RangeFrom,
|
||||
Some(..) => {
|
||||
if self.tcx.features().new_range() {
|
||||
hir::LangItem::RangeFromCopy
|
||||
} else {
|
||||
hir::LangItem::RangeFrom
|
||||
}
|
||||
}
|
||||
None => hir::LangItem::RangeFull,
|
||||
}
|
||||
}
|
||||
|
@ -570,6 +570,8 @@ declare_features! (
|
||||
(unstable, never_type, "1.13.0", Some(35121)),
|
||||
/// Allows diverging expressions to fall back to `!` rather than `()`.
|
||||
(unstable, never_type_fallback, "1.41.0", Some(65992)),
|
||||
/// Switch `..` syntax to use the new (`Copy + IntoIterator`) range types.
|
||||
(unstable, new_range, "CURRENT_RUSTC_VERSION", Some(123741)),
|
||||
/// Allows `#![no_core]`.
|
||||
(unstable, no_core, "1.3.0", Some(29639)),
|
||||
/// Allows the use of `no_sanitize` attribute.
|
||||
|
@ -2313,6 +2313,18 @@ impl Expr<'_> {
|
||||
[val2],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
)
|
||||
| (
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeFromCopy, _),
|
||||
[val1],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeFromCopy, _),
|
||||
[val2],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
) => val1.expr.equivalent_for_indexing(val2.expr),
|
||||
(
|
||||
ExprKind::Struct(
|
||||
@ -2325,6 +2337,30 @@ impl Expr<'_> {
|
||||
[val2, val4],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
)
|
||||
| (
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeCopy, _),
|
||||
[val1, val3],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeCopy, _),
|
||||
[val2, val4],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
)
|
||||
| (
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeInclusiveCopy, _),
|
||||
[val1, val3],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
ExprKind::Struct(
|
||||
QPath::LangItem(LangItem::RangeInclusiveCopy, _),
|
||||
[val2, val4],
|
||||
StructTailExpr::None,
|
||||
),
|
||||
) => {
|
||||
val1.expr.equivalent_for_indexing(val2.expr)
|
||||
&& val3.expr.equivalent_for_indexing(val4.expr)
|
||||
@ -2354,7 +2390,10 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool {
|
||||
| LangItem::RangeTo
|
||||
| LangItem::RangeFrom
|
||||
| LangItem::RangeFull
|
||||
| LangItem::RangeToInclusive,
|
||||
| LangItem::RangeToInclusive
|
||||
| LangItem::RangeCopy
|
||||
| LangItem::RangeFromCopy
|
||||
| LangItem::RangeInclusiveCopy,
|
||||
..
|
||||
)
|
||||
),
|
||||
|
@ -416,6 +416,11 @@ language_item_table! {
|
||||
RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, Target::Struct, GenericRequirement::None;
|
||||
RangeTo, sym::RangeTo, range_to_struct, Target::Struct, GenericRequirement::None;
|
||||
|
||||
// `new_range` types that are `Copy + IntoIterator`
|
||||
RangeFromCopy, sym::RangeFromCopy, range_from_copy_struct, Target::Struct, GenericRequirement::None;
|
||||
RangeCopy, sym::RangeCopy, range_copy_struct, Target::Struct, GenericRequirement::None;
|
||||
RangeInclusiveCopy, sym::RangeInclusiveCopy, range_inclusive_copy_struct, Target::Struct, GenericRequirement::None;
|
||||
|
||||
String, sym::String, string, Target::Struct, GenericRequirement::None;
|
||||
CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None;
|
||||
}
|
||||
|
@ -2395,6 +2395,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let lang_item = match parent_expr.kind {
|
||||
ExprKind::Struct(qpath, _, _) => match *qpath {
|
||||
QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
|
||||
QPath::LangItem(LangItem::RangeCopy, ..) => Some(LangItem::RangeCopy),
|
||||
QPath::LangItem(LangItem::RangeInclusiveCopy, ..) => {
|
||||
Some(LangItem::RangeInclusiveCopy)
|
||||
}
|
||||
QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
|
||||
QPath::LangItem(LangItem::RangeToInclusive, ..) => {
|
||||
Some(LangItem::RangeToInclusive)
|
||||
|
@ -294,9 +294,12 @@ symbols! {
|
||||
ProceduralMasqueradeDummyType,
|
||||
Range,
|
||||
RangeBounds,
|
||||
RangeCopy,
|
||||
RangeFrom,
|
||||
RangeFromCopy,
|
||||
RangeFull,
|
||||
RangeInclusive,
|
||||
RangeInclusiveCopy,
|
||||
RangeTo,
|
||||
RangeToInclusive,
|
||||
Rc,
|
||||
@ -1364,6 +1367,7 @@ symbols! {
|
||||
new_lower_hex,
|
||||
new_octal,
|
||||
new_pointer,
|
||||
new_range,
|
||||
new_unchecked,
|
||||
new_upper_exp,
|
||||
new_upper_hex,
|
||||
|
@ -37,175 +37,14 @@ pub use self::va_list::{VaList, VaListImpl};
|
||||
)]
|
||||
pub mod va_list;
|
||||
|
||||
macro_rules! type_alias {
|
||||
{
|
||||
$Docfile:tt, $Alias:ident = $Real:ty;
|
||||
$( $Cfg:tt )*
|
||||
} => {
|
||||
#[doc = include_str!($Docfile)]
|
||||
$( $Cfg )*
|
||||
#[stable(feature = "core_ffi_c", since = "1.64.0")]
|
||||
pub type $Alias = $Real;
|
||||
}
|
||||
}
|
||||
|
||||
type_alias! { "c_char.md", c_char = c_char_definition::c_char; #[doc(cfg(all()))] }
|
||||
|
||||
type_alias! { "c_schar.md", c_schar = i8; }
|
||||
type_alias! { "c_uchar.md", c_uchar = u8; }
|
||||
type_alias! { "c_short.md", c_short = i16; }
|
||||
type_alias! { "c_ushort.md", c_ushort = u16; }
|
||||
|
||||
type_alias! { "c_int.md", c_int = c_int_definition::c_int; #[doc(cfg(all()))] }
|
||||
type_alias! { "c_uint.md", c_uint = c_int_definition::c_uint; #[doc(cfg(all()))] }
|
||||
|
||||
type_alias! { "c_long.md", c_long = c_long_definition::c_long; #[doc(cfg(all()))] }
|
||||
type_alias! { "c_ulong.md", c_ulong = c_long_definition::c_ulong; #[doc(cfg(all()))] }
|
||||
|
||||
type_alias! { "c_longlong.md", c_longlong = i64; }
|
||||
type_alias! { "c_ulonglong.md", c_ulonglong = u64; }
|
||||
|
||||
type_alias! { "c_float.md", c_float = f32; }
|
||||
type_alias! { "c_double.md", c_double = f64; }
|
||||
|
||||
/// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++).
|
||||
///
|
||||
/// This type is currently always [`usize`], however in the future there may be
|
||||
/// platforms where this is not the case.
|
||||
mod primitives;
|
||||
#[stable(feature = "core_ffi_c", since = "1.64.0")]
|
||||
pub use self::primitives::{
|
||||
c_char, c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint,
|
||||
c_ulong, c_ulonglong, c_ushort,
|
||||
};
|
||||
#[unstable(feature = "c_size_t", issue = "88345")]
|
||||
pub type c_size_t = usize;
|
||||
|
||||
/// Equivalent to C's `ptrdiff_t` type, from `stddef.h` (or `cstddef` for C++).
|
||||
///
|
||||
/// This type is currently always [`isize`], however in the future there may be
|
||||
/// platforms where this is not the case.
|
||||
#[unstable(feature = "c_size_t", issue = "88345")]
|
||||
pub type c_ptrdiff_t = isize;
|
||||
|
||||
/// Equivalent to C's `ssize_t` (on POSIX) or `SSIZE_T` (on Windows) type.
|
||||
///
|
||||
/// This type is currently always [`isize`], however in the future there may be
|
||||
/// platforms where this is not the case.
|
||||
#[unstable(feature = "c_size_t", issue = "88345")]
|
||||
pub type c_ssize_t = isize;
|
||||
|
||||
mod c_char_definition {
|
||||
cfg_if! {
|
||||
// These are the targets on which c_char is unsigned. Usually the
|
||||
// signedness is the same for all target_os values on a given architecture
|
||||
// but there are some exceptions (see isSignedCharDefault() in clang).
|
||||
//
|
||||
// aarch64:
|
||||
// Section 10 "Arm C and C++ language mappings" in Procedure Call Standard for the Arm®
|
||||
// 64-bit Architecture (AArch64) says C/C++ char is unsigned byte.
|
||||
// https://github.com/ARM-software/abi-aa/blob/2024Q3/aapcs64/aapcs64.rst#arm-c-and-c-language-mappings
|
||||
// arm:
|
||||
// Section 8 "Arm C and C++ Language Mappings" in Procedure Call Standard for the Arm®
|
||||
// Architecture says C/C++ char is unsigned byte.
|
||||
// https://github.com/ARM-software/abi-aa/blob/2024Q3/aapcs32/aapcs32.rst#arm-c-and-c-language-mappings
|
||||
// csky:
|
||||
// Section 2.1.2 "Primary Data Type" in C-SKY V2 CPU Applications Binary Interface
|
||||
// Standards Manual says ANSI C char is unsigned byte.
|
||||
// https://github.com/c-sky/csky-doc/blob/9f7121f7d40970ba5cc0f15716da033db2bb9d07/C-SKY_V2_CPU_Applications_Binary_Interface_Standards_Manual.pdf
|
||||
// Note: this doesn't seem to match Clang's default (https://github.com/rust-lang/rust/issues/129945).
|
||||
// hexagon:
|
||||
// Section 3.1 "Basic data type" in Qualcomm Hexagon™ Application
|
||||
// Binary Interface User Guide says "By default, the `char` data type is unsigned."
|
||||
// https://docs.qualcomm.com/bundle/publicresource/80-N2040-23_REV_K_Qualcomm_Hexagon_Application_Binary_Interface_User_Guide.pdf
|
||||
// msp430:
|
||||
// Section 2.1 "Basic Types" in MSP430 Embedded Application Binary
|
||||
// Interface says "The char type is unsigned by default".
|
||||
// https://www.ti.com/lit/an/slaa534a/slaa534a.pdf
|
||||
// powerpc/powerpc64:
|
||||
// - PPC32 SysV: "Table 3-1 Scalar Types" in System V Application Binary Interface PowerPC
|
||||
// Processor Supplement says ANSI C char is unsigned byte
|
||||
// https://refspecs.linuxfoundation.org/elf/elfspec_ppc.pdf
|
||||
// - PPC64 ELFv1: Section 3.1.4 "Fundamental Types" in 64-bit PowerPC ELF Application
|
||||
// Binary Interface Supplement 1.9 says ANSI C is unsigned byte
|
||||
// https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUND-TYPE
|
||||
// - PPC64 ELFv2: Section 2.1.2.2 "Fundamental Types" in 64-Bit ELF V2 ABI Specification
|
||||
// says char is unsigned byte
|
||||
// https://openpowerfoundation.org/specifications/64bitelfabi/
|
||||
// - AIX: XL C for AIX Language Reference says "By default, char behaves like an unsigned char."
|
||||
// https://www.ibm.com/docs/en/xl-c-aix/13.1.3?topic=specifiers-character-types
|
||||
// riscv32/riscv64:
|
||||
// C/C++ type representations section in RISC-V Calling Conventions
|
||||
// page in RISC-V ELF psABI Document says "char is unsigned."
|
||||
// https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/draft-20240829-13bfa9f54634cb60d86b9b333e109f077805b4b3/riscv-cc.adoc#cc-type-representations
|
||||
// s390x:
|
||||
// - ELF: "Table 1.1.: Scalar types" in ELF Application Binary Interface s390x Supplement
|
||||
// Version 1.6.1 categorize ISO C char in unsigned integer
|
||||
// https://github.com/IBM/s390x-abi/releases/tag/v1.6.1
|
||||
// - z/OS: XL C/C++ Language Reference says: "By default, char behaves like an unsigned char."
|
||||
// https://www.ibm.com/docs/en/zos/3.1.0?topic=specifiers-character-types
|
||||
// xtensa:
|
||||
// Section 2.17.1 "Data Types and Alignment" of Xtensa LX Microprocessor Overview handbook
|
||||
// says "`char` type is unsigned by default".
|
||||
// https://loboris.eu/ESP32/Xtensa_lx%20Overview%20handbook.pdf
|
||||
//
|
||||
// On the following operating systems, c_char is signed by default, regardless of architecture.
|
||||
// Darwin (macOS, iOS, etc.):
|
||||
// Apple targets' c_char is signed by default even on arm
|
||||
// https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Handle-data-types-and-data-alignment-properly
|
||||
// Windows:
|
||||
// Windows MSVC C++ Language Reference says "Microsoft-specific: Variables of type char
|
||||
// are promoted to int as if from type signed char by default, unless the /J compilation
|
||||
// option is used."
|
||||
// https://learn.microsoft.com/en-us/cpp/cpp/fundamental-types-cpp?view=msvc-170#character-types
|
||||
// L4Re:
|
||||
// The kernel builds with -funsigned-char on all targets (but useserspace follows the
|
||||
// architecture defaults). As we only have a target for userspace apps so there are no
|
||||
// special cases for L4Re below.
|
||||
// https://github.com/rust-lang/rust/pull/132975#issuecomment-2484645240
|
||||
if #[cfg(all(
|
||||
not(windows),
|
||||
not(target_vendor = "apple"),
|
||||
any(
|
||||
target_arch = "aarch64",
|
||||
target_arch = "arm",
|
||||
target_arch = "csky",
|
||||
target_arch = "hexagon",
|
||||
target_arch = "msp430",
|
||||
target_arch = "powerpc",
|
||||
target_arch = "powerpc64",
|
||||
target_arch = "riscv32",
|
||||
target_arch = "riscv64",
|
||||
target_arch = "s390x",
|
||||
target_arch = "xtensa",
|
||||
)
|
||||
))] {
|
||||
pub(super) type c_char = u8;
|
||||
} else {
|
||||
// On every other target, c_char is signed.
|
||||
pub(super) type c_char = i8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod c_int_definition {
|
||||
cfg_if! {
|
||||
if #[cfg(any(target_arch = "avr", target_arch = "msp430"))] {
|
||||
pub(super) type c_int = i16;
|
||||
pub(super) type c_uint = u16;
|
||||
} else {
|
||||
pub(super) type c_int = i32;
|
||||
pub(super) type c_uint = u32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod c_long_definition {
|
||||
cfg_if! {
|
||||
if #[cfg(all(target_pointer_width = "64", not(windows)))] {
|
||||
pub(super) type c_long = i64;
|
||||
pub(super) type c_ulong = u64;
|
||||
} else {
|
||||
// The minimal size of `long` in the C standard is 32 bits
|
||||
pub(super) type c_long = i32;
|
||||
pub(super) type c_ulong = u32;
|
||||
}
|
||||
}
|
||||
}
|
||||
pub use self::primitives::{c_ptrdiff_t, c_size_t, c_ssize_t};
|
||||
|
||||
// N.B., for LLVM to recognize the void pointer type and by extension
|
||||
// functions like malloc(), we need to have it represented as i8* in
|
||||
|
174
library/core/src/ffi/primitives.rs
Normal file
174
library/core/src/ffi/primitives.rs
Normal file
@ -0,0 +1,174 @@
|
||||
//! Defines primitive types that match C's type definitions for FFI compatibility.
|
||||
//!
|
||||
//! This module is intentionally standalone to facilitate parsing when retrieving
|
||||
//! core C types.
|
||||
|
||||
macro_rules! type_alias {
|
||||
{
|
||||
$Docfile:tt, $Alias:ident = $Real:ty;
|
||||
$( $Cfg:tt )*
|
||||
} => {
|
||||
#[doc = include_str!($Docfile)]
|
||||
$( $Cfg )*
|
||||
#[stable(feature = "core_ffi_c", since = "1.64.0")]
|
||||
pub type $Alias = $Real;
|
||||
}
|
||||
}
|
||||
|
||||
type_alias! { "c_char.md", c_char = c_char_definition::c_char; #[doc(cfg(all()))] }
|
||||
|
||||
type_alias! { "c_schar.md", c_schar = i8; }
|
||||
type_alias! { "c_uchar.md", c_uchar = u8; }
|
||||
type_alias! { "c_short.md", c_short = i16; }
|
||||
type_alias! { "c_ushort.md", c_ushort = u16; }
|
||||
|
||||
type_alias! { "c_int.md", c_int = c_int_definition::c_int; #[doc(cfg(all()))] }
|
||||
type_alias! { "c_uint.md", c_uint = c_int_definition::c_uint; #[doc(cfg(all()))] }
|
||||
|
||||
type_alias! { "c_long.md", c_long = c_long_definition::c_long; #[doc(cfg(all()))] }
|
||||
type_alias! { "c_ulong.md", c_ulong = c_long_definition::c_ulong; #[doc(cfg(all()))] }
|
||||
|
||||
type_alias! { "c_longlong.md", c_longlong = i64; }
|
||||
type_alias! { "c_ulonglong.md", c_ulonglong = u64; }
|
||||
|
||||
type_alias! { "c_float.md", c_float = f32; }
|
||||
type_alias! { "c_double.md", c_double = f64; }
|
||||
|
||||
mod c_char_definition {
|
||||
cfg_if! {
|
||||
// These are the targets on which c_char is unsigned. Usually the
|
||||
// signedness is the same for all target_os values on a given architecture
|
||||
// but there are some exceptions (see isSignedCharDefault() in clang).
|
||||
//
|
||||
// aarch64:
|
||||
// Section 10 "Arm C and C++ language mappings" in Procedure Call Standard for the Arm®
|
||||
// 64-bit Architecture (AArch64) says C/C++ char is unsigned byte.
|
||||
// https://github.com/ARM-software/abi-aa/blob/2024Q3/aapcs64/aapcs64.rst#arm-c-and-c-language-mappings
|
||||
// arm:
|
||||
// Section 8 "Arm C and C++ Language Mappings" in Procedure Call Standard for the Arm®
|
||||
// Architecture says C/C++ char is unsigned byte.
|
||||
// https://github.com/ARM-software/abi-aa/blob/2024Q3/aapcs32/aapcs32.rst#arm-c-and-c-language-mappings
|
||||
// csky:
|
||||
// Section 2.1.2 "Primary Data Type" in C-SKY V2 CPU Applications Binary Interface
|
||||
// Standards Manual says ANSI C char is unsigned byte.
|
||||
// https://github.com/c-sky/csky-doc/blob/9f7121f7d40970ba5cc0f15716da033db2bb9d07/C-SKY_V2_CPU_Applications_Binary_Interface_Standards_Manual.pdf
|
||||
// Note: this doesn't seem to match Clang's default (https://github.com/rust-lang/rust/issues/129945).
|
||||
// hexagon:
|
||||
// Section 3.1 "Basic data type" in Qualcomm Hexagon™ Application
|
||||
// Binary Interface User Guide says "By default, the `char` data type is unsigned."
|
||||
// https://docs.qualcomm.com/bundle/publicresource/80-N2040-23_REV_K_Qualcomm_Hexagon_Application_Binary_Interface_User_Guide.pdf
|
||||
// msp430:
|
||||
// Section 2.1 "Basic Types" in MSP430 Embedded Application Binary
|
||||
// Interface says "The char type is unsigned by default".
|
||||
// https://www.ti.com/lit/an/slaa534a/slaa534a.pdf
|
||||
// powerpc/powerpc64:
|
||||
// - PPC32 SysV: "Table 3-1 Scalar Types" in System V Application Binary Interface PowerPC
|
||||
// Processor Supplement says ANSI C char is unsigned byte
|
||||
// https://refspecs.linuxfoundation.org/elf/elfspec_ppc.pdf
|
||||
// - PPC64 ELFv1: Section 3.1.4 "Fundamental Types" in 64-bit PowerPC ELF Application
|
||||
// Binary Interface Supplement 1.9 says ANSI C is unsigned byte
|
||||
// https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUND-TYPE
|
||||
// - PPC64 ELFv2: Section 2.1.2.2 "Fundamental Types" in 64-Bit ELF V2 ABI Specification
|
||||
// says char is unsigned byte
|
||||
// https://openpowerfoundation.org/specifications/64bitelfabi/
|
||||
// - AIX: XL C for AIX Language Reference says "By default, char behaves like an unsigned char."
|
||||
// https://www.ibm.com/docs/en/xl-c-aix/13.1.3?topic=specifiers-character-types
|
||||
// riscv32/riscv64:
|
||||
// C/C++ type representations section in RISC-V Calling Conventions
|
||||
// page in RISC-V ELF psABI Document says "char is unsigned."
|
||||
// https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/draft-20240829-13bfa9f54634cb60d86b9b333e109f077805b4b3/riscv-cc.adoc#cc-type-representations
|
||||
// s390x:
|
||||
// - ELF: "Table 1.1.: Scalar types" in ELF Application Binary Interface s390x Supplement
|
||||
// Version 1.6.1 categorize ISO C char in unsigned integer
|
||||
// https://github.com/IBM/s390x-abi/releases/tag/v1.6.1
|
||||
// - z/OS: XL C/C++ Language Reference says: "By default, char behaves like an unsigned char."
|
||||
// https://www.ibm.com/docs/en/zos/3.1.0?topic=specifiers-character-types
|
||||
// xtensa:
|
||||
// Section 2.17.1 "Data Types and Alignment" of Xtensa LX Microprocessor Overview handbook
|
||||
// says "`char` type is unsigned by default".
|
||||
// https://loboris.eu/ESP32/Xtensa_lx%20Overview%20handbook.pdf
|
||||
//
|
||||
// On the following operating systems, c_char is signed by default, regardless of architecture.
|
||||
// Darwin (macOS, iOS, etc.):
|
||||
// Apple targets' c_char is signed by default even on arm
|
||||
// https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Handle-data-types-and-data-alignment-properly
|
||||
// Windows:
|
||||
// Windows MSVC C++ Language Reference says "Microsoft-specific: Variables of type char
|
||||
// are promoted to int as if from type signed char by default, unless the /J compilation
|
||||
// option is used."
|
||||
// https://learn.microsoft.com/en-us/cpp/cpp/fundamental-types-cpp?view=msvc-170#character-types
|
||||
// L4Re:
|
||||
// The kernel builds with -funsigned-char on all targets (but useserspace follows the
|
||||
// architecture defaults). As we only have a target for userspace apps so there are no
|
||||
// special cases for L4Re below.
|
||||
// https://github.com/rust-lang/rust/pull/132975#issuecomment-2484645240
|
||||
if #[cfg(all(
|
||||
not(windows),
|
||||
not(target_vendor = "apple"),
|
||||
any(
|
||||
target_arch = "aarch64",
|
||||
target_arch = "arm",
|
||||
target_arch = "csky",
|
||||
target_arch = "hexagon",
|
||||
target_arch = "msp430",
|
||||
target_arch = "powerpc",
|
||||
target_arch = "powerpc64",
|
||||
target_arch = "riscv32",
|
||||
target_arch = "riscv64",
|
||||
target_arch = "s390x",
|
||||
target_arch = "xtensa",
|
||||
)
|
||||
))] {
|
||||
pub(super) type c_char = u8;
|
||||
} else {
|
||||
// On every other target, c_char is signed.
|
||||
pub(super) type c_char = i8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod c_long_definition {
|
||||
cfg_if! {
|
||||
if #[cfg(all(target_pointer_width = "64", not(windows)))] {
|
||||
pub(super) type c_long = i64;
|
||||
pub(super) type c_ulong = u64;
|
||||
} else {
|
||||
// The minimal size of `long` in the C standard is 32 bits
|
||||
pub(super) type c_long = i32;
|
||||
pub(super) type c_ulong = u32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++).
|
||||
///
|
||||
/// This type is currently always [`usize`], however in the future there may be
|
||||
/// platforms where this is not the case.
|
||||
#[unstable(feature = "c_size_t", issue = "88345")]
|
||||
pub type c_size_t = usize;
|
||||
|
||||
/// Equivalent to C's `ptrdiff_t` type, from `stddef.h` (or `cstddef` for C++).
|
||||
///
|
||||
/// This type is currently always [`isize`], however in the future there may be
|
||||
/// platforms where this is not the case.
|
||||
#[unstable(feature = "c_size_t", issue = "88345")]
|
||||
pub type c_ptrdiff_t = isize;
|
||||
|
||||
/// Equivalent to C's `ssize_t` (on POSIX) or `SSIZE_T` (on Windows) type.
|
||||
///
|
||||
/// This type is currently always [`isize`], however in the future there may be
|
||||
/// platforms where this is not the case.
|
||||
#[unstable(feature = "c_size_t", issue = "88345")]
|
||||
pub type c_ssize_t = isize;
|
||||
|
||||
mod c_int_definition {
|
||||
cfg_if! {
|
||||
if #[cfg(any(target_arch = "avr", target_arch = "msp430"))] {
|
||||
pub(super) type c_int = i16;
|
||||
pub(super) type c_uint = u16;
|
||||
} else {
|
||||
pub(super) type c_int = i32;
|
||||
pub(super) type c_uint = u32;
|
||||
}
|
||||
}
|
||||
}
|
@ -48,6 +48,7 @@ pub use crate::ops::{Bound, OneSidedRange, RangeBounds, RangeFull, RangeTo, Rang
|
||||
/// assert_eq!(Range::from(3..5), Range { start: 3, end: 5 });
|
||||
/// assert_eq!(3 + 4 + 5, Range::from(3..6).into_iter().sum());
|
||||
/// ```
|
||||
#[cfg_attr(not(bootstrap), lang = "RangeCopy")]
|
||||
#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
|
||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||
pub struct Range<Idx> {
|
||||
@ -205,6 +206,7 @@ impl<T> From<legacy::Range<T>> for Range<T> {
|
||||
/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, end: 5 });
|
||||
/// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum());
|
||||
/// ```
|
||||
#[cfg_attr(not(bootstrap), lang = "RangeInclusiveCopy")]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||
pub struct RangeInclusive<Idx> {
|
||||
@ -388,6 +390,7 @@ impl<T> From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
|
||||
/// assert_eq!(RangeFrom::from(2..), core::range::RangeFrom { start: 2 });
|
||||
/// assert_eq!(2 + 3 + 4, RangeFrom::from(2..).into_iter().take(3).sum());
|
||||
/// ```
|
||||
#[cfg_attr(not(bootstrap), lang = "RangeFromCopy")]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||
pub struct RangeFrom<Idx> {
|
||||
|
@ -7,6 +7,7 @@ license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/rust-lang/rust.git"
|
||||
description = "The Rust Standard Library"
|
||||
edition = "2021"
|
||||
autobenches = false
|
||||
|
||||
[lib]
|
||||
crate-type = ["dylib", "rlib"]
|
||||
@ -130,6 +131,18 @@ name = "pipe-subprocess"
|
||||
path = "tests/pipe_subprocess.rs"
|
||||
harness = false
|
||||
|
||||
[[test]]
|
||||
name = "sync"
|
||||
path = "tests/sync/lib.rs"
|
||||
|
||||
[[test]]
|
||||
name = "floats"
|
||||
path = "tests/floats/lib.rs"
|
||||
|
||||
[[test]]
|
||||
name = "thread_local"
|
||||
path = "tests/thread_local/lib.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "stdbenches"
|
||||
path = "benches/lib.rs"
|
||||
|
@ -5,3 +5,5 @@
|
||||
extern crate test;
|
||||
|
||||
mod hash;
|
||||
mod path;
|
||||
mod time;
|
||||
|
114
library/std/benches/path.rs
Normal file
114
library/std/benches/path.rs
Normal file
@ -0,0 +1,114 @@
|
||||
use core::hint::black_box;
|
||||
use std::collections::{BTreeSet, HashSet};
|
||||
use std::hash::{DefaultHasher, Hash, Hasher};
|
||||
use std::path::*;
|
||||
|
||||
#[bench]
|
||||
#[cfg_attr(miri, ignore)] // Miri isn't fast...
|
||||
fn bench_path_cmp_fast_path_buf_sort(b: &mut test::Bencher) {
|
||||
let prefix = "my/home";
|
||||
let mut paths: Vec<_> =
|
||||
(0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
|
||||
|
||||
paths.sort();
|
||||
|
||||
b.iter(|| {
|
||||
black_box(paths.as_mut_slice()).sort_unstable();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
#[cfg_attr(miri, ignore)] // Miri isn't fast...
|
||||
fn bench_path_cmp_fast_path_long(b: &mut test::Bencher) {
|
||||
let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
|
||||
let paths: Vec<_> =
|
||||
(0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
|
||||
|
||||
let mut set = BTreeSet::new();
|
||||
|
||||
paths.iter().for_each(|p| {
|
||||
set.insert(p.as_path());
|
||||
});
|
||||
|
||||
b.iter(|| {
|
||||
set.remove(paths[500].as_path());
|
||||
set.insert(paths[500].as_path());
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
#[cfg_attr(miri, ignore)] // Miri isn't fast...
|
||||
fn bench_path_cmp_fast_path_short(b: &mut test::Bencher) {
|
||||
let prefix = "my/home";
|
||||
let paths: Vec<_> =
|
||||
(0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
|
||||
|
||||
let mut set = BTreeSet::new();
|
||||
|
||||
paths.iter().for_each(|p| {
|
||||
set.insert(p.as_path());
|
||||
});
|
||||
|
||||
b.iter(|| {
|
||||
set.remove(paths[500].as_path());
|
||||
set.insert(paths[500].as_path());
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
#[cfg_attr(miri, ignore)] // Miri isn't fast...
|
||||
fn bench_path_hashset(b: &mut test::Bencher) {
|
||||
let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
|
||||
let paths: Vec<_> =
|
||||
(0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
|
||||
|
||||
let mut set = HashSet::new();
|
||||
|
||||
paths.iter().for_each(|p| {
|
||||
set.insert(p.as_path());
|
||||
});
|
||||
|
||||
b.iter(|| {
|
||||
set.remove(paths[500].as_path());
|
||||
set.insert(black_box(paths[500].as_path()))
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
#[cfg_attr(miri, ignore)] // Miri isn't fast...
|
||||
fn bench_path_hashset_miss(b: &mut test::Bencher) {
|
||||
let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
|
||||
let paths: Vec<_> =
|
||||
(0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
|
||||
|
||||
let mut set = HashSet::new();
|
||||
|
||||
paths.iter().for_each(|p| {
|
||||
set.insert(p.as_path());
|
||||
});
|
||||
|
||||
let probe = PathBuf::from(prefix).join("other");
|
||||
|
||||
b.iter(|| set.remove(black_box(probe.as_path())));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_hash_path_short(b: &mut test::Bencher) {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
let path = Path::new("explorer.exe");
|
||||
|
||||
b.iter(|| black_box(path).hash(&mut hasher));
|
||||
|
||||
black_box(hasher.finish());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_hash_path_long(b: &mut test::Bencher) {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
let path =
|
||||
Path::new("/aaaaa/aaaaaa/./../aaaaaaaa/bbbbbbbbbbbbb/ccccccccccc/ddddddddd/eeeeeee.fff");
|
||||
|
||||
b.iter(|| black_box(path).hash(&mut hasher));
|
||||
|
||||
black_box(hasher.finish());
|
||||
}
|
47
library/std/benches/time.rs
Normal file
47
library/std/benches/time.rs
Normal file
@ -0,0 +1,47 @@
|
||||
use std::time::Instant;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use test::{Bencher, black_box};
|
||||
|
||||
macro_rules! bench_instant_threaded {
|
||||
($bench_name:ident, $thread_count:expr) => {
|
||||
#[bench]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn $bench_name(b: &mut Bencher) -> std::thread::Result<()> {
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
let running = Arc::new(AtomicBool::new(true));
|
||||
|
||||
let threads: Vec<_> = (0..$thread_count)
|
||||
.map(|_| {
|
||||
let flag = Arc::clone(&running);
|
||||
std::thread::spawn(move || {
|
||||
while flag.load(Ordering::Relaxed) {
|
||||
black_box(Instant::now());
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
b.iter(|| {
|
||||
let a = Instant::now();
|
||||
let b = Instant::now();
|
||||
assert!(b >= a);
|
||||
});
|
||||
|
||||
running.store(false, Ordering::Relaxed);
|
||||
|
||||
for t in threads {
|
||||
t.join()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bench_instant_threaded!(instant_contention_01_threads, 0);
|
||||
bench_instant_threaded!(instant_contention_02_threads, 1);
|
||||
bench_instant_threaded!(instant_contention_04_threads, 3);
|
||||
bench_instant_threaded!(instant_contention_08_threads, 7);
|
||||
bench_instant_threaded!(instant_contention_16_threads, 15);
|
@ -10,9 +10,6 @@
|
||||
|
||||
#![stable(feature = "env", since = "1.0.0")]
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::path::{Path, PathBuf};
|
||||
|
120
library/std/src/env/tests.rs
vendored
120
library/std/src/env/tests.rs
vendored
@ -1,120 +0,0 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi", target_env = "sgx"), ignore)]
|
||||
fn test_self_exe_path() {
|
||||
let path = current_exe();
|
||||
assert!(path.is_ok());
|
||||
let path = path.unwrap();
|
||||
|
||||
// Hard to test this function
|
||||
assert!(path.is_absolute());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
assert!((!Path::new("test-path").is_absolute()));
|
||||
|
||||
#[cfg(not(target_env = "sgx"))]
|
||||
current_dir().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(windows)]
|
||||
fn split_paths_windows() {
|
||||
use crate::path::PathBuf;
|
||||
|
||||
fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
|
||||
split_paths(unparsed).collect::<Vec<_>>()
|
||||
== parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
assert!(check_parse("", &mut [""]));
|
||||
assert!(check_parse(r#""""#, &mut [""]));
|
||||
assert!(check_parse(";;", &mut ["", "", ""]));
|
||||
assert!(check_parse(r"c:\", &mut [r"c:\"]));
|
||||
assert!(check_parse(r"c:\;", &mut [r"c:\", ""]));
|
||||
assert!(check_parse(r"c:\;c:\Program Files\", &mut [r"c:\", r"c:\Program Files\"]));
|
||||
assert!(check_parse(r#"c:\;c:\"foo"\"#, &mut [r"c:\", r"c:\foo\"]));
|
||||
assert!(check_parse(r#"c:\;c:\"foo;bar"\;c:\baz"#, &mut [r"c:\", r"c:\foo;bar\", r"c:\baz"]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn split_paths_unix() {
|
||||
use crate::path::PathBuf;
|
||||
|
||||
fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
|
||||
split_paths(unparsed).collect::<Vec<_>>()
|
||||
== parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
assert!(check_parse("", &mut [""]));
|
||||
assert!(check_parse("::", &mut ["", "", ""]));
|
||||
assert!(check_parse("/", &mut ["/"]));
|
||||
assert!(check_parse("/:", &mut ["/", ""]));
|
||||
assert!(check_parse("/:/usr/local", &mut ["/", "/usr/local"]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn join_paths_unix() {
|
||||
use crate::ffi::OsStr;
|
||||
|
||||
fn test_eq(input: &[&str], output: &str) -> bool {
|
||||
&*join_paths(input.iter().cloned()).unwrap() == OsStr::new(output)
|
||||
}
|
||||
|
||||
assert!(test_eq(&[], ""));
|
||||
assert!(test_eq(&["/bin", "/usr/bin", "/usr/local/bin"], "/bin:/usr/bin:/usr/local/bin"));
|
||||
assert!(test_eq(&["", "/bin", "", "", "/usr/bin", ""], ":/bin:::/usr/bin:"));
|
||||
assert!(join_paths(["/te:st"].iter().cloned()).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(windows)]
|
||||
fn join_paths_windows() {
|
||||
use crate::ffi::OsStr;
|
||||
|
||||
fn test_eq(input: &[&str], output: &str) -> bool {
|
||||
&*join_paths(input.iter().cloned()).unwrap() == OsStr::new(output)
|
||||
}
|
||||
|
||||
assert!(test_eq(&[], ""));
|
||||
assert!(test_eq(&[r"c:\windows", r"c:\"], r"c:\windows;c:\"));
|
||||
assert!(test_eq(&["", r"c:\windows", "", "", r"c:\", ""], r";c:\windows;;;c:\;"));
|
||||
assert!(test_eq(&[r"c:\te;st", r"c:\"], r#""c:\te;st";c:\"#));
|
||||
assert!(join_paths([r#"c:\te"st"#].iter().cloned()).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn args_debug() {
|
||||
assert_eq!(
|
||||
format!("Args {{ inner: {:?} }}", args().collect::<Vec<_>>()),
|
||||
format!("{:?}", args())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn args_os_debug() {
|
||||
assert_eq!(
|
||||
format!("ArgsOs {{ inner: {:?} }}", args_os().collect::<Vec<_>>()),
|
||||
format!("{:?}", args_os())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vars_debug() {
|
||||
assert_eq!(
|
||||
format!("Vars {{ inner: {:?} }}", vars().collect::<Vec<_>>()),
|
||||
format!("{:?}", vars())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vars_os_debug() {
|
||||
assert_eq!(
|
||||
format!("VarsOs {{ inner: {:?} }}", vars_os().collect::<Vec<_>>()),
|
||||
format!("{:?}", vars_os())
|
||||
);
|
||||
}
|
@ -1,9 +1,6 @@
|
||||
#![doc = include_str!("../../core/src/error.md")]
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::error::Error;
|
||||
#[unstable(feature = "error_generic_member_access", issue = "99301")]
|
||||
|
@ -4,9 +4,6 @@
|
||||
//!
|
||||
//! Mathematically significant numbers are provided in the `consts` sub-module.
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[unstable(feature = "f128", issue = "116909")]
|
||||
pub use core::f128::consts;
|
||||
|
||||
|
@ -4,9 +4,6 @@
|
||||
//!
|
||||
//! Mathematically significant numbers are provided in the `consts` sub-module.
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[unstable(feature = "f16", issue = "116909")]
|
||||
pub use core::f16::consts;
|
||||
|
||||
|
@ -12,9 +12,6 @@
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use core::f32::{
|
||||
|
@ -12,9 +12,6 @@
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
pub use core::f64::{
|
||||
|
@ -530,6 +530,8 @@ pub use core::option;
|
||||
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")]
|
||||
|
@ -372,18 +372,3 @@ macro_rules! dbg {
|
||||
($($crate::dbg!($val)),+,)
|
||||
};
|
||||
}
|
||||
|
||||
/// Verify that floats are within a tolerance of each other, 1.0e-6 by default.
|
||||
#[cfg(test)]
|
||||
macro_rules! assert_approx_eq {
|
||||
($a:expr, $b:expr) => {{ assert_approx_eq!($a, $b, 1.0e-6) }};
|
||||
($a:expr, $b:expr, $lim:expr) => {{
|
||||
let (a, b) = (&$a, &$b);
|
||||
let diff = (*a - *b).abs();
|
||||
assert!(
|
||||
diff < $lim,
|
||||
"{a:?} is not approximately equal to {b:?} (threshold {lim:?}, difference {diff:?})",
|
||||
lim = $lim
|
||||
);
|
||||
}};
|
||||
}
|
||||
|
@ -6,9 +6,6 @@
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[stable(feature = "int_error_matching", since = "1.55.0")]
|
||||
pub use core::num::IntErrorKind;
|
||||
#[stable(feature = "generic_nonzero", since = "1.79.0")]
|
||||
@ -29,28 +26,3 @@ pub use core::num::{FpCategory, ParseFloatError, ParseIntError, TryFromIntError}
|
||||
pub use core::num::{NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize};
|
||||
#[stable(feature = "nonzero", since = "1.28.0")]
|
||||
pub use core::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize};
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::fmt;
|
||||
#[cfg(test)]
|
||||
use crate::ops::{Add, Div, Mul, Rem, Sub};
|
||||
|
||||
/// Helper function for testing numeric operations
|
||||
#[cfg(test)]
|
||||
pub fn test_num<T>(ten: T, two: T)
|
||||
where
|
||||
T: PartialEq
|
||||
+ Add<Output = T>
|
||||
+ Sub<Output = T>
|
||||
+ Mul<Output = T>
|
||||
+ Div<Output = T>
|
||||
+ Rem<Output = T>
|
||||
+ fmt::Debug
|
||||
+ Copy,
|
||||
{
|
||||
assert_eq!(ten.add(two), ten + two);
|
||||
assert_eq!(ten.sub(two), ten - two);
|
||||
assert_eq!(ten.mul(two), ten * two);
|
||||
assert_eq!(ten.div(two), ten / two);
|
||||
assert_eq!(ten.rem(two), ten % two);
|
||||
}
|
||||
|
@ -529,6 +529,3 @@ pub fn get_backtrace_style() -> Option<BacktraceStyle> {
|
||||
Err(new) => BacktraceStyle::from_u8(new),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
@ -67,9 +67,6 @@
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use core::clone::CloneToUninit;
|
||||
|
||||
use crate::borrow::{Borrow, Cow};
|
||||
|
@ -1,6 +1,3 @@
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use crate::fmt;
|
||||
// FIXME(nonpoison_mutex,nonpoison_condvar): switch to nonpoison versions once they are available
|
||||
use crate::sync::{Condvar, Mutex};
|
||||
|
@ -350,6 +350,3 @@ unsafe impl<T: Sync + Send, F: Send> Sync for LazyLock<T, F> {}
|
||||
impl<T: RefUnwindSafe + UnwindSafe, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> {}
|
||||
#[stable(feature = "lazy_cell", since = "1.80.0")]
|
||||
impl<T: UnwindSafe, F: UnwindSafe> UnwindSafe for LazyLock<T, F> {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
@ -137,12 +137,6 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))]
|
||||
mod tests;
|
||||
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))]
|
||||
mod sync_tests;
|
||||
|
||||
// MPSC channels are built as a wrapper around MPMC channels, which
|
||||
// were ported from the `crossbeam-channel` crate. MPMC channels are
|
||||
// not exposed publicly, but if you are curious about the implementation,
|
||||
@ -737,9 +731,10 @@ impl<T> SyncSender<T> {
|
||||
// Attempts to send for a value on this receiver, returning an error if the
|
||||
// corresponding channel has hung up, or if it waits more than `timeout`.
|
||||
//
|
||||
// This method is currently private and only used for tests.
|
||||
#[allow(unused)]
|
||||
fn send_timeout(&self, t: T, timeout: Duration) -> Result<(), mpmc::SendTimeoutError<T>> {
|
||||
// This method is currently only used for tests.
|
||||
#[unstable(issue = "none", feature = "std_internals")]
|
||||
#[doc(hidden)]
|
||||
pub fn send_timeout(&self, t: T, timeout: Duration) -> Result<(), mpmc::SendTimeoutError<T>> {
|
||||
self.inner.send_timeout(t, timeout)
|
||||
}
|
||||
}
|
@ -681,6 +681,3 @@ unsafe impl<#[may_dangle] T> Drop for OnceLock<T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
@ -1,6 +1,3 @@
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use crate::fmt;
|
||||
use crate::sync::poison::{self, LockResult, MutexGuard, PoisonError, mutex};
|
||||
use crate::sys::sync as sys;
|
||||
|
@ -1,6 +1,3 @@
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))]
|
||||
mod tests;
|
||||
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::fmt;
|
||||
use crate::marker::PhantomData;
|
||||
|
@ -3,9 +3,6 @@
|
||||
//! This primitive is meant to be used to run one-time initialization. An
|
||||
//! example use case would be for initializing an FFI library.
|
||||
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))]
|
||||
mod tests;
|
||||
|
||||
use crate::fmt;
|
||||
use crate::panic::{RefUnwindSafe, UnwindSafe};
|
||||
use crate::sys::sync as sys;
|
||||
|
@ -1,6 +1,3 @@
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))]
|
||||
mod tests;
|
||||
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::fmt;
|
||||
use crate::marker::PhantomData;
|
||||
|
@ -1,6 +1,3 @@
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))]
|
||||
mod tests;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
use crate::cell::UnsafeCell;
|
||||
@ -324,7 +321,10 @@ impl<T: ?Sized> ReentrantLock<T> {
|
||||
/// Otherwise, an RAII guard is returned.
|
||||
///
|
||||
/// This function does not block.
|
||||
pub(crate) fn try_lock(&self) -> Option<ReentrantLockGuard<'_, T>> {
|
||||
// FIXME maybe make it a public part of the API?
|
||||
#[unstable(issue = "none", feature = "std_internals")]
|
||||
#[doc(hidden)]
|
||||
pub fn try_lock(&self) -> Option<ReentrantLockGuard<'_, T>> {
|
||||
let this_thread = current_id();
|
||||
// Safety: We only touch lock_count when we own the inner mutex.
|
||||
// Additionally, we only call `self.owner.set()` while holding
|
||||
|
@ -2,12 +2,6 @@
|
||||
|
||||
#![unstable(feature = "thread_local_internals", issue = "none")]
|
||||
|
||||
#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))]
|
||||
mod tests;
|
||||
|
||||
#[cfg(test)]
|
||||
mod dynamic_tests;
|
||||
|
||||
use crate::cell::{Cell, RefCell};
|
||||
use crate::error::Error;
|
||||
use crate::fmt;
|
||||
|
@ -31,9 +31,6 @@
|
||||
|
||||
#![stable(feature = "time", since = "1.3.0")]
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[stable(feature = "time", since = "1.3.0")]
|
||||
pub use core::time::Duration;
|
||||
#[stable(feature = "duration_checked_float", since = "1.66.0")]
|
||||
|
@ -1,163 +1,123 @@
|
||||
use std::env::*;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
|
||||
use rand::distributions::{Alphanumeric, DistString};
|
||||
use std::path::Path;
|
||||
|
||||
mod common;
|
||||
use std::thread;
|
||||
|
||||
use common::test_rng;
|
||||
#[test]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi", target_env = "sgx"), ignore)]
|
||||
fn test_self_exe_path() {
|
||||
let path = current_exe();
|
||||
assert!(path.is_ok());
|
||||
let path = path.unwrap();
|
||||
|
||||
#[track_caller]
|
||||
fn make_rand_name() -> OsString {
|
||||
let n = format!("TEST{}", Alphanumeric.sample_string(&mut test_rng(), 10));
|
||||
let n = OsString::from(n);
|
||||
assert!(var_os(&n).is_none());
|
||||
n
|
||||
}
|
||||
|
||||
fn eq(a: Option<OsString>, b: Option<&str>) {
|
||||
assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s));
|
||||
// Hard to test this function
|
||||
assert!(path.is_absolute());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_var() {
|
||||
let n = make_rand_name();
|
||||
set_var(&n, "VALUE");
|
||||
eq(var_os(&n), Some("VALUE"));
|
||||
fn test() {
|
||||
assert!((!Path::new("test-path").is_absolute()));
|
||||
|
||||
#[cfg(not(target_env = "sgx"))]
|
||||
current_dir().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_remove_var() {
|
||||
let n = make_rand_name();
|
||||
set_var(&n, "VALUE");
|
||||
remove_var(&n);
|
||||
eq(var_os(&n), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_var_overwrite() {
|
||||
let n = make_rand_name();
|
||||
set_var(&n, "1");
|
||||
set_var(&n, "2");
|
||||
eq(var_os(&n), Some("2"));
|
||||
set_var(&n, "");
|
||||
eq(var_os(&n), Some(""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
fn test_var_big() {
|
||||
let mut s = "".to_string();
|
||||
let mut i = 0;
|
||||
while i < 100 {
|
||||
s.push_str("aaaaaaaaaa");
|
||||
i += 1;
|
||||
}
|
||||
let n = make_rand_name();
|
||||
set_var(&n, &s);
|
||||
eq(var_os(&n), Some(&s));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
fn test_env_set_get_huge() {
|
||||
let n = make_rand_name();
|
||||
let s = "x".repeat(10000);
|
||||
set_var(&n, &s);
|
||||
eq(var_os(&n), Some(&s));
|
||||
remove_var(&n);
|
||||
eq(var_os(&n), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_env_set_var() {
|
||||
let n = make_rand_name();
|
||||
|
||||
let mut e = vars_os();
|
||||
set_var(&n, "VALUE");
|
||||
assert!(!e.any(|(k, v)| { &*k == &*n && &*v == "VALUE" }));
|
||||
|
||||
assert!(vars_os().any(|(k, v)| { &*k == &*n && &*v == "VALUE" }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(not(any(unix, windows)), ignore, allow(unused))]
|
||||
#[allow(deprecated)]
|
||||
fn env_home_dir() {
|
||||
#[cfg(windows)]
|
||||
fn split_paths_windows() {
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn var_to_os_string(var: Result<String, VarError>) -> Option<OsString> {
|
||||
match var {
|
||||
Ok(var) => Some(OsString::from(var)),
|
||||
Err(VarError::NotUnicode(var)) => Some(var),
|
||||
_ => None,
|
||||
}
|
||||
fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
|
||||
split_paths(unparsed).collect::<Vec<_>>()
|
||||
== parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(unix)] {
|
||||
let oldhome = var_to_os_string(var("HOME"));
|
||||
assert!(check_parse("", &mut [""]));
|
||||
assert!(check_parse(r#""""#, &mut [""]));
|
||||
assert!(check_parse(";;", &mut ["", "", ""]));
|
||||
assert!(check_parse(r"c:\", &mut [r"c:\"]));
|
||||
assert!(check_parse(r"c:\;", &mut [r"c:\", ""]));
|
||||
assert!(check_parse(r"c:\;c:\Program Files\", &mut [r"c:\", r"c:\Program Files\"]));
|
||||
assert!(check_parse(r#"c:\;c:\"foo"\"#, &mut [r"c:\", r"c:\foo\"]));
|
||||
assert!(check_parse(r#"c:\;c:\"foo;bar"\;c:\baz"#, &mut [r"c:\", r"c:\foo;bar\", r"c:\baz"]));
|
||||
}
|
||||
|
||||
set_var("HOME", "/home/MountainView");
|
||||
assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn split_paths_unix() {
|
||||
use std::path::PathBuf;
|
||||
|
||||
remove_var("HOME");
|
||||
if cfg!(target_os = "android") {
|
||||
assert!(home_dir().is_none());
|
||||
} else {
|
||||
// When HOME is not set, some platforms return `None`,
|
||||
// but others return `Some` with a default.
|
||||
// Just check that it is not "/home/MountainView".
|
||||
assert_ne!(home_dir(), Some(PathBuf::from("/home/MountainView")));
|
||||
}
|
||||
|
||||
if let Some(oldhome) = oldhome { set_var("HOME", oldhome); }
|
||||
} else if #[cfg(windows)] {
|
||||
let oldhome = var_to_os_string(var("HOME"));
|
||||
let olduserprofile = var_to_os_string(var("USERPROFILE"));
|
||||
|
||||
remove_var("HOME");
|
||||
remove_var("USERPROFILE");
|
||||
|
||||
assert!(home_dir().is_some());
|
||||
|
||||
set_var("HOME", "/home/PaloAlto");
|
||||
assert_ne!(home_dir(), Some(PathBuf::from("/home/PaloAlto")), "HOME must not be used");
|
||||
|
||||
set_var("USERPROFILE", "/home/MountainView");
|
||||
assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
|
||||
|
||||
remove_var("HOME");
|
||||
|
||||
assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
|
||||
|
||||
set_var("USERPROFILE", "");
|
||||
assert_ne!(home_dir(), Some(PathBuf::from("")), "Empty USERPROFILE must be ignored");
|
||||
|
||||
remove_var("USERPROFILE");
|
||||
|
||||
if let Some(oldhome) = oldhome { set_var("HOME", oldhome); }
|
||||
if let Some(olduserprofile) = olduserprofile { set_var("USERPROFILE", olduserprofile); }
|
||||
}
|
||||
fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
|
||||
split_paths(unparsed).collect::<Vec<_>>()
|
||||
== parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
assert!(check_parse("", &mut [""]));
|
||||
assert!(check_parse("::", &mut ["", "", ""]));
|
||||
assert!(check_parse("/", &mut ["/"]));
|
||||
assert!(check_parse("/:", &mut ["/", ""]));
|
||||
assert!(check_parse("/:/usr/local", &mut ["/", "/usr/local"]));
|
||||
}
|
||||
|
||||
#[test] // miri shouldn't detect any data race in this fn
|
||||
#[cfg_attr(any(not(miri), target_os = "emscripten"), ignore)]
|
||||
fn test_env_get_set_multithreaded() {
|
||||
let getter = thread::spawn(|| {
|
||||
for _ in 0..100 {
|
||||
let _ = var_os("foo");
|
||||
}
|
||||
});
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn join_paths_unix() {
|
||||
use std::ffi::OsStr;
|
||||
|
||||
let setter = thread::spawn(|| {
|
||||
for _ in 0..100 {
|
||||
set_var("foo", "bar");
|
||||
}
|
||||
});
|
||||
fn test_eq(input: &[&str], output: &str) -> bool {
|
||||
&*join_paths(input.iter().cloned()).unwrap() == OsStr::new(output)
|
||||
}
|
||||
|
||||
let _ = getter.join();
|
||||
let _ = setter.join();
|
||||
assert!(test_eq(&[], ""));
|
||||
assert!(test_eq(&["/bin", "/usr/bin", "/usr/local/bin"], "/bin:/usr/bin:/usr/local/bin"));
|
||||
assert!(test_eq(&["", "/bin", "", "", "/usr/bin", ""], ":/bin:::/usr/bin:"));
|
||||
assert!(join_paths(["/te:st"].iter().cloned()).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(windows)]
|
||||
fn join_paths_windows() {
|
||||
use std::ffi::OsStr;
|
||||
|
||||
fn test_eq(input: &[&str], output: &str) -> bool {
|
||||
&*join_paths(input.iter().cloned()).unwrap() == OsStr::new(output)
|
||||
}
|
||||
|
||||
assert!(test_eq(&[], ""));
|
||||
assert!(test_eq(&[r"c:\windows", r"c:\"], r"c:\windows;c:\"));
|
||||
assert!(test_eq(&["", r"c:\windows", "", "", r"c:\", ""], r";c:\windows;;;c:\;"));
|
||||
assert!(test_eq(&[r"c:\te;st", r"c:\"], r#""c:\te;st";c:\"#));
|
||||
assert!(join_paths([r#"c:\te"st"#].iter().cloned()).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn args_debug() {
|
||||
assert_eq!(
|
||||
format!("Args {{ inner: {:?} }}", args().collect::<Vec<_>>()),
|
||||
format!("{:?}", args())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn args_os_debug() {
|
||||
assert_eq!(
|
||||
format!("ArgsOs {{ inner: {:?} }}", args_os().collect::<Vec<_>>()),
|
||||
format!("{:?}", args_os())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vars_debug() {
|
||||
assert_eq!(
|
||||
format!("Vars {{ inner: {:?} }}", vars().collect::<Vec<_>>()),
|
||||
format!("{:?}", vars())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vars_os_debug() {
|
||||
assert_eq!(
|
||||
format!("VarsOs {{ inner: {:?} }}", vars_os().collect::<Vec<_>>()),
|
||||
format!("{:?}", vars_os())
|
||||
);
|
||||
}
|
||||
|
166
library/std/tests/env_modify.rs
Normal file
166
library/std/tests/env_modify.rs
Normal file
@ -0,0 +1,166 @@
|
||||
// These tests are in a separate integration test as they modify the environment,
|
||||
// and would otherwise cause some other tests to fail.
|
||||
|
||||
use std::env::*;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
|
||||
use rand::distributions::{Alphanumeric, DistString};
|
||||
|
||||
mod common;
|
||||
use std::thread;
|
||||
|
||||
use common::test_rng;
|
||||
|
||||
#[track_caller]
|
||||
fn make_rand_name() -> OsString {
|
||||
let n = format!("TEST{}", Alphanumeric.sample_string(&mut test_rng(), 10));
|
||||
let n = OsString::from(n);
|
||||
assert!(var_os(&n).is_none());
|
||||
n
|
||||
}
|
||||
|
||||
fn eq(a: Option<OsString>, b: Option<&str>) {
|
||||
assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_var() {
|
||||
let n = make_rand_name();
|
||||
set_var(&n, "VALUE");
|
||||
eq(var_os(&n), Some("VALUE"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_remove_var() {
|
||||
let n = make_rand_name();
|
||||
set_var(&n, "VALUE");
|
||||
remove_var(&n);
|
||||
eq(var_os(&n), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_var_overwrite() {
|
||||
let n = make_rand_name();
|
||||
set_var(&n, "1");
|
||||
set_var(&n, "2");
|
||||
eq(var_os(&n), Some("2"));
|
||||
set_var(&n, "");
|
||||
eq(var_os(&n), Some(""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
fn test_var_big() {
|
||||
let mut s = "".to_string();
|
||||
let mut i = 0;
|
||||
while i < 100 {
|
||||
s.push_str("aaaaaaaaaa");
|
||||
i += 1;
|
||||
}
|
||||
let n = make_rand_name();
|
||||
set_var(&n, &s);
|
||||
eq(var_os(&n), Some(&s));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_os = "emscripten", ignore)]
|
||||
fn test_env_set_get_huge() {
|
||||
let n = make_rand_name();
|
||||
let s = "x".repeat(10000);
|
||||
set_var(&n, &s);
|
||||
eq(var_os(&n), Some(&s));
|
||||
remove_var(&n);
|
||||
eq(var_os(&n), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_env_set_var() {
|
||||
let n = make_rand_name();
|
||||
|
||||
let mut e = vars_os();
|
||||
set_var(&n, "VALUE");
|
||||
assert!(!e.any(|(k, v)| { &*k == &*n && &*v == "VALUE" }));
|
||||
|
||||
assert!(vars_os().any(|(k, v)| { &*k == &*n && &*v == "VALUE" }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(not(any(unix, windows)), ignore, allow(unused))]
|
||||
#[allow(deprecated)]
|
||||
fn env_home_dir() {
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn var_to_os_string(var: Result<String, VarError>) -> Option<OsString> {
|
||||
match var {
|
||||
Ok(var) => Some(OsString::from(var)),
|
||||
Err(VarError::NotUnicode(var)) => Some(var),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(unix)] {
|
||||
let oldhome = var_to_os_string(var("HOME"));
|
||||
|
||||
set_var("HOME", "/home/MountainView");
|
||||
assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
|
||||
|
||||
remove_var("HOME");
|
||||
if cfg!(target_os = "android") {
|
||||
assert!(home_dir().is_none());
|
||||
} else {
|
||||
// When HOME is not set, some platforms return `None`,
|
||||
// but others return `Some` with a default.
|
||||
// Just check that it is not "/home/MountainView".
|
||||
assert_ne!(home_dir(), Some(PathBuf::from("/home/MountainView")));
|
||||
}
|
||||
|
||||
if let Some(oldhome) = oldhome { set_var("HOME", oldhome); }
|
||||
} else if #[cfg(windows)] {
|
||||
let oldhome = var_to_os_string(var("HOME"));
|
||||
let olduserprofile = var_to_os_string(var("USERPROFILE"));
|
||||
|
||||
remove_var("HOME");
|
||||
remove_var("USERPROFILE");
|
||||
|
||||
assert!(home_dir().is_some());
|
||||
|
||||
set_var("HOME", "/home/PaloAlto");
|
||||
assert_ne!(home_dir(), Some(PathBuf::from("/home/PaloAlto")), "HOME must not be used");
|
||||
|
||||
set_var("USERPROFILE", "/home/MountainView");
|
||||
assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
|
||||
|
||||
remove_var("HOME");
|
||||
|
||||
assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
|
||||
|
||||
set_var("USERPROFILE", "");
|
||||
assert_ne!(home_dir(), Some(PathBuf::from("")), "Empty USERPROFILE must be ignored");
|
||||
|
||||
remove_var("USERPROFILE");
|
||||
|
||||
if let Some(oldhome) = oldhome { set_var("HOME", oldhome); }
|
||||
if let Some(olduserprofile) = olduserprofile { set_var("USERPROFILE", olduserprofile); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test] // miri shouldn't detect any data race in this fn
|
||||
#[cfg_attr(any(not(miri), target_os = "emscripten"), ignore)]
|
||||
fn test_env_get_set_multithreaded() {
|
||||
let getter = thread::spawn(|| {
|
||||
for _ in 0..100 {
|
||||
let _ = var_os("foo");
|
||||
}
|
||||
});
|
||||
|
||||
let setter = thread::spawn(|| {
|
||||
for _ in 0..100 {
|
||||
set_var("foo", "bar");
|
||||
}
|
||||
});
|
||||
|
||||
let _ = getter.join();
|
||||
let _ = setter.join();
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
use core::error::Request;
|
||||
#![feature(error_generic_member_access, error_reporter)]
|
||||
|
||||
use super::Error;
|
||||
use crate::fmt;
|
||||
use std::backtrace::Backtrace;
|
||||
use std::error::{Error, Report, Request};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct A;
|
||||
@ -38,9 +39,6 @@ fn downcasting() {
|
||||
}
|
||||
}
|
||||
|
||||
use crate::backtrace::Backtrace;
|
||||
use crate::error::Report;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SuperError {
|
||||
source: SuperErrorSideKick,
|
@ -1,11 +1,11 @@
|
||||
// FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy
|
||||
#![cfg(reliable_f128)]
|
||||
|
||||
use crate::f128::consts;
|
||||
use crate::num::FpCategory as Fp;
|
||||
use std::f128::consts;
|
||||
use std::num::FpCategory as Fp;
|
||||
#[cfg(reliable_f128_math)]
|
||||
use crate::ops::Rem;
|
||||
use crate::ops::{Add, Div, Mul, Sub};
|
||||
use std::ops::Rem;
|
||||
use std::ops::{Add, Div, Mul, Sub};
|
||||
|
||||
// Note these tolerances make sense around zero, but not for more extreme exponents.
|
||||
|
||||
@ -762,8 +762,6 @@ fn test_ln_gamma() {
|
||||
|
||||
#[test]
|
||||
fn test_real_consts() {
|
||||
use super::consts;
|
||||
|
||||
let pi: f128 = consts::PI;
|
||||
let frac_pi_2: f128 = consts::FRAC_PI_2;
|
||||
let frac_pi_3: f128 = consts::FRAC_PI_3;
|
@ -1,8 +1,8 @@
|
||||
// FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy
|
||||
#![cfg(reliable_f16)]
|
||||
|
||||
use crate::f16::consts;
|
||||
use crate::num::{FpCategory as Fp, *};
|
||||
use std::f16::consts;
|
||||
use std::num::FpCategory as Fp;
|
||||
|
||||
/// Tolerance for results on the order of 10.0e-2
|
||||
#[allow(unused)]
|
||||
@ -54,7 +54,7 @@ macro_rules! assert_f16_biteq {
|
||||
|
||||
#[test]
|
||||
fn test_num_f16() {
|
||||
test_num(10f16, 2f16);
|
||||
crate::test_num(10f16, 2f16);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -734,7 +734,6 @@ fn test_ln_gamma() {
|
||||
#[test]
|
||||
fn test_real_consts() {
|
||||
// FIXME(f16_f128): add math tests when available
|
||||
use super::consts;
|
||||
|
||||
let pi: f16 = consts::PI;
|
||||
let frac_pi_2: f16 = consts::FRAC_PI_2;
|
@ -1,5 +1,5 @@
|
||||
use crate::f32::consts;
|
||||
use crate::num::{FpCategory as Fp, *};
|
||||
use std::f32::consts;
|
||||
use std::num::FpCategory as Fp;
|
||||
|
||||
/// Smallest number
|
||||
const TINY_BITS: u32 = 0x1;
|
||||
@ -35,7 +35,7 @@ macro_rules! assert_f32_biteq {
|
||||
|
||||
#[test]
|
||||
fn test_num_f32() {
|
||||
test_num(10f32, 2f32);
|
||||
crate::test_num(10f32, 2f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -700,8 +700,6 @@ fn test_ln_gamma() {
|
||||
|
||||
#[test]
|
||||
fn test_real_consts() {
|
||||
use super::consts;
|
||||
|
||||
let pi: f32 = consts::PI;
|
||||
let frac_pi_2: f32 = consts::FRAC_PI_2;
|
||||
let frac_pi_3: f32 = consts::FRAC_PI_3;
|
@ -1,5 +1,5 @@
|
||||
use crate::f64::consts;
|
||||
use crate::num::{FpCategory as Fp, *};
|
||||
use std::f64::consts;
|
||||
use std::num::FpCategory as Fp;
|
||||
|
||||
/// Smallest number
|
||||
const TINY_BITS: u64 = 0x1;
|
||||
@ -35,7 +35,7 @@ macro_rules! assert_f64_biteq {
|
||||
|
||||
#[test]
|
||||
fn test_num_f64() {
|
||||
test_num(10f64, 2f64);
|
||||
crate::test_num(10f64, 2f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -680,7 +680,6 @@ fn test_ln_gamma() {
|
||||
|
||||
#[test]
|
||||
fn test_real_consts() {
|
||||
use super::consts;
|
||||
let pi: f64 = consts::PI;
|
||||
let frac_pi_2: f64 = consts::FRAC_PI_2;
|
||||
let frac_pi_3: f64 = consts::FRAC_PI_3;
|
42
library/std/tests/floats/lib.rs
Normal file
42
library/std/tests/floats/lib.rs
Normal file
@ -0,0 +1,42 @@
|
||||
#![feature(f16, f128, float_gamma, float_minimum_maximum)]
|
||||
|
||||
use std::fmt;
|
||||
use std::ops::{Add, Div, Mul, Rem, Sub};
|
||||
|
||||
/// Verify that floats are within a tolerance of each other, 1.0e-6 by default.
|
||||
macro_rules! assert_approx_eq {
|
||||
($a:expr, $b:expr) => {{ assert_approx_eq!($a, $b, 1.0e-6) }};
|
||||
($a:expr, $b:expr, $lim:expr) => {{
|
||||
let (a, b) = (&$a, &$b);
|
||||
let diff = (*a - *b).abs();
|
||||
assert!(
|
||||
diff < $lim,
|
||||
"{a:?} is not approximately equal to {b:?} (threshold {lim:?}, difference {diff:?})",
|
||||
lim = $lim
|
||||
);
|
||||
}};
|
||||
}
|
||||
|
||||
/// Helper function for testing numeric operations
|
||||
pub fn test_num<T>(ten: T, two: T)
|
||||
where
|
||||
T: PartialEq
|
||||
+ Add<Output = T>
|
||||
+ Sub<Output = T>
|
||||
+ Mul<Output = T>
|
||||
+ Div<Output = T>
|
||||
+ Rem<Output = T>
|
||||
+ fmt::Debug
|
||||
+ Copy,
|
||||
{
|
||||
assert_eq!(ten.add(two), ten + two);
|
||||
assert_eq!(ten.sub(two), ten - two);
|
||||
assert_eq!(ten.mul(two), ten * two);
|
||||
assert_eq!(ten.div(two), ten / two);
|
||||
assert_eq!(ten.rem(two), ten % two);
|
||||
}
|
||||
|
||||
mod f128;
|
||||
mod f16;
|
||||
mod f32;
|
||||
mod f64;
|
@ -1,4 +1,4 @@
|
||||
use crate::ops::Mul;
|
||||
use std::ops::Mul;
|
||||
|
||||
#[test]
|
||||
fn test_saturating_add_uint() {
|
||||
@ -190,8 +190,8 @@ fn test_uint_to_str_overflow() {
|
||||
assert_eq!(u64_val.to_string(), "0");
|
||||
}
|
||||
|
||||
fn from_str<T: crate::str::FromStr>(t: &str) -> Option<T> {
|
||||
crate::str::FromStr::from_str(t).ok()
|
||||
fn from_str<T: std::str::FromStr>(t: &str) -> Option<T> {
|
||||
std::str::FromStr::from_str(t).ok()
|
||||
}
|
||||
|
||||
#[test]
|
@ -1,9 +1,9 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use crate::cell::RefCell;
|
||||
use crate::panic::{AssertUnwindSafe, UnwindSafe};
|
||||
use crate::rc::Rc;
|
||||
use crate::sync::{Arc, Mutex, RwLock};
|
||||
use std::cell::RefCell;
|
||||
use std::panic::{AssertUnwindSafe, UnwindSafe};
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
|
||||
struct Foo {
|
||||
a: i32,
|
@ -1,10 +1,19 @@
|
||||
use core::hint::black_box;
|
||||
#![feature(
|
||||
clone_to_uninit,
|
||||
path_add_extension,
|
||||
path_file_prefix,
|
||||
maybe_uninit_slice,
|
||||
os_string_pathbuf_leak
|
||||
)]
|
||||
|
||||
use super::*;
|
||||
use crate::collections::{BTreeSet, HashSet};
|
||||
use crate::hash::DefaultHasher;
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::ptr;
|
||||
use std::clone::CloneToUninit;
|
||||
use std::ffi::OsStr;
|
||||
use std::hash::{DefaultHasher, Hash, Hasher};
|
||||
use std::mem::MaybeUninit;
|
||||
use std::path::*;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[allow(unknown_lints, unused_macro_rules)]
|
||||
macro_rules! t (
|
||||
@ -110,7 +119,7 @@ macro_rules! t (
|
||||
|
||||
#[test]
|
||||
fn into() {
|
||||
use crate::borrow::Cow;
|
||||
use std::borrow::Cow;
|
||||
|
||||
let static_path = Path::new("/home/foo");
|
||||
let static_cow_path: Cow<'static, Path> = static_path.into();
|
||||
@ -1525,7 +1534,7 @@ pub fn test_with_added_extension() {
|
||||
|
||||
#[test]
|
||||
fn test_eq_receivers() {
|
||||
use crate::borrow::Cow;
|
||||
use std::borrow::Cow;
|
||||
|
||||
let borrowed: &Path = Path::new("foo/bar");
|
||||
let mut owned: PathBuf = PathBuf::new();
|
||||
@ -1550,7 +1559,7 @@ fn test_eq_receivers() {
|
||||
|
||||
#[test]
|
||||
pub fn test_compare() {
|
||||
use crate::hash::{DefaultHasher, Hash, Hasher};
|
||||
use std::hash::{DefaultHasher, Hash, Hasher};
|
||||
|
||||
fn hash<T: Hash>(t: T) -> u64 {
|
||||
let mut s = DefaultHasher::new();
|
||||
@ -1867,12 +1876,12 @@ fn test_ord() {
|
||||
#[test]
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
fn test_unix_absolute() {
|
||||
use crate::path::absolute;
|
||||
use std::path::absolute;
|
||||
|
||||
assert!(absolute("").is_err());
|
||||
|
||||
let relative = "a/b";
|
||||
let mut expected = crate::env::current_dir().unwrap();
|
||||
let mut expected = std::env::current_dir().unwrap();
|
||||
expected.push(relative);
|
||||
assert_eq!(absolute(relative).unwrap().as_os_str(), expected.as_os_str());
|
||||
|
||||
@ -1888,7 +1897,7 @@ fn test_unix_absolute() {
|
||||
);
|
||||
|
||||
// Test leading `.` and `..` components
|
||||
let curdir = crate::env::current_dir().unwrap();
|
||||
let curdir = std::env::current_dir().unwrap();
|
||||
assert_eq!(absolute("./a").unwrap().as_os_str(), curdir.join("a").as_os_str());
|
||||
assert_eq!(absolute("../a").unwrap().as_os_str(), curdir.join("../a").as_os_str()); // return /pwd/../a
|
||||
}
|
||||
@ -1896,12 +1905,12 @@ fn test_unix_absolute() {
|
||||
#[test]
|
||||
#[cfg(windows)]
|
||||
fn test_windows_absolute() {
|
||||
use crate::path::absolute;
|
||||
use std::path::absolute;
|
||||
// An empty path is an error.
|
||||
assert!(absolute("").is_err());
|
||||
|
||||
let relative = r"a\b";
|
||||
let mut expected = crate::env::current_dir().unwrap();
|
||||
let mut expected = std::env::current_dir().unwrap();
|
||||
expected.push(relative);
|
||||
assert_eq!(absolute(relative).unwrap().as_os_str(), expected.as_os_str());
|
||||
|
||||
@ -1953,116 +1962,6 @@ fn test_extension_path_sep_alternate() {
|
||||
assert_eq!(path, Path::new("path/to/file.d\\test"));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
#[cfg_attr(miri, ignore)] // Miri isn't fast...
|
||||
fn bench_path_cmp_fast_path_buf_sort(b: &mut test::Bencher) {
|
||||
let prefix = "my/home";
|
||||
let mut paths: Vec<_> =
|
||||
(0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
|
||||
|
||||
paths.sort();
|
||||
|
||||
b.iter(|| {
|
||||
black_box(paths.as_mut_slice()).sort_unstable();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
#[cfg_attr(miri, ignore)] // Miri isn't fast...
|
||||
fn bench_path_cmp_fast_path_long(b: &mut test::Bencher) {
|
||||
let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
|
||||
let paths: Vec<_> =
|
||||
(0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
|
||||
|
||||
let mut set = BTreeSet::new();
|
||||
|
||||
paths.iter().for_each(|p| {
|
||||
set.insert(p.as_path());
|
||||
});
|
||||
|
||||
b.iter(|| {
|
||||
set.remove(paths[500].as_path());
|
||||
set.insert(paths[500].as_path());
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
#[cfg_attr(miri, ignore)] // Miri isn't fast...
|
||||
fn bench_path_cmp_fast_path_short(b: &mut test::Bencher) {
|
||||
let prefix = "my/home";
|
||||
let paths: Vec<_> =
|
||||
(0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
|
||||
|
||||
let mut set = BTreeSet::new();
|
||||
|
||||
paths.iter().for_each(|p| {
|
||||
set.insert(p.as_path());
|
||||
});
|
||||
|
||||
b.iter(|| {
|
||||
set.remove(paths[500].as_path());
|
||||
set.insert(paths[500].as_path());
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
#[cfg_attr(miri, ignore)] // Miri isn't fast...
|
||||
fn bench_path_hashset(b: &mut test::Bencher) {
|
||||
let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
|
||||
let paths: Vec<_> =
|
||||
(0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
|
||||
|
||||
let mut set = HashSet::new();
|
||||
|
||||
paths.iter().for_each(|p| {
|
||||
set.insert(p.as_path());
|
||||
});
|
||||
|
||||
b.iter(|| {
|
||||
set.remove(paths[500].as_path());
|
||||
set.insert(black_box(paths[500].as_path()))
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
#[cfg_attr(miri, ignore)] // Miri isn't fast...
|
||||
fn bench_path_hashset_miss(b: &mut test::Bencher) {
|
||||
let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
|
||||
let paths: Vec<_> =
|
||||
(0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
|
||||
|
||||
let mut set = HashSet::new();
|
||||
|
||||
paths.iter().for_each(|p| {
|
||||
set.insert(p.as_path());
|
||||
});
|
||||
|
||||
let probe = PathBuf::from(prefix).join("other");
|
||||
|
||||
b.iter(|| set.remove(black_box(probe.as_path())));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_hash_path_short(b: &mut test::Bencher) {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
let path = Path::new("explorer.exe");
|
||||
|
||||
b.iter(|| black_box(path).hash(&mut hasher));
|
||||
|
||||
black_box(hasher.finish());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_hash_path_long(b: &mut test::Bencher) {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
let path =
|
||||
Path::new("/aaaaa/aaaaaa/./../aaaaaaaa/bbbbbbbbbbbbb/ccccccccccc/ddddddddd/eeeeeee.fff");
|
||||
|
||||
b.iter(|| black_box(path).hash(&mut hasher));
|
||||
|
||||
black_box(hasher.finish());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clone_to_uninit() {
|
||||
let a = Path::new("hello.txt");
|
@ -1,6 +1,6 @@
|
||||
use crate::sync::mpsc::{TryRecvError, channel};
|
||||
use crate::sync::{Arc, Barrier};
|
||||
use crate::thread;
|
||||
use std::sync::mpsc::{TryRecvError, channel};
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::thread;
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
@ -1,8 +1,8 @@
|
||||
use crate::sync::atomic::{AtomicBool, Ordering};
|
||||
use crate::sync::mpsc::channel;
|
||||
use crate::sync::{Arc, Condvar, Mutex};
|
||||
use crate::thread;
|
||||
use crate::time::Duration;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::mpsc::channel;
|
||||
use std::sync::{Arc, Condvar, Mutex};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
#[test]
|
||||
fn smoke() {
|
@ -1,8 +1,8 @@
|
||||
use crate::cell::LazyCell;
|
||||
use crate::sync::atomic::AtomicUsize;
|
||||
use crate::sync::atomic::Ordering::SeqCst;
|
||||
use crate::sync::{LazyLock, Mutex, OnceLock};
|
||||
use crate::{panic, thread};
|
||||
use std::cell::LazyCell;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering::SeqCst;
|
||||
use std::sync::{LazyLock, Mutex, OnceLock};
|
||||
use std::{panic, thread};
|
||||
|
||||
fn spawn_and_wait<R: Send + 'static>(f: impl FnOnce() -> R + Send + 'static) -> R {
|
||||
thread::spawn(f).join().unwrap()
|
||||
@ -149,7 +149,7 @@ fn is_sync_send() {
|
||||
#[should_panic = "has previously been poisoned"]
|
||||
fn lazy_force_mut_panic() {
|
||||
let mut lazy = LazyLock::<String>::new(|| panic!());
|
||||
crate::panic::catch_unwind(crate::panic::AssertUnwindSafe(|| {
|
||||
panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
let _ = LazyLock::force_mut(&mut lazy);
|
||||
}))
|
||||
.unwrap_err();
|
31
library/std/tests/sync/lib.rs
Normal file
31
library/std/tests/sync/lib.rs
Normal file
@ -0,0 +1,31 @@
|
||||
#![feature(lazy_get)]
|
||||
#![feature(mapped_lock_guards)]
|
||||
#![feature(mpmc_channel)]
|
||||
#![feature(once_cell_try)]
|
||||
#![feature(lock_value_accessors)]
|
||||
#![feature(reentrant_lock)]
|
||||
#![feature(rwlock_downgrade)]
|
||||
#![feature(std_internals)]
|
||||
#![allow(internal_features)]
|
||||
|
||||
mod barrier;
|
||||
mod condvar;
|
||||
mod lazy_lock;
|
||||
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))]
|
||||
mod mpmc;
|
||||
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))]
|
||||
mod mpsc;
|
||||
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))]
|
||||
mod mpsc_sync;
|
||||
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))]
|
||||
mod mutex;
|
||||
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))]
|
||||
mod once;
|
||||
mod once_lock;
|
||||
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))]
|
||||
mod reentrant_lock;
|
||||
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))]
|
||||
mod rwlock;
|
||||
|
||||
#[path = "../common/mod.rs"]
|
||||
mod common;
|
@ -1,5 +1,6 @@
|
||||
use super::*;
|
||||
use crate::{env, thread};
|
||||
use std::sync::mpmc::*;
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{env, thread};
|
||||
|
||||
pub fn stress_factor() -> usize {
|
||||
match env::var("RUST_TEST_STRESS") {
|
@ -1,5 +1,6 @@
|
||||
use super::*;
|
||||
use crate::{env, thread};
|
||||
use std::sync::mpsc::*;
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{env, thread};
|
||||
|
||||
pub fn stress_factor() -> usize {
|
||||
match env::var("RUST_TEST_STRESS") {
|
@ -1,7 +1,8 @@
|
||||
use super::*;
|
||||
use crate::rc::Rc;
|
||||
use crate::sync::mpmc::SendTimeoutError;
|
||||
use crate::{env, thread};
|
||||
use std::rc::Rc;
|
||||
use std::sync::mpmc::SendTimeoutError;
|
||||
use std::sync::mpsc::*;
|
||||
use std::time::Duration;
|
||||
use std::{env, thread};
|
||||
|
||||
pub fn stress_factor() -> usize {
|
||||
match env::var("RUST_TEST_STRESS") {
|
@ -1,10 +1,10 @@
|
||||
use crate::fmt::Debug;
|
||||
use crate::ops::FnMut;
|
||||
use crate::panic::{self, AssertUnwindSafe};
|
||||
use crate::sync::atomic::{AtomicUsize, Ordering};
|
||||
use crate::sync::mpsc::channel;
|
||||
use crate::sync::{Arc, Condvar, MappedMutexGuard, Mutex, MutexGuard, TryLockError};
|
||||
use crate::{hint, mem, thread};
|
||||
use std::fmt::Debug;
|
||||
use std::ops::FnMut;
|
||||
use std::panic::{self, AssertUnwindSafe};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::mpsc::channel;
|
||||
use std::sync::{Arc, Condvar, MappedMutexGuard, Mutex, MutexGuard, TryLockError};
|
||||
use std::{hint, mem, thread};
|
||||
|
||||
struct Packet<T>(Arc<(Mutex<T>, Condvar)>);
|
||||
|
@ -1,9 +1,9 @@
|
||||
use super::Once;
|
||||
use crate::sync::atomic::AtomicBool;
|
||||
use crate::sync::atomic::Ordering::Relaxed;
|
||||
use crate::sync::mpsc::channel;
|
||||
use crate::time::Duration;
|
||||
use crate::{panic, thread};
|
||||
use std::sync::Once;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::Ordering::Relaxed;
|
||||
use std::sync::mpsc::channel;
|
||||
use std::time::Duration;
|
||||
use std::{panic, thread};
|
||||
|
||||
#[test]
|
||||
fn smoke_once() {
|
@ -1,8 +1,8 @@
|
||||
use crate::sync::OnceLock;
|
||||
use crate::sync::atomic::AtomicUsize;
|
||||
use crate::sync::atomic::Ordering::SeqCst;
|
||||
use crate::sync::mpsc::channel;
|
||||
use crate::{panic, thread};
|
||||
use std::sync::OnceLock;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering::SeqCst;
|
||||
use std::sync::mpsc::channel;
|
||||
use std::{panic, thread};
|
||||
|
||||
fn spawn_and_wait<R: Send + 'static>(f: impl FnOnce() -> R + Send + 'static) -> R {
|
||||
thread::spawn(f).join().unwrap()
|
||||
@ -33,15 +33,6 @@ fn sync_once_cell_get_mut() {
|
||||
assert_eq!(c.get_mut(), Some(&mut 92));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sync_once_cell_get_unchecked() {
|
||||
let c = OnceLock::new();
|
||||
c.set(92).unwrap();
|
||||
unsafe {
|
||||
assert_eq!(c.get_unchecked(), &92);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
|
||||
fn sync_once_cell_drop() {
|
||||
@ -88,7 +79,6 @@ fn get_or_try_init() {
|
||||
|
||||
let res = panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() }));
|
||||
assert!(res.is_err());
|
||||
assert!(!cell.is_initialized());
|
||||
assert!(cell.get().is_none());
|
||||
|
||||
assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
|
||||
@ -174,7 +164,7 @@ fn sync_once_cell_does_not_leak_partially_constructed_boxes() {
|
||||
break;
|
||||
}
|
||||
#[cfg(target_env = "sgx")]
|
||||
crate::thread::yield_now();
|
||||
std::thread::yield_now();
|
||||
}
|
||||
});
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
use super::ReentrantLock;
|
||||
use crate::cell::RefCell;
|
||||
use crate::sync::Arc;
|
||||
use crate::thread;
|
||||
use std::cell::RefCell;
|
||||
use std::sync::{Arc, ReentrantLock};
|
||||
use std::thread;
|
||||
|
||||
#[test]
|
||||
fn smoke() {
|
@ -1,15 +1,15 @@
|
||||
use rand::Rng;
|
||||
|
||||
use crate::fmt::Debug;
|
||||
use crate::ops::FnMut;
|
||||
use crate::panic::{self, AssertUnwindSafe};
|
||||
use crate::sync::atomic::{AtomicUsize, Ordering};
|
||||
use crate::sync::mpsc::channel;
|
||||
use crate::sync::{
|
||||
use std::fmt::Debug;
|
||||
use std::ops::FnMut;
|
||||
use std::panic::{self, AssertUnwindSafe};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::mpsc::channel;
|
||||
use std::sync::{
|
||||
Arc, MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard, RwLockWriteGuard,
|
||||
TryLockError,
|
||||
};
|
||||
use crate::{hint, mem, thread};
|
||||
use std::{hint, mem, thread};
|
||||
|
||||
use rand::Rng;
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
struct NonCopy(i32);
|
||||
@ -57,7 +57,7 @@ fn frob() {
|
||||
let tx = tx.clone();
|
||||
let r = r.clone();
|
||||
thread::spawn(move || {
|
||||
let mut rng = crate::test_helpers::test_rng();
|
||||
let mut rng = crate::common::test_rng();
|
||||
for _ in 0..M {
|
||||
if rng.gen_bool(1.0 / (N as f64)) {
|
||||
drop(r.write().unwrap());
|
||||
@ -704,7 +704,7 @@ fn test_downgrade_atomic() {
|
||||
|
||||
// Wait for a good amount of time so that evil threads go to sleep.
|
||||
// Note: this is not strictly necessary...
|
||||
let eternity = crate::time::Duration::from_millis(42);
|
||||
let eternity = std::time::Duration::from_millis(42);
|
||||
thread::sleep(eternity);
|
||||
|
||||
// Once everyone is asleep, set the value to `NEW_VALUE`.
|
@ -1,6 +1,6 @@
|
||||
use crate::cell::RefCell;
|
||||
use crate::collections::HashMap;
|
||||
use crate::thread_local;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::thread_local;
|
||||
|
||||
#[test]
|
||||
fn smoke() {
|
4
library/std/tests/thread_local/lib.rs
Normal file
4
library/std/tests/thread_local/lib.rs
Normal file
@ -0,0 +1,4 @@
|
||||
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))]
|
||||
mod tests;
|
||||
|
||||
mod dynamic_tests;
|
@ -1,8 +1,8 @@
|
||||
use crate::cell::{Cell, UnsafeCell};
|
||||
use crate::sync::atomic::{AtomicU8, Ordering};
|
||||
use crate::sync::{Arc, Condvar, Mutex};
|
||||
use crate::thread::{self, Builder, LocalKey};
|
||||
use crate::thread_local;
|
||||
use std::cell::{Cell, UnsafeCell};
|
||||
use std::sync::atomic::{AtomicU8, Ordering};
|
||||
use std::sync::{Arc, Condvar, Mutex};
|
||||
use std::thread::{self, Builder, LocalKey};
|
||||
use std::thread_local;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
struct Signal(Arc<(Mutex<bool>, Condvar)>);
|
@ -1,9 +1,7 @@
|
||||
use core::fmt::Debug;
|
||||
#![feature(duration_constants)]
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use test::{Bencher, black_box};
|
||||
|
||||
use super::{Duration, Instant, SystemTime, UNIX_EPOCH};
|
||||
use std::fmt::Debug;
|
||||
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
|
||||
|
||||
macro_rules! assert_almost_eq {
|
||||
($a:expr, $b:expr) => {{
|
||||
@ -29,10 +27,10 @@ fn instant_monotonic() {
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn instant_monotonic_concurrent() -> crate::thread::Result<()> {
|
||||
fn instant_monotonic_concurrent() -> std::thread::Result<()> {
|
||||
let threads: Vec<_> = (0..8)
|
||||
.map(|_| {
|
||||
crate::thread::spawn(|| {
|
||||
std::thread::spawn(|| {
|
||||
let mut old = Instant::now();
|
||||
let count = if cfg!(miri) { 1_000 } else { 5_000_000 };
|
||||
for _ in 0..count {
|
||||
@ -229,46 +227,3 @@ fn big_math() {
|
||||
check(instant.checked_add(Duration::from_secs(100)), Instant::checked_sub);
|
||||
check(instant.checked_add(Duration::from_secs(i64::MAX as _)), Instant::checked_sub);
|
||||
}
|
||||
|
||||
macro_rules! bench_instant_threaded {
|
||||
($bench_name:ident, $thread_count:expr) => {
|
||||
#[bench]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn $bench_name(b: &mut Bencher) -> crate::thread::Result<()> {
|
||||
use crate::sync::Arc;
|
||||
use crate::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
let running = Arc::new(AtomicBool::new(true));
|
||||
|
||||
let threads: Vec<_> = (0..$thread_count)
|
||||
.map(|_| {
|
||||
let flag = Arc::clone(&running);
|
||||
crate::thread::spawn(move || {
|
||||
while flag.load(Ordering::Relaxed) {
|
||||
black_box(Instant::now());
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
b.iter(|| {
|
||||
let a = Instant::now();
|
||||
let b = Instant::now();
|
||||
assert!(b >= a);
|
||||
});
|
||||
|
||||
running.store(false, Ordering::Relaxed);
|
||||
|
||||
for t in threads {
|
||||
t.join()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bench_instant_threaded!(instant_contention_01_threads, 0);
|
||||
bench_instant_threaded!(instant_contention_02_threads, 1);
|
||||
bench_instant_threaded!(instant_contention_04_threads, 3);
|
||||
bench_instant_threaded!(instant_contention_08_threads, 7);
|
||||
bench_instant_threaded!(instant_contention_16_threads, 15);
|
@ -455,6 +455,7 @@ tool_check_step!(Rls { path: "src/tools/rls" });
|
||||
tool_check_step!(Rustfmt { path: "src/tools/rustfmt" });
|
||||
tool_check_step!(MiroptTestTools { path: "src/tools/miropt-test-tools" });
|
||||
tool_check_step!(TestFloatParse { path: "src/etc/test-float-parse" });
|
||||
tool_check_step!(FeaturesStatusDump { path: "src/tools/features-status-dump" });
|
||||
|
||||
tool_check_step!(Bootstrap { path: "src/bootstrap", default: false });
|
||||
|
||||
|
@ -311,3 +311,34 @@ impl Step for UnicodeTableGenerator {
|
||||
cmd.run(builder);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
|
||||
pub struct FeaturesStatusDump;
|
||||
|
||||
impl Step for FeaturesStatusDump {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/features-status-dump")
|
||||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(FeaturesStatusDump);
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
let mut cmd = builder.tool_cmd(Tool::FeaturesStatusDump);
|
||||
|
||||
cmd.arg("--library-path");
|
||||
cmd.arg(builder.src.join("library"));
|
||||
|
||||
cmd.arg("--compiler-path");
|
||||
cmd.arg(builder.src.join("compiler"));
|
||||
|
||||
cmd.arg("--output-path");
|
||||
cmd.arg(builder.out.join("features-status-dump.json"));
|
||||
|
||||
cmd.run(builder);
|
||||
}
|
||||
}
|
||||
|
@ -365,6 +365,7 @@ bootstrap_tool!(
|
||||
RustcPerfWrapper, "src/tools/rustc-perf-wrapper", "rustc-perf-wrapper";
|
||||
WasmComponentLd, "src/tools/wasm-component-ld", "wasm-component-ld", is_unstable_tool = true, allow_features = "min_specialization";
|
||||
UnicodeTableGenerator, "src/tools/unicode-table-generator", "unicode-table-generator";
|
||||
FeaturesStatusDump, "src/tools/features-status-dump", "features-status-dump";
|
||||
);
|
||||
|
||||
/// These are the submodules that are required for rustbook to work due to
|
||||
|
@ -938,6 +938,7 @@ impl<'a> Builder<'a> {
|
||||
check::Bootstrap,
|
||||
check::RunMakeSupport,
|
||||
check::Compiletest,
|
||||
check::FeaturesStatusDump,
|
||||
),
|
||||
Kind::Test => describe!(
|
||||
crate::core::build_steps::toolstate::ToolStateCheck,
|
||||
@ -1089,6 +1090,7 @@ impl<'a> Builder<'a> {
|
||||
run::GenerateWindowsSys,
|
||||
run::GenerateCompletions,
|
||||
run::UnicodeTableGenerator,
|
||||
run::FeaturesStatusDump,
|
||||
),
|
||||
Kind::Setup => {
|
||||
describe!(setup::Profile, setup::Hook, setup::Link, setup::Editor)
|
||||
|
9
src/doc/unstable-book/src/language-features/new-range.md
Normal file
9
src/doc/unstable-book/src/language-features/new-range.md
Normal file
@ -0,0 +1,9 @@
|
||||
# `new_range`
|
||||
|
||||
The tracking issue for this feature is: [#123741]
|
||||
|
||||
[#123741]: https://github.com/rust-lang/rust/issues/123741
|
||||
|
||||
---
|
||||
|
||||
Switch the syntaxes `a..`, `a..b`, and `a..=b` to resolve the new range types.
|
12
src/tools/features-status-dump/Cargo.toml
Normal file
12
src/tools/features-status-dump/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "features-status-dump"
|
||||
version = "0.1.0"
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = { version = "1", features = ["backtrace"] }
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
serde = { version = "1.0.125", features = [ "derive" ] }
|
||||
serde_json = "1.0.59"
|
||||
tidy = { path = "../tidy", features = ["build-metrics"] }
|
53
src/tools/features-status-dump/src/main.rs
Normal file
53
src/tools/features-status-dump/src/main.rs
Normal file
@ -0,0 +1,53 @@
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io::BufWriter;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use clap::Parser;
|
||||
use tidy::features::{Feature, collect_lang_features, collect_lib_features};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
struct Cli {
|
||||
/// Path to `library/` directory.
|
||||
#[arg(long)]
|
||||
library_path: PathBuf,
|
||||
/// Path to `compiler/` directory.
|
||||
#[arg(long)]
|
||||
compiler_path: PathBuf,
|
||||
/// Path to `output/` directory.
|
||||
#[arg(long)]
|
||||
output_path: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize)]
|
||||
struct FeaturesStatus {
|
||||
lang_features_status: HashMap<String, Feature>,
|
||||
lib_features_status: HashMap<String, Feature>,
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let Cli { compiler_path, library_path, output_path } = Cli::parse();
|
||||
|
||||
let lang_features_status = collect_lang_features(&compiler_path, &mut false);
|
||||
let lib_features_status = collect_lib_features(&library_path)
|
||||
.into_iter()
|
||||
.filter(|&(ref name, _)| !lang_features_status.contains_key(name))
|
||||
.collect();
|
||||
let features_status = FeaturesStatus { lang_features_status, lib_features_status };
|
||||
|
||||
let output_dir = output_path.parent().with_context(|| {
|
||||
format!("failed to get parent dir of output path `{}`", output_path.display())
|
||||
})?;
|
||||
std::fs::create_dir_all(output_dir).with_context(|| {
|
||||
format!("failed to create output directory at `{}`", output_dir.display())
|
||||
})?;
|
||||
|
||||
let output_file = File::create(&output_path).with_context(|| {
|
||||
format!("failed to create file at given output path `{}`", output_path.display())
|
||||
})?;
|
||||
let writer = BufWriter::new(output_file);
|
||||
serde_json::to_writer_pretty(writer, &features_status)
|
||||
.context("failed to write json output")?;
|
||||
Ok(())
|
||||
}
|
@ -12,11 +12,15 @@ miropt-test-tools = { path = "../miropt-test-tools" }
|
||||
walkdir = "2"
|
||||
ignore = "0.4.18"
|
||||
semver = "1.0"
|
||||
serde = { version = "1.0.125", features = ["derive"], optional = true }
|
||||
termcolor = "1.1.3"
|
||||
rustc-hash = "2.0.0"
|
||||
fluent-syntax = "0.11.1"
|
||||
similar = "2.5.0"
|
||||
|
||||
[features]
|
||||
build-metrics = ["dep:serde"]
|
||||
|
||||
[[bin]]
|
||||
name = "rust-tidy"
|
||||
path = "src/main.rs"
|
||||
|
@ -27,6 +27,7 @@ const FEATURE_GROUP_START_PREFIX: &str = "// feature-group-start";
|
||||
const FEATURE_GROUP_END_PREFIX: &str = "// feature-group-end";
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
#[cfg_attr(feature = "build-metrics", derive(serde::Serialize))]
|
||||
pub enum Status {
|
||||
Accepted,
|
||||
Removed,
|
||||
@ -45,6 +46,7 @@ impl fmt::Display for Status {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(feature = "build-metrics", derive(serde::Serialize))]
|
||||
pub struct Feature {
|
||||
pub level: Status,
|
||||
pub since: Option<Version>,
|
||||
|
@ -8,6 +8,7 @@ mod tests;
|
||||
pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[cfg_attr(feature = "build-metrics", derive(serde::Serialize))]
|
||||
pub enum Version {
|
||||
Explicit { parts: [u32; 3] },
|
||||
CurrentPlaceholder,
|
||||
|
@ -48,8 +48,9 @@ const EXCEPTION_PATHS: &[&str] = &[
|
||||
// we must use `#[cfg(windows)]` to conditionally compile the
|
||||
// correct `VaList` structure for windows.
|
||||
"library/core/src/ffi/va_list.rs",
|
||||
// We placed a linkage against Windows libraries here
|
||||
// core::ffi contains platform-specific type and linkage configuration
|
||||
"library/core/src/ffi/mod.rs",
|
||||
"library/core/src/ffi/primitives.rs",
|
||||
"library/std/src/sys", // Platform-specific code for std lives here.
|
||||
"library/std/src/os", // Platform-specific public interfaces
|
||||
// Temporary `std` exceptions
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Verify that debuginfo column numbers are 1-based byte offsets.
|
||||
//
|
||||
//@ ignore-windows
|
||||
//@ ignore-msvc
|
||||
//@ compile-flags: -C debuginfo=2
|
||||
|
||||
#[rustfmt::skip]
|
||||
|
@ -1,5 +1,5 @@
|
||||
//@ compile-flags: -C no-prepopulate-passes -C panic=abort -C force-unwind-tables=n
|
||||
//@ ignore-windows
|
||||
//@ ignore-windows: unwind tables are required for panics on Windows
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//@ compile-flags: -O
|
||||
//@ aux-build:thread_local_aux.rs
|
||||
//@ ignore-windows FIXME(#84933)
|
||||
//@ ignore-windows FIXME(#134939)
|
||||
//@ ignore-wasm globals are used instead of thread locals
|
||||
//@ ignore-emscripten globals are used instead of thread locals
|
||||
//@ ignore-android does not use #[thread_local]
|
||||
|
@ -2,6 +2,10 @@
|
||||
//@compile-flags: -Clink-dead-code=true --crate-type lib
|
||||
//@ only-x86_64
|
||||
//@ ignore-windows
|
||||
// The set of targets this crashes on is really fiddly, because it is deep in our ABI logic. It
|
||||
// crashes on x86_64-unknown-linux-gnu, and i686-pc-windows-msvc, but not on
|
||||
// x86_64-pc-windows-msvc. If you are trying to fix this crash, don't pay too much attention to the
|
||||
// directives.
|
||||
|
||||
#![feature(rust_cold_cc)]
|
||||
pub extern "rust-cold" fn foo(_: [usize; 3]) {}
|
||||
|
@ -19,16 +19,16 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
|
||||
scope 2 {
|
||||
debug x => _9;
|
||||
}
|
||||
scope 5 (inlined iter::range::<impl Iterator for RangeInclusive<u32>>::next) {
|
||||
scope 5 (inlined iter::range::<impl Iterator for std::ops::RangeInclusive<u32>>::next) {
|
||||
}
|
||||
}
|
||||
scope 3 (inlined RangeInclusive::<u32>::new) {
|
||||
scope 3 (inlined std::ops::RangeInclusive::<u32>::new) {
|
||||
}
|
||||
scope 4 (inlined <RangeInclusive<u32> as IntoIterator>::into_iter) {
|
||||
scope 4 (inlined <std::ops::RangeInclusive<u32> as IntoIterator>::into_iter) {
|
||||
}
|
||||
|
||||
bb0: {
|
||||
_4 = RangeInclusive::<u32> { start: copy _1, end: copy _2, exhausted: const false };
|
||||
_4 = std::ops::RangeInclusive::<u32> { start: copy _1, end: copy _2, exhausted: const false };
|
||||
StorageLive(_5);
|
||||
_5 = copy _4;
|
||||
goto -> bb1;
|
||||
@ -37,7 +37,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
|
||||
bb1: {
|
||||
StorageLive(_7);
|
||||
_6 = &mut _5;
|
||||
_7 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind unreachable];
|
||||
_7 = <std::ops::RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind unreachable];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
|
@ -19,16 +19,16 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
|
||||
scope 2 {
|
||||
debug x => _9;
|
||||
}
|
||||
scope 5 (inlined iter::range::<impl Iterator for RangeInclusive<u32>>::next) {
|
||||
scope 5 (inlined iter::range::<impl Iterator for std::ops::RangeInclusive<u32>>::next) {
|
||||
}
|
||||
}
|
||||
scope 3 (inlined RangeInclusive::<u32>::new) {
|
||||
scope 3 (inlined std::ops::RangeInclusive::<u32>::new) {
|
||||
}
|
||||
scope 4 (inlined <RangeInclusive<u32> as IntoIterator>::into_iter) {
|
||||
scope 4 (inlined <std::ops::RangeInclusive<u32> as IntoIterator>::into_iter) {
|
||||
}
|
||||
|
||||
bb0: {
|
||||
_4 = RangeInclusive::<u32> { start: copy _1, end: copy _2, exhausted: const false };
|
||||
_4 = std::ops::RangeInclusive::<u32> { start: copy _1, end: copy _2, exhausted: const false };
|
||||
StorageLive(_5);
|
||||
_5 = copy _4;
|
||||
goto -> bb1;
|
||||
@ -37,7 +37,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
|
||||
bb1: {
|
||||
StorageLive(_7);
|
||||
_6 = &mut _5;
|
||||
_7 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind: bb8];
|
||||
_7 = <std::ops::RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind: bb8];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
|
@ -1,13 +1,13 @@
|
||||
// MIR for `range_inclusive_iter_next` after PreCodegen
|
||||
|
||||
fn range_inclusive_iter_next(_1: &mut RangeInclusive<u32>) -> Option<u32> {
|
||||
fn range_inclusive_iter_next(_1: &mut std::ops::RangeInclusive<u32>) -> Option<u32> {
|
||||
debug it => _1;
|
||||
let mut _0: std::option::Option<u32>;
|
||||
scope 1 (inlined iter::range::<impl Iterator for RangeInclusive<u32>>::next) {
|
||||
scope 1 (inlined iter::range::<impl Iterator for std::ops::RangeInclusive<u32>>::next) {
|
||||
}
|
||||
|
||||
bb0: {
|
||||
_0 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind unreachable];
|
||||
_0 = <std::ops::RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
|
@ -1,13 +1,13 @@
|
||||
// MIR for `range_inclusive_iter_next` after PreCodegen
|
||||
|
||||
fn range_inclusive_iter_next(_1: &mut RangeInclusive<u32>) -> Option<u32> {
|
||||
fn range_inclusive_iter_next(_1: &mut std::ops::RangeInclusive<u32>) -> Option<u32> {
|
||||
debug it => _1;
|
||||
let mut _0: std::option::Option<u32>;
|
||||
scope 1 (inlined iter::range::<impl Iterator for RangeInclusive<u32>>::next) {
|
||||
scope 1 (inlined iter::range::<impl Iterator for std::ops::RangeInclusive<u32>>::next) {
|
||||
}
|
||||
|
||||
bb0: {
|
||||
_0 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind continue];
|
||||
_0 = <std::ops::RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind continue];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
|
@ -1,4 +1,4 @@
|
||||
//@ ignore-windows
|
||||
//@ ignore-windows different error message
|
||||
//@ revisions: edition2015 edition2024
|
||||
//@[edition2015]edition:2015
|
||||
//@[edition2015]check-fail
|
||||
|
@ -4,7 +4,6 @@
|
||||
//@ ignore-stage1
|
||||
//@ ignore-cross-compile
|
||||
//@ ignore-remote
|
||||
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![feature(assert_matches)]
|
||||
|
@ -5,7 +5,6 @@
|
||||
//@ ignore-stage1
|
||||
//@ ignore-cross-compile
|
||||
//@ ignore-remote
|
||||
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||
//@ edition: 2021
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
@ -4,7 +4,6 @@
|
||||
//@ ignore-stage1
|
||||
//@ ignore-cross-compile
|
||||
//@ ignore-remote
|
||||
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
//@ ignore-stage1
|
||||
//@ ignore-cross-compile
|
||||
//@ ignore-remote
|
||||
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
//@ ignore-stage1
|
||||
//@ ignore-cross-compile
|
||||
//@ ignore-remote
|
||||
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![feature(assert_matches)]
|
||||
|
@ -5,7 +5,6 @@
|
||||
//@ ignore-stage1
|
||||
//@ ignore-cross-compile
|
||||
//@ ignore-remote
|
||||
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||
//@ edition: 2021
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
@ -4,7 +4,6 @@
|
||||
//@ ignore-stage1
|
||||
//@ ignore-cross-compile
|
||||
//@ ignore-remote
|
||||
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||
//@ edition: 2021
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
@ -4,7 +4,6 @@
|
||||
//@ ignore-stage1
|
||||
//@ ignore-cross-compile
|
||||
//@ ignore-remote
|
||||
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||
//@ edition: 2021
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
@ -4,7 +4,6 @@
|
||||
//@ ignore-stage1
|
||||
//@ ignore-cross-compile
|
||||
//@ ignore-remote
|
||||
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||
//@ edition: 2021
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
@ -8,7 +8,6 @@
|
||||
//@ ignore-stage1
|
||||
//@ ignore-cross-compile
|
||||
//@ ignore-remote
|
||||
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![feature(assert_matches)]
|
||||
|
@ -4,7 +4,6 @@
|
||||
//@ ignore-stage1
|
||||
//@ ignore-cross-compile
|
||||
//@ ignore-remote
|
||||
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||
//@ edition: 2021
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
@ -4,7 +4,6 @@
|
||||
//@ ignore-stage1
|
||||
//@ ignore-cross-compile
|
||||
//@ ignore-remote
|
||||
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||
//@ edition: 2021
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
@ -4,7 +4,6 @@
|
||||
//@ ignore-stage1
|
||||
//@ ignore-cross-compile
|
||||
//@ ignore-remote
|
||||
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||
//@ edition: 2021
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
@ -4,7 +4,6 @@
|
||||
//@ ignore-stage1
|
||||
//@ ignore-cross-compile
|
||||
//@ ignore-remote
|
||||
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![feature(assert_matches)]
|
||||
|
@ -5,7 +5,6 @@
|
||||
//@ ignore-stage1
|
||||
//@ ignore-cross-compile
|
||||
//@ ignore-remote
|
||||
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
|
||||
//@ edition: 2021
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user