Auto merge of #149682 - matthiaskrgr:rollup-serlk7i, r=matthiaskrgr

Rollup of 11 pull requests

Successful merges:

 - rust-lang/rust#148662 (alloc: Document panics when allocations will exceed max)
 - rust-lang/rust#148811 (core docs: rewrite `panic::Location::caller` with visual line/column numbers)
 - rust-lang/rust#149101 (Improve mutable-binding suggestion to include name)
 - rust-lang/rust#149477 (float::maximum/minimum: make docs more streamlined)
 - rust-lang/rust#149547 (library: Rename `IterRange*` to `Range*Iter`)
 - rust-lang/rust#149548 (Generate delegation error body when delegation is not resolved)
 - rust-lang/rust#149630 (Check identifiers defined in macros when suggesting identifiers hidden by hygiene)
 - rust-lang/rust#149647 (Add regression test for 141845)
 - rust-lang/rust#149661 (Fix for LLVM22 making lowering decisions dependent on RuntimeLibraryInfo.)
 - rust-lang/rust#149666 (Add perma-unstable `--print=backend-has-zstd` for use by compiletest)
 - rust-lang/rust#149671 (interpret: test SNaN handling of float min/max and update comments)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors
2025-12-05 16:20:35 +00:00
49 changed files with 561 additions and 310 deletions
+37 -3
View File
@@ -96,7 +96,7 @@ pub(crate) fn lower_delegation(
let generics = self.lower_delegation_generics(span);
DelegationResults { body_id, sig, ident, generics }
}
Err(err) => self.generate_delegation_error(err, span),
Err(err) => self.generate_delegation_error(err, span, delegation),
}
}
@@ -404,6 +404,7 @@ fn generate_delegation_error(
&mut self,
err: ErrorGuaranteed,
span: Span,
delegation: &Delegation,
) -> DelegationResults<'hir> {
let generics = self.lower_delegation_generics(span);
@@ -418,8 +419,41 @@ fn generate_delegation_error(
let header = self.generate_header_error();
let sig = hir::FnSig { decl, header, span };
let ident = Ident::dummy();
let body_id = self.lower_body(|this| (&[], this.mk_expr(hir::ExprKind::Err(err), span)));
let ident = self.lower_ident(delegation.ident);
let body_id = self.lower_body(|this| {
let body_expr = match delegation.body.as_ref() {
Some(box block) => {
// Generates a block when we failed to resolve delegation, where a target expression is its only statement,
// thus there will be no ICEs on further stages of analysis (see #144594)
// As we generate a void function we want to convert target expression to statement to avoid additional
// errors, such as mismatched return type
let stmts = this.arena.alloc_from_iter([hir::Stmt {
hir_id: this.next_id(),
kind: rustc_hir::StmtKind::Semi(
this.arena.alloc(this.lower_target_expr(block)),
),
span,
}]);
let block = this.arena.alloc(hir::Block {
stmts,
expr: None,
hir_id: this.next_id(),
rules: hir::BlockCheckMode::DefaultBlock,
span,
targeted_by_break: false,
});
hir::ExprKind::Block(block, None)
}
None => hir::ExprKind::Err(err),
};
(&[], this.mk_expr(body_expr, span))
});
DelegationResults { ident, generics, body_id, sig }
}
@@ -3940,13 +3940,30 @@ pub(crate) fn report_illegal_reassignment(
if let Some(decl) = local_decl
&& decl.can_be_made_mutable()
{
let is_for_loop = matches!(
decl.local_info(),
LocalInfo::User(BindingForm::Var(VarBindingForm {
opt_match_place: Some((_, match_span)),
..
})) if matches!(match_span.desugaring_kind(), Some(DesugaringKind::ForLoop))
);
let message = if is_for_loop
&& let Ok(binding_name) =
self.infcx.tcx.sess.source_map().span_to_snippet(decl.source_info.span)
{
format!("(mut {}) ", binding_name)
} else {
"mut ".to_string()
};
err.span_suggestion_verbose(
decl.source_info.span.shrink_to_lo(),
"consider making this binding mutable",
"mut ".to_string(),
message,
Applicability::MachineApplicable,
);
if !from_arg
&& !is_for_loop
&& matches!(
decl.local_info(),
LocalInfo::User(BindingForm::Var(VarBindingForm {
@@ -75,7 +75,7 @@ fn write_output_file<'ll>(
let result = unsafe {
let pm = llvm::LLVMCreatePassManager();
llvm::LLVMAddAnalysisPasses(target, pm);
llvm::LLVMRustAddLibraryInfo(pm, m, no_builtins);
llvm::LLVMRustAddLibraryInfo(target, pm, m, no_builtins);
llvm::LLVMRustWriteOutputFile(
target,
pm,
+4
View File
@@ -257,6 +257,10 @@ fn print(&self, req: &PrintRequest, out: &mut String, sess: &Session) {
}
writeln!(out).unwrap();
}
PrintKind::BackendHasZstd => {
let has_zstd = llvm::LLVMRustLLVMHasZstdCompression();
writeln!(out, "{has_zstd}").unwrap();
}
PrintKind::CodeModels => {
writeln!(out, "Available code models:").unwrap();
for name in &["tiny", "small", "kernel", "medium", "large"] {
@@ -2379,6 +2379,7 @@ pub(crate) fn LLVMRustCreateTargetMachine(
) -> *mut TargetMachine;
pub(crate) fn LLVMRustAddLibraryInfo<'a>(
T: &TargetMachine,
PM: &PassManager<'a>,
M: &'a Module,
DisableSimplifyLibCalls: bool,
@@ -40,18 +40,20 @@ pub(crate) enum MinMax {
/// In particular, `-0.0` is considered smaller than `+0.0` and
/// if either input is NaN, the result is NaN.
Minimum,
/// The IEEE-2008 `minNum` operation - see `f32::min` etc.
/// The IEEE-2008 `minNum` operation with the SNaN handling of the
/// IEEE-2019 `minimumNumber` operation - see `f32::min` etc.
/// In particular, if the inputs are `-0.0` and `+0.0`, the result is non-deterministic,
/// and if one argument is NaN, the other one is returned.
MinNum,
/// and if one argument is NaN (quiet or signaling), the other one is returned.
MinimumNumber,
/// The IEEE-2019 `maximum` operation - see `f32::maximum` etc.
/// In particular, `-0.0` is considered smaller than `+0.0` and
/// if either input is NaN, the result is NaN.
Maximum,
/// The IEEE-2008 `maxNum` operation - see `f32::max` etc.
/// The IEEE-2008 `maxNum` operation with the SNaN handling of the
/// IEEE-2019 `maximumNumber` operation - see `f32::max` etc.
/// In particular, if the inputs are `-0.0` and `+0.0`, the result is non-deterministic,
/// and if one argument is NaN, the other one is returned.
MaxNum,
/// and if one argument is NaN (quiet or signaling), the other one is returned.
MaximumNumber,
}
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
@@ -524,10 +526,18 @@ pub fn eval_intrinsic(
self.write_scalar(Scalar::from_target_usize(align.bytes(), self), dest)?;
}
sym::minnumf16 => self.float_minmax_intrinsic::<Half>(args, MinMax::MinNum, dest)?,
sym::minnumf32 => self.float_minmax_intrinsic::<Single>(args, MinMax::MinNum, dest)?,
sym::minnumf64 => self.float_minmax_intrinsic::<Double>(args, MinMax::MinNum, dest)?,
sym::minnumf128 => self.float_minmax_intrinsic::<Quad>(args, MinMax::MinNum, dest)?,
sym::minnumf16 => {
self.float_minmax_intrinsic::<Half>(args, MinMax::MinimumNumber, dest)?
}
sym::minnumf32 => {
self.float_minmax_intrinsic::<Single>(args, MinMax::MinimumNumber, dest)?
}
sym::minnumf64 => {
self.float_minmax_intrinsic::<Double>(args, MinMax::MinimumNumber, dest)?
}
sym::minnumf128 => {
self.float_minmax_intrinsic::<Quad>(args, MinMax::MinimumNumber, dest)?
}
sym::minimumf16 => self.float_minmax_intrinsic::<Half>(args, MinMax::Minimum, dest)?,
sym::minimumf32 => {
@@ -538,10 +548,18 @@ pub fn eval_intrinsic(
}
sym::minimumf128 => self.float_minmax_intrinsic::<Quad>(args, MinMax::Minimum, dest)?,
sym::maxnumf16 => self.float_minmax_intrinsic::<Half>(args, MinMax::MaxNum, dest)?,
sym::maxnumf32 => self.float_minmax_intrinsic::<Single>(args, MinMax::MaxNum, dest)?,
sym::maxnumf64 => self.float_minmax_intrinsic::<Double>(args, MinMax::MaxNum, dest)?,
sym::maxnumf128 => self.float_minmax_intrinsic::<Quad>(args, MinMax::MaxNum, dest)?,
sym::maxnumf16 => {
self.float_minmax_intrinsic::<Half>(args, MinMax::MaximumNumber, dest)?
}
sym::maxnumf32 => {
self.float_minmax_intrinsic::<Single>(args, MinMax::MaximumNumber, dest)?
}
sym::maxnumf64 => {
self.float_minmax_intrinsic::<Double>(args, MinMax::MaximumNumber, dest)?
}
sym::maxnumf128 => {
self.float_minmax_intrinsic::<Quad>(args, MinMax::MaximumNumber, dest)?
}
sym::maximumf16 => self.float_minmax_intrinsic::<Half>(args, MinMax::Maximum, dest)?,
sym::maximumf32 => {
@@ -966,16 +984,16 @@ fn float_minmax<F>(
{
let a: F = a.to_float()?;
let b: F = b.to_float()?;
let res = if matches!(op, MinMax::MinNum | MinMax::MaxNum) && a == b {
let res = if matches!(op, MinMax::MinimumNumber | MinMax::MaximumNumber) && a == b {
// They are definitely not NaN (those are never equal), but they could be `+0` and `-0`.
// Let the machine decide which one to return.
M::equal_float_min_max(self, a, b)
} else {
let result = match op {
MinMax::Minimum => a.minimum(b),
MinMax::MinNum => a.min(b),
MinMax::MinimumNumber => a.min(b),
MinMax::Maximum => a.maximum(b),
MinMax::MaxNum => a.max(b),
MinMax::MaximumNumber => a.max(b),
};
self.adjust_nan(result, &[a, b])
};
@@ -202,8 +202,8 @@ enum Op {
sym::simd_le => Op::MirOp(BinOp::Le),
sym::simd_gt => Op::MirOp(BinOp::Gt),
sym::simd_ge => Op::MirOp(BinOp::Ge),
sym::simd_fmax => Op::FMinMax(MinMax::MaxNum),
sym::simd_fmin => Op::FMinMax(MinMax::MinNum),
sym::simd_fmax => Op::FMinMax(MinMax::MaximumNumber),
sym::simd_fmin => Op::FMinMax(MinMax::MinimumNumber),
sym::simd_saturating_add => Op::SaturatingOp(BinOp::Add),
sym::simd_saturating_sub => Op::SaturatingOp(BinOp::Sub),
sym::simd_arith_offset => Op::WrappingOffset,
@@ -295,8 +295,8 @@ enum Op {
sym::simd_reduce_xor => Op::MirOp(BinOp::BitXor),
sym::simd_reduce_any => Op::MirOpBool(BinOp::BitOr),
sym::simd_reduce_all => Op::MirOpBool(BinOp::BitAnd),
sym::simd_reduce_max => Op::MinMax(MinMax::MaxNum),
sym::simd_reduce_min => Op::MinMax(MinMax::MinNum),
sym::simd_reduce_max => Op::MinMax(MinMax::MaximumNumber),
sym::simd_reduce_min => Op::MinMax(MinMax::MinimumNumber),
_ => unreachable!(),
};
@@ -320,8 +320,8 @@ enum Op {
} else {
// Just boring integers, no NaNs to worry about.
let mirop = match mmop {
MinMax::MinNum | MinMax::Minimum => BinOp::Le,
MinMax::MaxNum | MinMax::Maximum => BinOp::Ge,
MinMax::MinimumNumber | MinMax::Minimum => BinOp::Le,
MinMax::MaximumNumber | MinMax::Maximum => BinOp::Ge,
};
if self.binary_op(mirop, &res, &op)?.to_scalar().to_bool()? {
res
+1
View File
@@ -799,6 +799,7 @@ fn print_crate_info(
println_info!("{}", calling_conventions.join("\n"));
}
RelocationModels
| BackendHasZstd
| CodeModels
| TlsModels
| TargetCPUs
@@ -6,6 +6,9 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/Lint.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#if LLVM_VERSION_GE(22, 0)
#include "llvm/Analysis/RuntimeLibcallInfo.h"
#endif
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/CodeGen/CommandFlags.h"
@@ -379,13 +382,20 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
// Unfortunately, the LLVM C API doesn't provide a way to create the
// TargetLibraryInfo pass, so we use this method to do so.
extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M,
extern "C" void LLVMRustAddLibraryInfo(LLVMTargetMachineRef T,
LLVMPassManagerRef PMR, LLVMModuleRef M,
bool DisableSimplifyLibCalls) {
auto TargetTriple = Triple(unwrap(M)->getTargetTriple());
TargetOptions *Options = &unwrap(T)->Options;
auto TLII = TargetLibraryInfoImpl(TargetTriple);
if (DisableSimplifyLibCalls)
TLII.disableAllFunctions();
unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII));
#if LLVM_VERSION_GE(22, 0)
unwrap(PMR)->add(new RuntimeLibraryInfoWrapper(
TargetTriple, Options->ExceptionModel, Options->FloatABIType,
Options->EABIVersion, Options->MCOptions.ABIName, Options->VecLib));
#endif
}
extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) {
@@ -1155,6 +1155,7 @@ fn suggest_ident_hidden_by_hygiene(&self, err: &mut Diag<'_>, path: &[Segment],
let callsite_span = span.source_callsite();
for rib in self.ribs[ValueNS].iter().rev() {
for (binding_ident, _) in &rib.bindings {
// Case 1: the identifier is defined in the same scope as the macro is called
if binding_ident.name == ident.name
&& !binding_ident.span.eq_ctxt(span)
&& !binding_ident.span.from_expansion()
@@ -1166,6 +1167,19 @@ fn suggest_ident_hidden_by_hygiene(&self, err: &mut Diag<'_>, path: &[Segment],
);
return;
}
// Case 2: the identifier is defined in a macro call in the same scope
if binding_ident.name == ident.name
&& binding_ident.span.from_expansion()
&& binding_ident.span.source_callsite().eq_ctxt(callsite_span)
&& binding_ident.span.source_callsite().lo() < callsite_span.lo()
{
err.span_help(
binding_ident.span,
"an identifier with the same name is defined here, but is not accessible due to macro hygiene",
);
return;
}
}
}
}
@@ -22,6 +22,7 @@ pub struct PrintRequest {
pub enum PrintKind {
// tidy-alphabetical-start
AllTargetSpecsJson,
BackendHasZstd,
CallingConventions,
Cfg,
CheckCfg,
@@ -59,6 +60,7 @@ fn name(self) -> &'static str {
match self {
// tidy-alphabetical-start
AllTargetSpecsJson => "all-target-specs-json",
BackendHasZstd => "backend-has-zstd",
CallingConventions => "calling-conventions",
Cfg => "cfg",
CheckCfg => "check-cfg",
@@ -111,6 +113,7 @@ fn is_stable(self) -> bool {
// Unstable values:
AllTargetSpecsJson => false,
BackendHasZstd => false, // (perma-unstable, for use by compiletest)
CheckCfg => false,
CrateRootLintLevels => false,
SupportedCrateTypes => false,
+17 -4
View File
@@ -454,6 +454,10 @@ pub const fn new() -> String {
///
/// [`new`]: String::new
///
/// # Panics
///
/// Panics if the capacity exceeds `isize::MAX` _bytes_.
///
/// # Examples
///
/// ```
@@ -1079,6 +1083,10 @@ pub const fn as_mut_str(&mut self) -> &mut str {
/// Appends a given string slice onto the end of this `String`.
///
/// # Panics
///
/// Panics if the new capacity exceeds `isize::MAX` _bytes_.
///
/// # Examples
///
/// ```
@@ -1101,8 +1109,9 @@ pub fn push_str(&mut self, string: &str) {
///
/// # Panics
///
/// Panics if the range has `start_bound > end_bound`, or, if the range is
/// bounded on either end and does not lie on a [`char`] boundary.
/// Panics if the range has `start_bound > end_bound`, if the range is
/// bounded on either end and does not lie on a [`char`] boundary, or if the
/// new capacity exceeds `isize::MAX` bytes.
///
/// # Examples
///
@@ -1158,7 +1167,7 @@ pub const fn capacity(&self) -> usize {
///
/// # Panics
///
/// Panics if the new capacity overflows [`usize`].
/// Panics if the new capacity exceeds `isize::MAX` _bytes_.
///
/// # Examples
///
@@ -1208,7 +1217,7 @@ pub fn reserve(&mut self, additional: usize) {
///
/// # Panics
///
/// Panics if the new capacity overflows [`usize`].
/// Panics if the new capacity exceeds `isize::MAX` _bytes_.
///
/// # Examples
///
@@ -1372,6 +1381,10 @@ pub fn shrink_to(&mut self, min_capacity: usize) {
/// Appends the given [`char`] to the end of this `String`.
///
/// # Panics
///
/// Panics if the new capacity exceeds `isize::MAX` _bytes_.
///
/// # Examples
///
/// ```
+7 -2
View File
@@ -3340,6 +3340,10 @@ pub fn resize(&mut self, new_len: usize, value: T) {
/// except that it also works with slice elements that are Clone but not Copy.
/// If Rust gets specialization this function may be deprecated.
///
/// # Panics
///
/// Panics if the new capacity exceeds `isize::MAX` _bytes_.
///
/// # Examples
///
/// ```
@@ -3361,8 +3365,9 @@ pub fn extend_from_slice(&mut self, other: &[T]) {
///
/// # Panics
///
/// Panics if starting index is greater than the end index
/// or if the index is greater than the length of the vector.
/// Panics if starting index is greater than the end index, if the index is
/// greater than the length of the vector, or if the new capacity exceeds
/// `isize::MAX` _bytes_.
///
/// # Examples
///
+18 -18
View File
@@ -756,8 +756,15 @@ pub const fn min(self, other: f128) -> f128 {
/// Returns the maximum of the two numbers, propagating NaN.
///
/// This returns NaN when *either* argument is NaN, as opposed to
/// [`f128::max`] which only returns NaN when *both* arguments are NaN.
/// If at least one of the arguments is NaN, the return value is NaN, with the bit pattern
/// picked using the usual [rules for arithmetic operations](f32#nan-bit-patterns). Furthermore,
/// `-0.0` is considered to be less than `+0.0`, making this function fully deterministic for
/// non-NaN inputs.
///
/// This is in contrast to [`f128::max`] which only returns NaN when *both* arguments are NaN,
/// and which does not reliably order `-0.0` and `+0.0`.
///
/// This follows the IEEE 754-2019 semantics for `maximum`.
///
/// ```
/// #![feature(f128)]
@@ -772,13 +779,6 @@ pub const fn min(self, other: f128) -> f128 {
/// assert!(x.maximum(f128::NAN).is_nan());
/// # }
/// ```
///
/// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater
/// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
/// Note that this follows the IEEE 754-2019 semantics for `maximum`.
///
/// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN
/// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info.
#[inline]
#[unstable(feature = "f128", issue = "116909")]
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
@@ -789,8 +789,15 @@ pub const fn maximum(self, other: f128) -> f128 {
/// Returns the minimum of the two numbers, propagating NaN.
///
/// This returns NaN when *either* argument is NaN, as opposed to
/// [`f128::min`] which only returns NaN when *both* arguments are NaN.
/// If at least one of the arguments is NaN, the return value is NaN, with the bit pattern
/// picked using the usual [rules for arithmetic operations](f32#nan-bit-patterns). Furthermore,
/// `-0.0` is considered to be less than `+0.0`, making this function fully deterministic for
/// non-NaN inputs.
///
/// This is in contrast to [`f128::min`] which only returns NaN when *both* arguments are NaN,
/// and which does not reliably order `-0.0` and `+0.0`.
///
/// This follows the IEEE 754-2019 semantics for `minimum`.
///
/// ```
/// #![feature(f128)]
@@ -805,13 +812,6 @@ pub const fn maximum(self, other: f128) -> f128 {
/// assert!(x.minimum(f128::NAN).is_nan());
/// # }
/// ```
///
/// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser
/// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
/// Note that this follows the IEEE 754-2019 semantics for `minimum`.
///
/// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN
/// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info.
#[inline]
#[unstable(feature = "f128", issue = "116909")]
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
+18 -18
View File
@@ -747,8 +747,15 @@ pub const fn min(self, other: f16) -> f16 {
/// Returns the maximum of the two numbers, propagating NaN.
///
/// This returns NaN when *either* argument is NaN, as opposed to
/// [`f16::max`] which only returns NaN when *both* arguments are NaN.
/// If at least one of the arguments is NaN, the return value is NaN, with the bit pattern
/// picked using the usual [rules for arithmetic operations](f32#nan-bit-patterns). Furthermore,
/// `-0.0` is considered to be less than `+0.0`, making this function fully deterministic for
/// non-NaN inputs.
///
/// This is in contrast to [`f16::max`] which only returns NaN when *both* arguments are NaN,
/// and which does not reliably order `-0.0` and `+0.0`.
///
/// This follows the IEEE 754-2019 semantics for `maximum`.
///
/// ```
/// #![feature(f16)]
@@ -762,13 +769,6 @@ pub const fn min(self, other: f16) -> f16 {
/// assert!(x.maximum(f16::NAN).is_nan());
/// # }
/// ```
///
/// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater
/// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
/// Note that this follows the IEEE 754-2019 semantics for `maximum`.
///
/// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN
/// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info.
#[inline]
#[unstable(feature = "f16", issue = "116909")]
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
@@ -779,8 +779,15 @@ pub const fn maximum(self, other: f16) -> f16 {
/// Returns the minimum of the two numbers, propagating NaN.
///
/// This returns NaN when *either* argument is NaN, as opposed to
/// [`f16::min`] which only returns NaN when *both* arguments are NaN.
/// If at least one of the arguments is NaN, the return value is NaN, with the bit pattern
/// picked using the usual [rules for arithmetic operations](f32#nan-bit-patterns). Furthermore,
/// `-0.0` is considered to be less than `+0.0`, making this function fully deterministic for
/// non-NaN inputs.
///
/// This is in contrast to [`f16::min`] which only returns NaN when *both* arguments are NaN,
/// and which does not reliably order `-0.0` and `+0.0`.
///
/// This follows the IEEE 754-2019 semantics for `minimum`.
///
/// ```
/// #![feature(f16)]
@@ -794,13 +801,6 @@ pub const fn maximum(self, other: f16) -> f16 {
/// assert!(x.minimum(f16::NAN).is_nan());
/// # }
/// ```
///
/// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser
/// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
/// Note that this follows the IEEE 754-2019 semantics for `minimum`.
///
/// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN
/// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info.
#[inline]
#[unstable(feature = "f16", issue = "116909")]
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
+18 -18
View File
@@ -949,8 +949,15 @@ pub const fn min(self, other: f32) -> f32 {
/// Returns the maximum of the two numbers, propagating NaN.
///
/// This returns NaN when *either* argument is NaN, as opposed to
/// [`f32::max`] which only returns NaN when *both* arguments are NaN.
/// If at least one of the arguments is NaN, the return value is NaN, with the bit pattern
/// picked using the usual [rules for arithmetic operations](f32#nan-bit-patterns). Furthermore,
/// `-0.0` is considered to be less than `+0.0`, making this function fully deterministic for
/// non-NaN inputs.
///
/// This is in contrast to [`f32::max`] which only returns NaN when *both* arguments are NaN,
/// and which does not reliably order `-0.0` and `+0.0`.
///
/// This follows the IEEE 754-2019 semantics for `maximum`.
///
/// ```
/// #![feature(float_minimum_maximum)]
@@ -960,13 +967,6 @@ pub const fn min(self, other: f32) -> f32 {
/// assert_eq!(x.maximum(y), y);
/// assert!(x.maximum(f32::NAN).is_nan());
/// ```
///
/// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater
/// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
/// Note that this follows the IEEE 754-2019 semantics for `maximum`.
///
/// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN
/// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info.
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[inline]
@@ -976,8 +976,15 @@ pub const fn maximum(self, other: f32) -> f32 {
/// Returns the minimum of the two numbers, propagating NaN.
///
/// This returns NaN when *either* argument is NaN, as opposed to
/// [`f32::min`] which only returns NaN when *both* arguments are NaN.
/// If at least one of the arguments is NaN, the return value is NaN, with the bit pattern
/// picked using the usual [rules for arithmetic operations](f32#nan-bit-patterns). Furthermore,
/// `-0.0` is considered to be less than `+0.0`, making this function fully deterministic for
/// non-NaN inputs.
///
/// This is in contrast to [`f32::min`] which only returns NaN when *both* arguments are NaN,
/// and which does not reliably order `-0.0` and `+0.0`.
///
/// This follows the IEEE 754-2019 semantics for `minimum`.
///
/// ```
/// #![feature(float_minimum_maximum)]
@@ -987,13 +994,6 @@ pub const fn maximum(self, other: f32) -> f32 {
/// assert_eq!(x.minimum(y), x);
/// assert!(x.minimum(f32::NAN).is_nan());
/// ```
///
/// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser
/// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
/// Note that this follows the IEEE 754-2019 semantics for `minimum`.
///
/// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN
/// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info.
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[inline]
+18 -18
View File
@@ -967,8 +967,15 @@ pub const fn min(self, other: f64) -> f64 {
/// Returns the maximum of the two numbers, propagating NaN.
///
/// This returns NaN when *either* argument is NaN, as opposed to
/// [`f64::max`] which only returns NaN when *both* arguments are NaN.
/// If at least one of the arguments is NaN, the return value is NaN, with the bit pattern
/// picked using the usual [rules for arithmetic operations](f32#nan-bit-patterns). Furthermore,
/// `-0.0` is considered to be less than `+0.0`, making this function fully deterministic for
/// non-NaN inputs.
///
/// This is in contrast to [`f64::max`] which only returns NaN when *both* arguments are NaN,
/// and which does not reliably order `-0.0` and `+0.0`.
///
/// This follows the IEEE 754-2019 semantics for `maximum`.
///
/// ```
/// #![feature(float_minimum_maximum)]
@@ -978,13 +985,6 @@ pub const fn min(self, other: f64) -> f64 {
/// assert_eq!(x.maximum(y), y);
/// assert!(x.maximum(f64::NAN).is_nan());
/// ```
///
/// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater
/// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
/// Note that this follows the IEEE 754-2019 semantics for `maximum`.
///
/// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN
/// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info.
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[inline]
@@ -994,8 +994,15 @@ pub const fn maximum(self, other: f64) -> f64 {
/// Returns the minimum of the two numbers, propagating NaN.
///
/// This returns NaN when *either* argument is NaN, as opposed to
/// [`f64::min`] which only returns NaN when *both* arguments are NaN.
/// If at least one of the arguments is NaN, the return value is NaN, with the bit pattern
/// picked using the usual [rules for arithmetic operations](f32#nan-bit-patterns). Furthermore,
/// `-0.0` is considered to be less than `+0.0`, making this function fully deterministic for
/// non-NaN inputs.
///
/// This is in contrast to [`f64::min`] which only returns NaN when *both* arguments are NaN,
/// and which does not reliably order `-0.0` and `+0.0`.
///
/// This follows the IEEE 754-2019 semantics for `minimum`.
///
/// ```
/// #![feature(float_minimum_maximum)]
@@ -1005,13 +1012,6 @@ pub const fn maximum(self, other: f64) -> f64 {
/// assert_eq!(x.minimum(y), x);
/// assert!(x.minimum(f64::NAN).is_nan());
/// ```
///
/// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser
/// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
/// Note that this follows the IEEE 754-2019 semantics for `minimum`.
///
/// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN
/// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info.
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[inline]
+57 -23
View File
@@ -105,38 +105,72 @@ impl<'a> Location<'a> {
/// ```standalone_crate
/// use std::panic::Location;
///
/// /// Returns the [`Location`] at which it is called.
/// /// ```
/// /// |1 |11 |21 |31 |41
/// /// +-|---------|---------|---------|---------|--------
/// /// 15 | #[track_caller]
/// /// 16 | fn new_location() -> &'static Location<'static> {
/// /// 17 | Location::caller()
/// /// | ------------------| the value of this expression depends on the caller,
/// /// | | since the function is marked #[track_caller]
/// /// 18 | }
/// /// ```
/// #[track_caller]
/// fn get_caller_location() -> &'static Location<'static> {
/// fn new_location() -> &'static Location<'static> {
/// Location::caller()
/// }
///
/// /// Returns a [`Location`] from within this function's definition.
/// fn get_just_one_location() -> &'static Location<'static> {
/// get_caller_location()
/// /// ```
/// /// |1 |5 |11 |21 |31 |41 |51
/// /// +-|---|-----|---------|---------|---------|---------|---
/// /// 29 | fn constant_location() -> &'static Location<'static> {
/// /// 30 | new_location()
/// /// | ^ any invocation of constant_location() points here,
/// /// | no matter the location it is called from
/// /// 31 | }
/// /// ```
/// fn constant_location() -> &'static Location<'static> {
/// new_location()
/// }
///
/// let fixed_location = get_just_one_location();
/// assert_eq!(fixed_location.file(), file!());
/// assert_eq!(fixed_location.line(), 14);
/// assert_eq!(fixed_location.column(), 5);
/// fn main() {
/// // |1 |5 |11 |21 |31 |41 |51
/// // +-|---|-----|---------|---------|---------|---------|---
/// // 29 | fn constant_location() -> &'static Location<'static> {
/// // 30 | new_location()
/// // | ^ `let constant` points here
/// // 31 | }
/// let constant = constant_location();
/// assert_eq!(constant.file(), file!());
/// assert_eq!((constant.line(), constant.column()), (30, 5));
///
/// // running the same untracked function in a different location gives us the same result
/// let second_fixed_location = get_just_one_location();
/// assert_eq!(fixed_location.file(), second_fixed_location.file());
/// assert_eq!(fixed_location.line(), second_fixed_location.line());
/// assert_eq!(fixed_location.column(), second_fixed_location.column());
/// let constant_2 = constant_location();
/// assert_eq!(
/// (constant.file(), constant.line(), constant.column()),
/// (constant_2.file(), constant_2.line(), constant_2.column())
/// );
///
/// let this_location = get_caller_location();
/// assert_eq!(this_location.file(), file!());
/// assert_eq!(this_location.line(), 28);
/// assert_eq!(this_location.column(), 21);
/// // |1 |11 |16 |21 |31
/// // +-|---------|----|----|---------|------
/// // 55 | let here = new_location();
/// // | ^ `let here` points here, as `new_location()` is the callsite
/// // 56 | assert_eq!(here.file(), file!());
/// let here = new_location();
/// assert_eq!(here.file(), file!());
/// assert_eq!((here.line(), here.column()), (55, 16));
///
/// // running the tracked function in a different location produces a different value
/// let another_location = get_caller_location();
/// assert_eq!(this_location.file(), another_location.file());
/// assert_ne!(this_location.line(), another_location.line());
/// assert_ne!(this_location.column(), another_location.column());
/// // |1 |11 |21 ||32 |41 |51
/// // +-|---------|---------|---------||--------|---------|------
/// // 64 | let yet_another_location = new_location();
/// // | ^ `let yet_another_location` points here
/// // 65 | assert_eq!(here.file(), yet_another_location.file());
/// let yet_another_location = new_location();
/// assert_eq!(here.file(), yet_another_location.file());
/// assert_ne!(
/// (here.line(), here.column()),
/// (yet_another_location.line(), yet_another_location.column())
/// );
/// }
/// ```
#[must_use]
#[stable(feature = "track_caller", since = "1.46.0")]
+4 -4
View File
@@ -26,7 +26,7 @@
use Bound::{Excluded, Included, Unbounded};
#[doc(inline)]
pub use iter::{IterRange, IterRangeFrom, IterRangeInclusive};
pub use iter::{RangeFromIter, RangeInclusiveIter, RangeIter};
#[doc(inline)]
pub use crate::iter::Step;
@@ -89,7 +89,7 @@ impl<Idx: Step> Range<Idx> {
/// ```
#[unstable(feature = "new_range_api", issue = "125687")]
#[inline]
pub fn iter(&self) -> IterRange<Idx> {
pub fn iter(&self) -> RangeIter<Idx> {
self.clone().into_iter()
}
}
@@ -340,7 +340,7 @@ impl<Idx: Step> RangeInclusive<Idx> {
/// ```
#[unstable(feature = "new_range_api", issue = "125687")]
#[inline]
pub fn iter(&self) -> IterRangeInclusive<Idx> {
pub fn iter(&self) -> RangeInclusiveIter<Idx> {
self.clone().into_iter()
}
}
@@ -477,7 +477,7 @@ impl<Idx: Step> RangeFrom<Idx> {
/// ```
#[unstable(feature = "new_range_api", issue = "125687")]
#[inline]
pub fn iter(&self) -> IterRangeFrom<Idx> {
pub fn iter(&self) -> RangeFromIter<Idx> {
self.clone().into_iter()
}
}
+27 -27
View File
@@ -8,9 +8,9 @@
/// By-value [`Range`] iterator.
#[unstable(feature = "new_range_api", issue = "125687")]
#[derive(Debug, Clone)]
pub struct IterRange<A>(legacy::Range<A>);
pub struct RangeIter<A>(legacy::Range<A>);
impl<A> IterRange<A> {
impl<A> RangeIter<A> {
/// Returns the remainder of the range being iterated over.
pub fn remainder(self) -> Range<A> {
Range { start: self.0.start, end: self.0.end }
@@ -23,11 +23,11 @@ macro_rules! unsafe_range_trusted_random_access_impl {
($($t:ty)*) => ($(
#[doc(hidden)]
#[unstable(feature = "trusted_random_access", issue = "none")]
unsafe impl TrustedRandomAccess for IterRange<$t> {}
unsafe impl TrustedRandomAccess for RangeIter<$t> {}
#[doc(hidden)]
#[unstable(feature = "trusted_random_access", issue = "none")]
unsafe impl TrustedRandomAccessNoCoerce for IterRange<$t> {
unsafe impl TrustedRandomAccessNoCoerce for RangeIter<$t> {
const MAY_HAVE_SIDE_EFFECT: bool = false;
}
)*)
@@ -50,7 +50,7 @@ unsafe impl TrustedRandomAccessNoCoerce for IterRange<$t> {
}
#[unstable(feature = "new_range_api", issue = "125687")]
impl<A: Step> Iterator for IterRange<A> {
impl<A: Step> Iterator for RangeIter<A> {
type Item = A;
#[inline]
@@ -118,7 +118,7 @@ unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
}
#[unstable(feature = "new_range_api", issue = "125687")]
impl<A: Step> DoubleEndedIterator for IterRange<A> {
impl<A: Step> DoubleEndedIterator for RangeIter<A> {
#[inline]
fn next_back(&mut self) -> Option<A> {
self.0.next_back()
@@ -136,27 +136,27 @@ fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
}
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<A: TrustedStep> TrustedLen for IterRange<A> {}
unsafe impl<A: TrustedStep> TrustedLen for RangeIter<A> {}
#[unstable(feature = "new_range_api", issue = "125687")]
impl<A: Step> FusedIterator for IterRange<A> {}
impl<A: Step> FusedIterator for RangeIter<A> {}
#[unstable(feature = "new_range_api", issue = "125687")]
impl<A: Step> IntoIterator for Range<A> {
type Item = A;
type IntoIter = IterRange<A>;
type IntoIter = RangeIter<A>;
fn into_iter(self) -> Self::IntoIter {
IterRange(self.into())
RangeIter(self.into())
}
}
/// By-value [`RangeInclusive`] iterator.
#[unstable(feature = "new_range_api", issue = "125687")]
#[derive(Debug, Clone)]
pub struct IterRangeInclusive<A>(legacy::RangeInclusive<A>);
pub struct RangeInclusiveIter<A>(legacy::RangeInclusive<A>);
impl<A: Step> IterRangeInclusive<A> {
impl<A: Step> RangeInclusiveIter<A> {
/// Returns the remainder of the range being iterated over.
///
/// If the iterator is exhausted or empty, returns `None`.
@@ -170,7 +170,7 @@ pub fn remainder(self) -> Option<RangeInclusive<A>> {
}
#[unstable(feature = "new_range_api", issue = "125687")]
impl<A: Step> Iterator for IterRangeInclusive<A> {
impl<A: Step> Iterator for RangeInclusiveIter<A> {
type Item = A;
#[inline]
@@ -226,7 +226,7 @@ fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
}
#[unstable(feature = "new_range_api", issue = "125687")]
impl<A: Step> DoubleEndedIterator for IterRangeInclusive<A> {
impl<A: Step> DoubleEndedIterator for RangeInclusiveIter<A> {
#[inline]
fn next_back(&mut self) -> Option<A> {
self.0.next_back()
@@ -244,18 +244,18 @@ fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
}
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<A: TrustedStep> TrustedLen for IterRangeInclusive<A> {}
unsafe impl<A: TrustedStep> TrustedLen for RangeInclusiveIter<A> {}
#[unstable(feature = "new_range_api", issue = "125687")]
impl<A: Step> FusedIterator for IterRangeInclusive<A> {}
impl<A: Step> FusedIterator for RangeInclusiveIter<A> {}
#[unstable(feature = "new_range_api", issue = "125687")]
impl<A: Step> IntoIterator for RangeInclusive<A> {
type Item = A;
type IntoIter = IterRangeInclusive<A>;
type IntoIter = RangeInclusiveIter<A>;
fn into_iter(self) -> Self::IntoIter {
IterRangeInclusive(self.into())
RangeInclusiveIter(self.into())
}
}
@@ -270,14 +270,14 @@ fn into_iter(self) -> Self::IntoIter {
macro_rules! range_exact_iter_impl {
($($t:ty)*) => ($(
#[unstable(feature = "new_range_api", issue = "125687")]
impl ExactSizeIterator for IterRange<$t> { }
impl ExactSizeIterator for RangeIter<$t> { }
)*)
}
macro_rules! range_incl_exact_iter_impl {
($($t:ty)*) => ($(
#[unstable(feature = "new_range_api", issue = "125687")]
impl ExactSizeIterator for IterRangeInclusive<$t> { }
impl ExactSizeIterator for RangeInclusiveIter<$t> { }
)*)
}
@@ -294,14 +294,14 @@ impl ExactSizeIterator for IterRangeInclusive<$t> { }
/// By-value [`RangeFrom`] iterator.
#[unstable(feature = "new_range_api", issue = "125687")]
#[derive(Debug, Clone)]
pub struct IterRangeFrom<A> {
pub struct RangeFromIter<A> {
start: A,
/// Whether the first element of the iterator has yielded.
/// Only used when overflow checks are enabled.
first: bool,
}
impl<A: Step> IterRangeFrom<A> {
impl<A: Step> RangeFromIter<A> {
/// Returns the remainder of the range being iterated over.
#[inline]
#[rustc_inherit_overflow_checks]
@@ -317,7 +317,7 @@ pub fn remainder(self) -> RangeFrom<A> {
}
#[unstable(feature = "new_range_api", issue = "125687")]
impl<A: Step> Iterator for IterRangeFrom<A> {
impl<A: Step> Iterator for RangeFromIter<A> {
type Item = A;
#[inline]
@@ -366,17 +366,17 @@ fn nth(&mut self, n: usize) -> Option<A> {
}
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<A: TrustedStep> TrustedLen for IterRangeFrom<A> {}
unsafe impl<A: TrustedStep> TrustedLen for RangeFromIter<A> {}
#[unstable(feature = "new_range_api", issue = "125687")]
impl<A: Step> FusedIterator for IterRangeFrom<A> {}
impl<A: Step> FusedIterator for RangeFromIter<A> {}
#[unstable(feature = "new_range_api", issue = "125687")]
impl<A: Step> IntoIterator for RangeFrom<A> {
type Item = A;
type IntoIter = IterRangeFrom<A>;
type IntoIter = RangeFromIter<A>;
fn into_iter(self) -> Self::IntoIter {
IterRangeFrom { start: self.start, first: true }
RangeFromIter { start: self.start, first: true }
}
}
+5 -1
View File
@@ -1096,7 +1096,11 @@ fn supported_crate_types(config: &Config) -> HashSet<String> {
crate_types
}
fn query_rustc_output(config: &Config, args: &[&str], envs: HashMap<String, String>) -> String {
pub(crate) fn query_rustc_output(
config: &Config,
args: &[&str],
envs: HashMap<String, String>,
) -> String {
let query_rustc_path = config.query_rustc_path.as_deref().unwrap_or(&config.rustc_path);
let mut command = Command::new(query_rustc_path);
-101
View File
@@ -885,107 +885,6 @@ pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<Version> {
None
}
/// For tests using the `needs-llvm-zstd` directive:
/// - for local LLVM builds, try to find the static zstd library in the llvm-config system libs.
/// - for `download-ci-llvm`, see if `lld` was built with zstd support.
pub fn llvm_has_libzstd(config: &Config) -> bool {
// Strategy 1: works for local builds but not with `download-ci-llvm`.
//
// We check whether `llvm-config` returns the zstd library. Bootstrap's `llvm.libzstd` will only
// ask to statically link it when building LLVM, so we only check if the list of system libs
// contains a path to that static lib, and that it exists.
//
// See compiler/rustc_llvm/build.rs for more details and similar expectations.
fn is_zstd_in_config(llvm_bin_dir: &Utf8Path) -> Option<()> {
let llvm_config_path = llvm_bin_dir.join("llvm-config");
let output = Command::new(llvm_config_path).arg("--system-libs").output().ok()?;
assert!(output.status.success(), "running llvm-config --system-libs failed");
let libs = String::from_utf8(output.stdout).ok()?;
for lib in libs.split_whitespace() {
if lib.ends_with("libzstd.a") && Utf8Path::new(lib).exists() {
return Some(());
}
}
None
}
// Strategy 2: `download-ci-llvm`'s `llvm-config --system-libs` will not return any libs to
// use.
//
// The CI artifacts also don't contain the bootstrap config used to build them: otherwise we
// could have looked at the `llvm.libzstd` config.
//
// We infer whether `LLVM_ENABLE_ZSTD` was used to build LLVM as a byproduct of testing whether
// `lld` supports it. If not, an error will be emitted: "LLVM was not built with
// LLVM_ENABLE_ZSTD or did not find zstd at build time".
#[cfg(unix)]
fn is_lld_built_with_zstd(llvm_bin_dir: &Utf8Path) -> Option<()> {
let lld_path = llvm_bin_dir.join("lld");
if lld_path.exists() {
// We can't call `lld` as-is, it expects to be invoked by a compiler driver using a
// different name. Prepare a temporary symlink to do that.
let lld_symlink_path = llvm_bin_dir.join("ld.lld");
if !lld_symlink_path.exists() {
std::os::unix::fs::symlink(lld_path, &lld_symlink_path).ok()?;
}
// Run `lld` with a zstd flag. We expect this command to always error here, we don't
// want to link actual files and don't pass any.
let output = Command::new(&lld_symlink_path)
.arg("--compress-debug-sections=zstd")
.output()
.ok()?;
assert!(!output.status.success());
// Look for a specific error caused by LLVM not being built with zstd support. We could
// also look for the "no input files" message, indicating the zstd flag was accepted.
let stderr = String::from_utf8(output.stderr).ok()?;
let zstd_available = !stderr.contains("LLVM was not built with LLVM_ENABLE_ZSTD");
// We don't particularly need to clean the link up (so the previous commands could fail
// in theory but won't in practice), but we can try.
std::fs::remove_file(lld_symlink_path).ok()?;
if zstd_available {
return Some(());
}
}
None
}
#[cfg(not(unix))]
fn is_lld_built_with_zstd(_llvm_bin_dir: &Utf8Path) -> Option<()> {
None
}
if let Some(llvm_bin_dir) = &config.llvm_bin_dir {
// Strategy 1: for local LLVM builds.
if is_zstd_in_config(llvm_bin_dir).is_some() {
return true;
}
// Strategy 2: for LLVM artifacts built on CI via `download-ci-llvm`.
//
// It doesn't work for cases where the artifacts don't contain the linker, but it's
// best-effort: CI has `llvm.libzstd` and `lld` enabled on the x64 linux artifacts, so it
// will at least work there.
//
// If this can be improved and expanded to less common cases in the future, it should.
if config.target == "x86_64-unknown-linux-gnu"
&& config.host == config.target
&& is_lld_built_with_zstd(llvm_bin_dir).is_some()
{
return true;
}
}
// Otherwise, all hope is lost.
false
}
/// Takes a directive of the form `"<version1> [- <version2>]"`, returns the numeric representation
/// of `<version1>` and `<version2>` as tuple: `(<version1>, <version2>)`.
///
+20 -3
View File
@@ -1,5 +1,7 @@
use crate::common::{Config, KNOWN_CRATE_TYPES, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer};
use crate::directives::{DirectiveLine, IgnoreDecision, llvm_has_libzstd};
use crate::common::{
Config, KNOWN_CRATE_TYPES, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer, query_rustc_output,
};
use crate::directives::{DirectiveLine, IgnoreDecision};
pub(super) fn handle_needs(
cache: &CachedNeedsConditions,
@@ -377,7 +379,7 @@ pub(super) fn load(config: &Config) -> Self {
.join(if config.host.contains("windows") { "rust-lld.exe" } else { "rust-lld" })
.exists(),
llvm_zstd: llvm_has_libzstd(&config),
llvm_zstd: llvm_has_zstd(&config),
dlltool: find_dlltool(&config),
symlinks: has_symlinks(),
}
@@ -428,3 +430,18 @@ fn has_symlinks() -> bool {
fn has_symlinks() -> bool {
true
}
fn llvm_has_zstd(config: &Config) -> bool {
// The compiler already knows whether LLVM was built with zstd or not,
// so compiletest can just ask the compiler.
let output = query_rustc_output(
config,
&["-Zunstable-options", "--print=backend-has-zstd"],
Default::default(),
);
match output.trim() {
"true" => true,
"false" => false,
_ => panic!("unexpected output from `--print=backend-has-zstd`: {output:?}"),
}
}
+23 -29
View File
@@ -48,29 +48,15 @@ macro_rules! assert_approx_eq {
};
}
/// From IEEE 754 a Signaling NaN for single precision has the following representation:
/// ```
/// s | 1111 1111 | 0x..x
/// ````
/// Were at least one `x` is a 1.
///
/// This sNaN has the following representation and is used for testing purposes.:
/// ```
/// 0 | 1111111 | 01..0
/// ```
const SNAN_F32: f32 = f32::from_bits(0x7fa00000);
/// From IEEE 754 a Signaling NaN for double precision has the following representation:
/// ```
/// s | 1111 1111 111 | 0x..x
/// ````
/// Were at least one `x` is a 1.
///
/// This sNaN has the following representation and is used for testing purposes.:
/// ```
/// 0 | 1111 1111 111 | 01..0
/// ```
const SNAN_F64: f64 = f64::from_bits(0x7ff4000000000000);
/// We turn the quiet NaN f*::NAN into a signaling one by flipping the first (most significant)
/// two bits of the mantissa. For this we have to shift by `MANTISSA_DIGITS-3` because:
/// we subtract 1 as the actual mantissa is 1 bit smaller, and 2 more as that's the width
/// if the value we are shifting.
const F16_SNAN: f16 = f16::from_bits(f16::NAN.to_bits() ^ (0b11 << (f16::MANTISSA_DIGITS - 3)));
const F32_SNAN: f32 = f32::from_bits(f32::NAN.to_bits() ^ (0b11 << (f32::MANTISSA_DIGITS - 3)));
const F64_SNAN: f64 = f64::from_bits(f64::NAN.to_bits() ^ (0b11 << (f64::MANTISSA_DIGITS - 3)));
const F128_SNAN: f128 =
f128::from_bits(f128::NAN.to_bits() ^ (0b11 << (f128::MANTISSA_DIGITS - 3)));
fn main() {
basic();
@@ -757,6 +743,8 @@ fn ops() {
assert_eq(f16::NAN.max(-9.0), -9.0);
assert_eq((9.0_f16).min(f16::NAN), 9.0);
assert_eq((-9.0_f16).max(f16::NAN), -9.0);
assert_eq(F16_SNAN.min(9.0), 9.0);
assert_eq((-9.0_f16).max(F16_SNAN), -9.0);
// f32 min/max
assert_eq((1.0 as f32).max(-1.0), 1.0);
@@ -765,6 +753,8 @@ fn ops() {
assert_eq(f32::NAN.max(-9.0), -9.0);
assert_eq((9.0 as f32).min(f32::NAN), 9.0);
assert_eq((-9.0 as f32).max(f32::NAN), -9.0);
assert_eq(F32_SNAN.min(9.0), 9.0);
assert_eq((-9.0_f32).max(F32_SNAN), -9.0);
// f64 min/max
assert_eq((1.0 as f64).max(-1.0), 1.0);
@@ -773,6 +763,8 @@ fn ops() {
assert_eq(f64::NAN.max(-9.0), -9.0);
assert_eq((9.0 as f64).min(f64::NAN), 9.0);
assert_eq((-9.0 as f64).max(f64::NAN), -9.0);
assert_eq(F64_SNAN.min(9.0), 9.0);
assert_eq((-9.0_f64).max(F64_SNAN), -9.0);
// f128 min/max
assert_eq((1.0_f128).max(-1.0), 1.0);
@@ -781,6 +773,8 @@ fn ops() {
assert_eq(f128::NAN.max(-9.0), -9.0);
assert_eq((9.0_f128).min(f128::NAN), 9.0);
assert_eq((-9.0_f128).max(f128::NAN), -9.0);
assert_eq(F128_SNAN.min(9.0), 9.0);
assert_eq((-9.0_f128).max(F128_SNAN), -9.0);
// f16 copysign
assert_eq(3.5_f16.copysign(0.42), 3.5_f16);
@@ -1548,15 +1542,15 @@ fn test_operations_f128(a: f128, b: f128) {
test_operations_f128(25., 18.);
// SNaN^0 = (1 | NaN)
check_nondet(|| f32::powf(SNAN_F32, 0.0).is_nan());
check_nondet(|| f64::powf(SNAN_F64, 0.0).is_nan());
check_nondet(|| f32::powf(F32_SNAN, 0.0).is_nan());
check_nondet(|| f64::powf(F64_SNAN, 0.0).is_nan());
// 1^SNaN = (1 | NaN)
check_nondet(|| f32::powf(1.0, SNAN_F32).is_nan());
check_nondet(|| f64::powf(1.0, SNAN_F64).is_nan());
check_nondet(|| f32::powf(1.0, F32_SNAN).is_nan());
check_nondet(|| f64::powf(1.0, F64_SNAN).is_nan());
// same as powf (keep it consistent):
// x^SNaN = (1 | NaN)
check_nondet(|| f32::powi(SNAN_F32, 0).is_nan());
check_nondet(|| f64::powi(SNAN_F64, 0).is_nan());
check_nondet(|| f32::powi(F32_SNAN, 0).is_nan());
check_nondet(|| f64::powi(F64_SNAN, 0).is_nan());
}
@@ -11,11 +11,11 @@
#![crate_type = "lib"]
#![feature(new_range_api)]
use std::range::{IterRangeFrom, RangeFrom};
use std::range::{RangeFrom, RangeFromIter};
// CHECK-LABEL: @iterrangefrom_remainder(
#[no_mangle]
pub unsafe fn iterrangefrom_remainder(x: IterRangeFrom<i32>) -> RangeFrom<i32> {
pub unsafe fn iterrangefrom_remainder(x: RangeFromIter<i32>) -> RangeFrom<i32> {
// DEBUG: i32 noundef %x
// NOCHECKS: i32 noundef returned %x
// DEBUG: br i1
@@ -2,6 +2,6 @@
error: unknown print request: `xxx`
|
- = help: valid print requests are: `calling-conventions`, `cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `tls-models`
+ = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models`
+ = help: valid print requests are: `all-target-specs-json`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models`
= help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information
@@ -1,5 +1,5 @@
error: unknown print request: `xxx`
|
= help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models`
= help: valid print requests are: `all-target-specs-json`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models`
= help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information
+1 -1
View File
@@ -43,7 +43,7 @@ Options:
--print <INFO>[=<FILE>]
Compiler information to print on stdout (or to a file)
INFO may be one of
<all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|target-spec-json-schema|tls-models>.
<all-target-specs-json|backend-has-zstd|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|target-spec-json-schema|tls-models>.
-g Equivalent to -C debuginfo=2
-O Equivalent to -C opt-level=3
-o <FILENAME> Write output to FILENAME
+1 -1
View File
@@ -43,7 +43,7 @@ Options:
--print <INFO>[=<FILE>]
Compiler information to print on stdout (or to a file)
INFO may be one of
<all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|target-spec-json-schema|tls-models>.
<all-target-specs-json|backend-has-zstd|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|target-spec-json-schema|tls-models>.
-g Equivalent to -C debuginfo=2
-O Equivalent to -C opt-level=3
-o <FILENAME> Write output to FILENAME
@@ -0,0 +1,10 @@
//! regression test for <https://github.com/rust-lang/rust/issues/148467>
//! Ensure the diagnostic suggests `for &(mut x) ...` (parenthesized) instead of `&mut x`.
fn main() {
let nums: &[u32] = &[1, 2, 3];
for &num in nums {
num *= 2; //~ ERROR cannot assign twice to immutable variable `num`
println!("{num}");
}
}
@@ -0,0 +1,16 @@
error[E0384]: cannot assign twice to immutable variable `num`
--> $DIR/borrowck-for-loop-deref-pattern-assignment.rs:7:9
|
LL | for &num in nums {
| --- first assignment to `num`
LL | num *= 2;
| ^^^^^^^^ cannot assign twice to immutable variable
|
help: consider making this binding mutable
|
LL | for &(mut num) num in nums {
| +++++++++
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0384`.
@@ -0,0 +1,13 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/141845>
//! Checks const resolution stability when using inherent associated types
//! and generic const arguments.
//@compile-flags: --crate-type=lib
#![expect(incomplete_features)]
#![feature(inherent_associated_types, min_generic_const_args)]
trait Trait {}
struct Struct<const N: usize>;
type Alias<T: Trait> = Struct<{ Struct::N }>;
//~^ ERROR: missing generics for struct `Struct` [E0107]
@@ -0,0 +1,19 @@
error[E0107]: missing generics for struct `Struct`
--> $DIR/resolution-with-inherent-associated-types.rs:12:33
|
LL | type Alias<T: Trait> = Struct<{ Struct::N }>;
| ^^^^^^ expected 1 generic argument
|
note: struct defined here, with 1 generic parameter: `N`
--> $DIR/resolution-with-inherent-associated-types.rs:10:8
|
LL | struct Struct<const N: usize>;
| ^^^^^^ --------------
help: add missing generic argument
|
LL | type Alias<T: Trait> = Struct<{ Struct<N>::N }>;
| +++
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0107`.
@@ -3,6 +3,7 @@
//~| ERROR functions delegation is not yet fully implemented
dbg!(b);
//~^ ERROR missing lifetime specifier
//~| ERROR `fn() {b}` doesn't implement `Debug`
}
fn main() {}
@@ -20,7 +20,7 @@ LL | / reuse a as b {
LL | |
LL | |
LL | | dbg!(b);
LL | |
... |
LL | | }
| |_^
|
@@ -28,7 +28,19 @@ LL | | }
= help: add `#![feature(fn_delegation)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 3 previous errors
error[E0277]: `fn() {b}` doesn't implement `Debug`
--> $DIR/ice-line-bounds-issue-148732.rs:4:5
|
LL | reuse a as b {
| - consider calling this function
...
LL | dbg!(b);
| ^^^^^^^ the trait `Debug` is not implemented for fn item `fn() {b}`
|
= help: use parentheses to call this function: `b()`
= note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
Some errors have detailed explanations: E0106, E0425, E0658.
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0106, E0277, E0425, E0658.
For more information about an error, try `rustc --explain E0106`.
@@ -0,0 +1,13 @@
#![allow(incomplete_features)]
#![feature(fn_delegation)]
reuse a as b {
//~^ ERROR cannot find function `a` in this scope [E0425]
|| {
use std::ops::Add;
x.add
//~^ ERROR cannot find value `x` in this scope [E0425]
}
}
fn main() {}
@@ -0,0 +1,15 @@
error[E0425]: cannot find function `a` in this scope
--> $DIR/unused-import-ice-144594.rs:4:7
|
LL | reuse a as b {
| ^ not found in this scope
error[E0425]: cannot find value `x` in this scope
--> $DIR/unused-import-ice-144594.rs:8:9
|
LL | x.add
| ^ not found in this scope
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0425`.
+10
View File
@@ -3,6 +3,16 @@ error[E0425]: cannot find value `x` in this scope
|
LL | x + 1;
| ^ not found in this scope
|
help: an identifier with the same name is defined here, but is not accessible due to macro hygiene
--> $DIR/pattern-macro.rs:1:28
|
LL | macro_rules! foo { () => ( x ) }
| ^
...
LL | let foo!() = 2;
| ------ in this macro invocation
= note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 1 previous error
@@ -3,5 +3,5 @@ error: Argument to option 'print' missing
--print <INFO>[=<FILE>]
Compiler information to print on stdout (or to a file)
INFO may be one of
<all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|target-spec-json-schema|tls-models>.
<all-target-specs-json|backend-has-zstd|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|target-spec-json-schema|tls-models>.
+1 -1
View File
@@ -1,5 +1,5 @@
error: unknown print request: `yyyy`
|
= help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models`
= help: valid print requests are: `all-target-specs-json`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models`
= help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information
@@ -0,0 +1,9 @@
macro_rules! let_it { {} => { let it = (); } }
macro_rules! print_it { {} => { println!("{:?}", it); } }
//~^ ERROR cannot find value `it` in this scope
fn main() {
let_it!();
let () = it; //~ ERROR cannot find value `it` in this scope
print_it!();
}
@@ -0,0 +1,38 @@
error[E0425]: cannot find value `it` in this scope
--> $DIR/macro-hygiene-help-issue-149604.rs:7:14
|
LL | let () = it;
| ^^ not found in this scope
|
help: an identifier with the same name is defined here, but is not accessible due to macro hygiene
--> $DIR/macro-hygiene-help-issue-149604.rs:1:35
|
LL | macro_rules! let_it { {} => { let it = (); } }
| ^^
...
LL | let_it!();
| --------- in this macro invocation
= note: this error originates in the macro `let_it` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0425]: cannot find value `it` in this scope
--> $DIR/macro-hygiene-help-issue-149604.rs:2:50
|
LL | macro_rules! print_it { {} => { println!("{:?}", it); } }
| ^^ not found in this scope
...
LL | print_it!();
| ----------- in this macro invocation
|
help: an identifier with the same name is defined here, but is not accessible due to macro hygiene
--> $DIR/macro-hygiene-help-issue-149604.rs:1:35
|
LL | macro_rules! let_it { {} => { let it = (); } }
| ^^
...
LL | let_it!();
| --------- in this macro invocation
= note: this error originates in the macro `print_it` which comes from the expansion of the macro `let_it` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0425`.
+3 -3
View File
@@ -17,8 +17,8 @@ fn main() {
let c: core::range::RangeInclusive<u8> = 4..=5;
let d: core::range::RangeToInclusive<u8> = ..=3;
let _: core::range::IterRangeFrom<u8> = a.into_iter();
let _: core::range::IterRange<u8> = b.into_iter();
let _: core::range::IterRangeInclusive<u8> = c.into_iter();
let _: core::range::RangeFromIter<u8> = a.into_iter();
let _: core::range::RangeIter<u8> = b.into_iter();
let _: core::range::RangeInclusiveIter<u8> = c.into_iter();
// RangeToInclusive has no Iterator implementation
}
@@ -0,0 +1,8 @@
//! Check that `--print=backend-has-zstd` is unstable.
//!
//! That print value is intended for use by compiletest, and should probably
//! never be stabilized in this form.
//@ compile-flags: --print=backend-has-zstd
//~? ERROR: the `-Z unstable-options` flag must also be passed
@@ -0,0 +1,2 @@
error: the `-Z unstable-options` flag must also be passed to enable the `backend-has-zstd` print option
@@ -1,6 +1,6 @@
error: unknown print request: `lints`
|
= help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models`
= help: valid print requests are: `all-target-specs-json`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models`
= help: use `-Whelp` to print a list of lints
= help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information
@@ -30,6 +30,16 @@ error[E0425]: cannot find value `local_def` in this scope
|
LL | local_def;
| ^^^^^^^^^ help: a local variable with a similar name exists: `local_use`
|
help: an identifier with the same name is defined here, but is not accessible due to macro hygiene
--> $DIR/gen-macro-rules-hygiene.rs:13:1
|
LL | gen_macro_rules!();
| ^^^^^^^^^^^^^^^^^^
...
LL | generated!();
| ------------ in this macro invocation
= note: this error originates in the macro `generated` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors
@@ -606,6 +606,13 @@ error[E0425]: cannot find value `local_def` in this scope
|
LL | local_def;
| ^^^^^^^^^ help: a local variable with a similar name exists: `local_use`
|
help: an identifier with the same name is defined here, but is not accessible due to macro hygiene
--> $DIR/mixed-site-span.rs:23:9
|
LL | proc_macro_rules!();
| ^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `proc_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 52 previous errors