mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
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:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
///
|
||||
/// ```
|
||||
|
||||
@@ -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
|
||||
///
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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]
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>)`.
|
||||
///
|
||||
|
||||
@@ -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:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
+2
-2
@@ -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
-1
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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`.
|
||||
@@ -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,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`.
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user