Auto merge of #142142 - jhpratt:rollup-frlezq2, r=jhpratt

Rollup of 8 pull requests

Successful merges:

 - rust-lang/rust#137992 (Stabilise `os_string_pathbuf_leak`)
 - rust-lang/rust#141558 (Limit the size of cgu names when using the `-Zhuman-readable-cgu-name…)
 - rust-lang/rust#141797 (compiler: set Apple frame pointers by architecture)
 - rust-lang/rust#141857 (coretests: move float tests from num to floats module and use a more flexible macro to generate them)
 - rust-lang/rust#142045 (Make obligation cause code suggestions verbose)
 - rust-lang/rust#142076 (Check documentation of bootstrap in PR CI)
 - rust-lang/rust#142110 (Add solaris targets to build-manifest)
 - rust-lang/rust#142131 (Make cast suggestions verbose)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors
2025-06-07 06:20:45 +00:00
51 changed files with 815 additions and 570 deletions

View File

@@ -380,20 +380,21 @@ impl<'a, 'tcx> CastCheck<'tcx> {
err.span_label(self.span, "invalid cast");
if self.expr_ty.is_numeric() {
if self.expr_ty == fcx.tcx.types.u32 {
match fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) {
Ok(snippet) => err.span_suggestion(
self.span,
"try `char::from_u32` instead",
format!("char::from_u32({snippet})"),
Applicability::MachineApplicable,
),
Err(_) => err.span_help(self.span, "try `char::from_u32` instead"),
};
err.multipart_suggestion(
"consider using `char::from_u32` instead",
vec![
(self.expr_span.shrink_to_lo(), "char::from_u32(".to_string()),
(self.expr_span.shrink_to_hi().to(self.cast_span), ")".to_string()),
],
Applicability::MachineApplicable,
);
} else if self.expr_ty == fcx.tcx.types.i8 {
err.span_help(self.span, "try casting from `u8` instead");
err.span_help(self.span, "consider casting from `u8` instead");
} else {
err.span_help(self.span, "try `char::from_u32` instead (via a `u32`)");
err.span_help(
self.span,
"consider using `char::from_u32` instead (via a `u32`)",
);
};
}
err.emit();
@@ -494,11 +495,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
self.cast_ty.kind(),
ty::FnDef(..) | ty::FnPtr(..) | ty::Closure(..)
) {
let mut label = true;
// Check `impl From<self.expr_ty> for self.cast_ty {}` for accurate suggestion:
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span)
&& let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::From)
{
if let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::From) {
let ty = fcx.resolve_vars_if_possible(self.cast_ty);
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
if fcx
@@ -506,26 +504,22 @@ impl<'a, 'tcx> CastCheck<'tcx> {
.type_implements_trait(from_trait, [ty, expr_ty], fcx.param_env)
.must_apply_modulo_regions()
{
label = false;
if let ty::Adt(def, args) = self.cast_ty.kind() {
err.span_suggestion_verbose(
self.span,
"consider using the `From` trait instead",
format!(
"{}::from({})",
fcx.tcx.value_path_str_with_args(def.did(), args),
snippet
),
Applicability::MaybeIncorrect,
);
let to_ty = if let ty::Adt(def, args) = self.cast_ty.kind() {
fcx.tcx.value_path_str_with_args(def.did(), args)
} else {
err.span_suggestion(
self.span,
"consider using the `From` trait instead",
format!("{}::from({})", self.cast_ty, snippet),
Applicability::MaybeIncorrect,
);
self.cast_ty.to_string()
};
err.multipart_suggestion(
"consider using the `From` trait instead",
vec![
(self.expr_span.shrink_to_lo(), format!("{to_ty}::from(")),
(
self.expr_span.shrink_to_hi().to(self.cast_span),
")".to_string(),
),
],
Applicability::MaybeIncorrect,
);
}
}
@@ -548,11 +542,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
)
};
if label {
err.span_label(self.span, msg);
} else {
err.note(msg);
}
err.span_label(self.span, msg);
if let Some(note) = note {
err.note(note);
@@ -654,38 +644,22 @@ impl<'a, 'tcx> CastCheck<'tcx> {
match self.expr_ty.kind() {
ty::Ref(_, _, mt) => {
let mtstr = mt.prefix_str();
match fcx.tcx.sess.source_map().span_to_snippet(self.cast_span) {
Ok(s) => {
err.span_suggestion(
self.cast_span,
"try casting to a reference instead",
format!("&{mtstr}{s}"),
Applicability::MachineApplicable,
);
}
Err(_) => {
let msg = format!("did you mean `&{mtstr}{tstr}`?");
err.span_help(self.cast_span, msg);
}
}
err.span_suggestion_verbose(
self.cast_span.shrink_to_lo(),
"consider casting to a reference instead",
format!("&{mtstr}"),
Applicability::MachineApplicable,
);
}
ty::Adt(def, ..) if def.is_box() => {
match fcx.tcx.sess.source_map().span_to_snippet(self.cast_span) {
Ok(s) => {
err.span_suggestion(
self.cast_span,
"you can cast to a `Box` instead",
format!("Box<{s}>"),
Applicability::MachineApplicable,
);
}
Err(_) => {
err.span_help(
self.cast_span,
format!("you might have meant `Box<{tstr}>`"),
);
}
}
err.multipart_suggestion(
"you can cast to a `Box` instead",
vec![
(self.cast_span.shrink_to_lo(), "Box<".to_string()),
(self.cast_span.shrink_to_hi(), ">".to_string()),
],
Applicability::MachineApplicable,
);
}
_ => {
err.span_help(self.expr_span, "consider using a box or reference as appropriate");

View File

@@ -51,6 +51,7 @@
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(ptr_alignment_type)]
#![feature(round_char_boundary)]
#![feature(rustc_attrs)]
#![feature(rustdoc_internals)]
#![feature(trusted_len)]

View File

@@ -1,3 +1,4 @@
use std::borrow::Cow;
use std::fmt;
use std::hash::Hash;
@@ -468,6 +469,29 @@ impl<'tcx> CodegenUnit<'tcx> {
hash.as_u128().to_base_fixed_len(CASE_INSENSITIVE)
}
pub fn shorten_name(human_readable_name: &str) -> Cow<'_, str> {
// Set a limit a somewhat below the common platform limits for file names.
const MAX_CGU_NAME_LENGTH: usize = 200;
const TRUNCATED_NAME_PREFIX: &str = "-trunc-";
if human_readable_name.len() > MAX_CGU_NAME_LENGTH {
let mangled_name = Self::mangle_name(human_readable_name);
// Determine a safe byte offset to truncate the name to
let truncate_to = human_readable_name.floor_char_boundary(
MAX_CGU_NAME_LENGTH - TRUNCATED_NAME_PREFIX.len() - mangled_name.len(),
);
format!(
"{}{}{}",
&human_readable_name[..truncate_to],
TRUNCATED_NAME_PREFIX,
mangled_name
)
.into()
} else {
// If the name is short enough, we can just return it as is.
human_readable_name.into()
}
}
pub fn compute_size_estimate(&mut self) {
// The size of a codegen unit as the sum of the sizes of the items
// within it.
@@ -604,7 +628,7 @@ impl<'tcx> CodegenUnitNameBuilder<'tcx> {
let cgu_name = self.build_cgu_name_no_mangle(cnum, components, special_suffix);
if self.tcx.sess.opts.unstable_opts.human_readable_cgu_names {
cgu_name
Symbol::intern(&CodegenUnit::shorten_name(cgu_name.as_str()))
} else {
Symbol::intern(&CodegenUnit::mangle_name(cgu_name.as_str()))
}

View File

@@ -461,15 +461,15 @@ fn merge_codegen_units<'tcx>(
for cgu in codegen_units.iter_mut() {
if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) {
if cx.tcx.sess.opts.unstable_opts.human_readable_cgu_names {
cgu.set_name(Symbol::intern(new_cgu_name));
let new_cgu_name = if cx.tcx.sess.opts.unstable_opts.human_readable_cgu_names {
Symbol::intern(&CodegenUnit::shorten_name(new_cgu_name))
} else {
// If we don't require CGU names to be human-readable,
// we use a fixed length hash of the composite CGU name
// instead.
let new_cgu_name = CodegenUnit::mangle_name(new_cgu_name);
cgu.set_name(Symbol::intern(&new_cgu_name));
}
Symbol::intern(&CodegenUnit::mangle_name(new_cgu_name))
};
cgu.set_name(new_cgu_name);
}
}

View File

@@ -124,7 +124,13 @@ pub(crate) fn base(
// to v4, so we do the same.
// https://github.com/llvm/llvm-project/blob/378778a0d10c2f8d5df8ceff81f95b6002984a4b/clang/lib/Driver/ToolChains/Darwin.cpp#L1203
default_dwarf_version: 4,
frame_pointer: FramePointer::Always,
frame_pointer: match arch {
// clang ignores `-fomit-frame-pointer` for Armv7, it only accepts `-momit-leaf-frame-pointer`
Armv7k | Armv7s => FramePointer::Always,
// clang supports omitting frame pointers for the rest, but... don't?
Arm64 | Arm64e | Arm64_32 => FramePointer::NonLeaf,
I386 | I686 | X86_64 | X86_64h => FramePointer::Always,
},
has_rpath: true,
dll_suffix: ".dylib".into(),
archive_format: "darwin".into(),

View File

@@ -1,5 +1,5 @@
use crate::spec::base::apple::{Arch, TargetAbi, base};
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
pub(crate) fn target() -> Target {
let (opts, llvm_target, arch) = base("macos", Arch::Arm64, TargetAbi::Normal);
@@ -17,7 +17,6 @@ pub(crate) fn target() -> Target {
arch,
options: TargetOptions {
mcount: "\u{1}mcount".into(),
frame_pointer: FramePointer::NonLeaf,
cpu: "apple-m1".into(),
max_atomic_width: Some(128),
// FIXME: The leak sanitizer currently fails the tests, see #88132.

View File

@@ -1,5 +1,5 @@
use crate::spec::base::apple::{Arch, TargetAbi, base};
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
pub(crate) fn target() -> Target {
let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Normal);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
max_atomic_width: Some(128),
frame_pointer: FramePointer::NonLeaf,
supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
..opts
},

View File

@@ -1,5 +1,5 @@
use crate::spec::base::apple::{Arch, TargetAbi, base};
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
pub(crate) fn target() -> Target {
let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::MacCatalyst);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a12".into(),
max_atomic_width: Some(128),
frame_pointer: FramePointer::NonLeaf,
supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD,
..opts
},

View File

@@ -1,5 +1,5 @@
use crate::spec::base::apple::{Arch, TargetAbi, base};
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
pub(crate) fn target() -> Target {
let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Simulator);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
max_atomic_width: Some(128),
frame_pointer: FramePointer::NonLeaf,
supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
..opts
},

View File

@@ -1,5 +1,5 @@
use crate::spec::base::apple::{Arch, TargetAbi, base};
use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
use crate::spec::{Target, TargetMetadata, TargetOptions};
pub(crate) fn target() -> Target {
let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Normal);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
max_atomic_width: Some(128),
frame_pointer: FramePointer::NonLeaf,
..opts
},
}

View File

@@ -1,5 +1,5 @@
use crate::spec::base::apple::{Arch, TargetAbi, base};
use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
use crate::spec::{Target, TargetMetadata, TargetOptions};
pub(crate) fn target() -> Target {
let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Simulator);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
max_atomic_width: Some(128),
frame_pointer: FramePointer::NonLeaf,
..opts
},
}

View File

@@ -1,5 +1,5 @@
use crate::spec::base::apple::{Arch, TargetAbi, base};
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
pub(crate) fn target() -> Target {
let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Normal);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a16".into(),
max_atomic_width: Some(128),
frame_pointer: FramePointer::NonLeaf,
supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
..opts
},

View File

@@ -1,5 +1,5 @@
use crate::spec::base::apple::{Arch, TargetAbi, base};
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
pub(crate) fn target() -> Target {
let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Simulator);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a16".into(),
max_atomic_width: Some(128),
frame_pointer: FramePointer::NonLeaf,
supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
..opts
},

View File

@@ -1,5 +1,5 @@
use crate::spec::base::apple::{Arch, TargetAbi, base};
use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
use crate::spec::{Target, TargetMetadata, TargetOptions};
pub(crate) fn target() -> Target {
let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetAbi::Simulator);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
max_atomic_width: Some(128),
frame_pointer: FramePointer::NonLeaf,
..opts
},
}

View File

@@ -1,5 +1,5 @@
use crate::spec::base::apple::{Arch, TargetAbi, base};
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
pub(crate) fn target() -> Target {
let (opts, llvm_target, arch) = base("macos", Arch::Arm64e, TargetAbi::Normal);
@@ -17,7 +17,6 @@ pub(crate) fn target() -> Target {
arch,
options: TargetOptions {
mcount: "\u{1}mcount".into(),
frame_pointer: FramePointer::NonLeaf,
cpu: "apple-m1".into(),
max_atomic_width: Some(128),
// FIXME: The leak sanitizer currently fails the tests, see #88132.

View File

@@ -1,5 +1,5 @@
use crate::spec::base::apple::{Arch, TargetAbi, base};
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
pub(crate) fn target() -> Target {
let (opts, llvm_target, arch) = base("ios", Arch::Arm64e, TargetAbi::Normal);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a12,+v8.3a,+pauth".into(),
max_atomic_width: Some(128),
frame_pointer: FramePointer::NonLeaf,
supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
..opts
},

View File

@@ -1,5 +1,5 @@
use crate::spec::base::apple::{Arch, TargetAbi, base};
use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
use crate::spec::{Target, TargetMetadata, TargetOptions};
pub(crate) fn target() -> Target {
let (opts, llvm_target, arch) = base("tvos", Arch::Arm64e, TargetAbi::Normal);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a12,+v8.3a,+pauth".into(),
max_atomic_width: Some(128),
frame_pointer: FramePointer::NonLeaf,
..opts
},
}

View File

@@ -1,5 +1,5 @@
use crate::spec::base::apple::{Arch, TargetAbi, base};
use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
use crate::spec::{Target, TargetMetadata, TargetOptions};
pub(crate) fn target() -> Target {
let (opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal);
@@ -16,11 +16,6 @@ pub(crate) fn target() -> Target {
i128:128-f64:32:64-f80:128-n8:16:32-S128"
.into(),
arch,
options: TargetOptions {
mcount: "\u{1}mcount".into(),
max_atomic_width: Some(64),
frame_pointer: FramePointer::Always,
..opts
},
options: TargetOptions { mcount: "\u{1}mcount".into(), max_atomic_width: Some(64), ..opts },
}
}

View File

@@ -1,5 +1,5 @@
use crate::spec::base::apple::{Arch, TargetAbi, base};
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
pub(crate) fn target() -> Target {
let (opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
mcount: "\u{1}mcount".into(),
max_atomic_width: Some(128), // penryn+ supports cmpxchg16b
frame_pointer: FramePointer::Always,
supported_sanitizers: SanitizerSet::ADDRESS
| SanitizerSet::CFI
| SanitizerSet::LEAK

View File

@@ -1,10 +1,9 @@
use crate::spec::base::apple::{Arch, TargetAbi, base};
use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
pub(crate) fn target() -> Target {
let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64h, TargetAbi::Normal);
opts.max_atomic_width = Some(128);
opts.frame_pointer = FramePointer::Always;
opts.supported_sanitizers =
SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;

View File

@@ -1411,7 +1411,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
err.span_suggestion(
err.span_suggestion_verbose(
obligation.cause.span.shrink_to_lo(),
format!(
"consider borrowing the value, since `&{self_ty}` can be coerced into `{target_ty}`"
@@ -1574,7 +1574,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
.span_extend_while_whitespace(expr_span)
.shrink_to_hi()
.to(await_expr.span.shrink_to_hi());
err.span_suggestion(
err.span_suggestion_verbose(
removal_span,
"remove the `.await`",
"",
@@ -2126,7 +2126,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
));
if !assoc_item.is_impl_trait_in_trait() {
err.span_suggestion(
err.span_suggestion_verbose(
span,
"use the fully qualified path to an implementation",
format!(
@@ -2924,12 +2924,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
);
let sm = tcx.sess.source_map();
if matches!(is_constable, IsConstable::Fn | IsConstable::Ctor)
&& let Ok(snip) = sm.span_to_snippet(elt_span)
&& let Ok(_) = sm.span_to_snippet(elt_span)
{
err.span_suggestion(
elt_span,
err.multipart_suggestion(
"create an inline `const` block",
format!("const {{ {snip} }}"),
vec![
(elt_span.shrink_to_lo(), "const { ".to_string()),
(elt_span.shrink_to_hi(), " }".to_string()),
],
Applicability::MachineApplicable,
);
} else {
@@ -3127,13 +3129,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
err.help("change the field's type to have a statically known size");
err.span_suggestion(
err.span_suggestion_verbose(
span.shrink_to_lo(),
"borrowed types always have a statically known size",
"&",
Applicability::MachineApplicable,
);
err.multipart_suggestion(
err.multipart_suggestion_verbose(
"the `Box` type always has a statically known size and allocates its contents \
in the heap",
vec![

View File

@@ -52,6 +52,119 @@ macro_rules! assert_biteq {
};
}
mod const_asserts {
// Shadow some assert implementations that would otherwise not compile in a const-context.
// Every macro added here also needs to be added in the `float_test!` macro below.
macro_rules! assert_eq {
($left:expr, $right:expr $(,)?) => {
std::assert!($left == $right)
};
($left:expr, $right:expr, $($arg:tt)+) => {
std::assert!($left == $right, $($arg)+)
};
}
pub(crate) use assert_eq;
}
/// Generate float tests for all our float types, for compile-time and run-time behavior.
///
/// By default all tests run for all float types. Configuration can be applied via `attrs`.
///
/// ```ignore (this is only a sketch)
/// float_test! {
/// name: fn_name, /* function under test */
/// attrs: {
/// // Apply a configuration to the test for a single type
/// f16: #[cfg(target_has_reliable_f16_math)],
/// // Types can be excluded with `cfg(false)`
/// f64: #[cfg(false)],
/// },
/// test<Float> {
/// /* write tests here, using `Float` as the type */
/// }
/// }
macro_rules! float_test {
(
name: $name:ident,
attrs: {
$(const: #[ $($const_meta:meta),+ ] ,)?
$(f16: #[ $($f16_meta:meta),+ ] ,)?
$(const f16: #[ $($f16_const_meta:meta),+ ] ,)?
$(f32: #[ $($f32_meta:meta),+ ] ,)?
$(const f32: #[ $($f32_const_meta:meta),+ ] ,)?
$(f64: #[ $($f64_meta:meta),+ ] ,)?
$(const f64: #[ $($f64_const_meta:meta),+ ] ,)?
$(f128: #[ $($f128_meta:meta),+ ] ,)?
$(const f128: #[ $($f128_const_meta:meta),+ ] ,)?
},
test<$fty:ident> $test:block
) => {
mod $name {
#[test]
$( $( #[$f16_meta] )+ )?
fn test_f16() {
type $fty = f16;
$test
}
#[test]
$( $( #[$f32_meta] )+ )?
fn test_f32() {
type $fty = f32;
$test
}
#[test]
$( $( #[$f64_meta] )+ )?
fn test_f64() {
type $fty = f64;
$test
}
#[test]
$( $( #[$f128_meta] )+ )?
fn test_f128() {
type $fty = f128;
$test
}
$( $( #[$const_meta] )+ )?
mod const_ {
use $crate::floats::const_asserts::assert_eq;
#[test]
$( $( #[$f16_const_meta] )+ )?
fn test_f16() {
type $fty = f16;
const { $test }
}
#[test]
$( $( #[$f32_const_meta] )+ )?
fn test_f32() {
type $fty = f32;
const { $test }
}
#[test]
$( $( #[$f64_const_meta] )+ )?
fn test_f64() {
type $fty = f64;
const { $test }
}
#[test]
$( $( #[$f128_const_meta] )+ )?
fn test_f128() {
type $fty = f128;
const { $test }
}
}
}
};
}
/// Helper function for testing numeric operations
pub fn test_num<T>(ten: T, two: T)
where
@@ -75,3 +188,438 @@ mod f128;
mod f16;
mod f32;
mod f64;
float_test! {
name: min,
attrs: {
f16: #[cfg(any(miri, target_has_reliable_f16_math))],
f128: #[cfg(any(miri, target_has_reliable_f128_math))],
},
test<Float> {
assert_eq!((0.0 as Float).min(0.0), 0.0);
assert!((0.0 as Float).min(0.0).is_sign_positive());
assert_eq!((-0.0 as Float).min(-0.0), -0.0);
assert!((-0.0 as Float).min(-0.0).is_sign_negative());
assert_eq!((9.0 as Float).min(9.0), 9.0);
assert_eq!((-9.0 as Float).min(0.0), -9.0);
assert_eq!((0.0 as Float).min(9.0), 0.0);
assert!((0.0 as Float).min(9.0).is_sign_positive());
assert_eq!((-0.0 as Float).min(9.0), -0.0);
assert!((-0.0 as Float).min(9.0).is_sign_negative());
assert_eq!((-0.0 as Float).min(-9.0), -9.0);
assert_eq!(Float::INFINITY.min(9.0), 9.0);
assert_eq!((9.0 as Float).min(Float::INFINITY), 9.0);
assert_eq!(Float::INFINITY.min(-9.0), -9.0);
assert_eq!((-9.0 as Float).min(Float::INFINITY), -9.0);
assert_eq!(Float::NEG_INFINITY.min(9.0), Float::NEG_INFINITY);
assert_eq!((9.0 as Float).min(Float::NEG_INFINITY), Float::NEG_INFINITY);
assert_eq!(Float::NEG_INFINITY.min(-9.0), Float::NEG_INFINITY);
assert_eq!((-9.0 as Float).min(Float::NEG_INFINITY), Float::NEG_INFINITY);
assert_eq!(Float::NAN.min(9.0), 9.0);
assert_eq!(Float::NAN.min(-9.0), -9.0);
assert_eq!((9.0 as Float).min(Float::NAN), 9.0);
assert_eq!((-9.0 as Float).min(Float::NAN), -9.0);
assert!(Float::NAN.min(Float::NAN).is_nan());
}
}
float_test! {
name: max,
attrs: {
f16: #[cfg(any(miri, target_has_reliable_f16_math))],
f128: #[cfg(any(miri, target_has_reliable_f128_math))],
},
test<Float> {
assert_eq!((0.0 as Float).max(0.0), 0.0);
assert!((0.0 as Float).max(0.0).is_sign_positive());
assert_eq!((-0.0 as Float).max(-0.0), -0.0);
assert!((-0.0 as Float).max(-0.0).is_sign_negative());
assert_eq!((9.0 as Float).max(9.0), 9.0);
assert_eq!((-9.0 as Float).max(0.0), 0.0);
assert!((-9.0 as Float).max(0.0).is_sign_positive());
assert_eq!((-9.0 as Float).max(-0.0), -0.0);
assert!((-9.0 as Float).max(-0.0).is_sign_negative());
assert_eq!((0.0 as Float).max(9.0), 9.0);
assert_eq!((0.0 as Float).max(-9.0), 0.0);
assert!((0.0 as Float).max(-9.0).is_sign_positive());
assert_eq!((-0.0 as Float).max(-9.0), -0.0);
assert!((-0.0 as Float).max(-9.0).is_sign_negative());
assert_eq!(Float::INFINITY.max(9.0), Float::INFINITY);
assert_eq!((9.0 as Float).max(Float::INFINITY), Float::INFINITY);
assert_eq!(Float::INFINITY.max(-9.0), Float::INFINITY);
assert_eq!((-9.0 as Float).max(Float::INFINITY), Float::INFINITY);
assert_eq!(Float::NEG_INFINITY.max(9.0), 9.0);
assert_eq!((9.0 as Float).max(Float::NEG_INFINITY), 9.0);
assert_eq!(Float::NEG_INFINITY.max(-9.0), -9.0);
assert_eq!((-9.0 as Float).max(Float::NEG_INFINITY), -9.0);
assert_eq!(Float::NAN.max(9.0), 9.0);
assert_eq!(Float::NAN.max(-9.0), -9.0);
assert_eq!((9.0 as Float).max(Float::NAN), 9.0);
assert_eq!((-9.0 as Float).max(Float::NAN), -9.0);
assert!(Float::NAN.max(Float::NAN).is_nan());
}
}
float_test! {
name: minimum,
attrs: {
f16: #[cfg(any(miri, target_has_reliable_f16_math))],
f128: #[cfg(any(miri, target_has_reliable_f128_math))],
},
test<Float> {
assert_eq!((0.0 as Float).minimum(0.0), 0.0);
assert!((0.0 as Float).minimum(0.0).is_sign_positive());
assert_eq!((-0.0 as Float).minimum(0.0), -0.0);
assert!((-0.0 as Float).minimum(0.0).is_sign_negative());
assert_eq!((-0.0 as Float).minimum(-0.0), -0.0);
assert!((-0.0 as Float).minimum(-0.0).is_sign_negative());
assert_eq!((9.0 as Float).minimum(9.0), 9.0);
assert_eq!((-9.0 as Float).minimum(0.0), -9.0);
assert_eq!((0.0 as Float).minimum(9.0), 0.0);
assert!((0.0 as Float).minimum(9.0).is_sign_positive());
assert_eq!((-0.0 as Float).minimum(9.0), -0.0);
assert!((-0.0 as Float).minimum(9.0).is_sign_negative());
assert_eq!((-0.0 as Float).minimum(-9.0), -9.0);
assert_eq!(Float::INFINITY.minimum(9.0), 9.0);
assert_eq!((9.0 as Float).minimum(Float::INFINITY), 9.0);
assert_eq!(Float::INFINITY.minimum(-9.0), -9.0);
assert_eq!((-9.0 as Float).minimum(Float::INFINITY), -9.0);
assert_eq!(Float::NEG_INFINITY.minimum(9.0), Float::NEG_INFINITY);
assert_eq!((9.0 as Float).minimum(Float::NEG_INFINITY), Float::NEG_INFINITY);
assert_eq!(Float::NEG_INFINITY.minimum(-9.0), Float::NEG_INFINITY);
assert_eq!((-9.0 as Float).minimum(Float::NEG_INFINITY), Float::NEG_INFINITY);
assert!(Float::NAN.minimum(9.0).is_nan());
assert!(Float::NAN.minimum(-9.0).is_nan());
assert!((9.0 as Float).minimum(Float::NAN).is_nan());
assert!((-9.0 as Float).minimum(Float::NAN).is_nan());
assert!(Float::NAN.minimum(Float::NAN).is_nan());
}
}
float_test! {
name: maximum,
attrs: {
f16: #[cfg(any(miri, target_has_reliable_f16_math))],
f128: #[cfg(any(miri, target_has_reliable_f128_math))],
},
test<Float> {
assert_eq!((0.0 as Float).maximum(0.0), 0.0);
assert!((0.0 as Float).maximum(0.0).is_sign_positive());
assert_eq!((-0.0 as Float).maximum(0.0), 0.0);
assert!((-0.0 as Float).maximum(0.0).is_sign_positive());
assert_eq!((-0.0 as Float).maximum(-0.0), -0.0);
assert!((-0.0 as Float).maximum(-0.0).is_sign_negative());
assert_eq!((9.0 as Float).maximum(9.0), 9.0);
assert_eq!((-9.0 as Float).maximum(0.0), 0.0);
assert!((-9.0 as Float).maximum(0.0).is_sign_positive());
assert_eq!((-9.0 as Float).maximum(-0.0), -0.0);
assert!((-9.0 as Float).maximum(-0.0).is_sign_negative());
assert_eq!((0.0 as Float).maximum(9.0), 9.0);
assert_eq!((0.0 as Float).maximum(-9.0), 0.0);
assert!((0.0 as Float).maximum(-9.0).is_sign_positive());
assert_eq!((-0.0 as Float).maximum(-9.0), -0.0);
assert!((-0.0 as Float).maximum(-9.0).is_sign_negative());
assert_eq!(Float::INFINITY.maximum(9.0), Float::INFINITY);
assert_eq!((9.0 as Float).maximum(Float::INFINITY), Float::INFINITY);
assert_eq!(Float::INFINITY.maximum(-9.0), Float::INFINITY);
assert_eq!((-9.0 as Float).maximum(Float::INFINITY), Float::INFINITY);
assert_eq!(Float::NEG_INFINITY.maximum(9.0), 9.0);
assert_eq!((9.0 as Float).maximum(Float::NEG_INFINITY), 9.0);
assert_eq!(Float::NEG_INFINITY.maximum(-9.0), -9.0);
assert_eq!((-9.0 as Float).maximum(Float::NEG_INFINITY), -9.0);
assert!(Float::NAN.maximum(9.0).is_nan());
assert!(Float::NAN.maximum(-9.0).is_nan());
assert!((9.0 as Float).maximum(Float::NAN).is_nan());
assert!((-9.0 as Float).maximum(Float::NAN).is_nan());
assert!(Float::NAN.maximum(Float::NAN).is_nan());
}
}
float_test! {
name: midpoint,
attrs: {
f16: #[cfg(any(miri, target_has_reliable_f16_math))],
f128: #[cfg(any(miri, target_has_reliable_f128_math))],
},
test<Float> {
assert_eq!((0.5 as Float).midpoint(0.5), 0.5);
assert_eq!((0.5 as Float).midpoint(2.5), 1.5);
assert_eq!((3.0 as Float).midpoint(4.0), 3.5);
assert_eq!((-3.0 as Float).midpoint(4.0), 0.5);
assert_eq!((3.0 as Float).midpoint(-4.0), -0.5);
assert_eq!((-3.0 as Float).midpoint(-4.0), -3.5);
assert_eq!((0.0 as Float).midpoint(0.0), 0.0);
assert_eq!((-0.0 as Float).midpoint(-0.0), -0.0);
assert_eq!((-5.0 as Float).midpoint(5.0), 0.0);
assert_eq!(Float::MAX.midpoint(Float::MIN), 0.0);
assert_eq!(Float::MIN.midpoint(Float::MAX), -0.0);
assert_eq!(Float::MAX.midpoint(Float::MIN_POSITIVE), Float::MAX / 2.);
assert_eq!((-Float::MAX).midpoint(Float::MIN_POSITIVE), -Float::MAX / 2.);
assert_eq!(Float::MAX.midpoint(-Float::MIN_POSITIVE), Float::MAX / 2.);
assert_eq!((-Float::MAX).midpoint(-Float::MIN_POSITIVE), -Float::MAX / 2.);
assert_eq!((Float::MIN_POSITIVE).midpoint(Float::MAX), Float::MAX / 2.);
assert_eq!((Float::MIN_POSITIVE).midpoint(-Float::MAX), -Float::MAX / 2.);
assert_eq!((-Float::MIN_POSITIVE).midpoint(Float::MAX), Float::MAX / 2.);
assert_eq!((-Float::MIN_POSITIVE).midpoint(-Float::MAX), -Float::MAX / 2.);
assert_eq!(Float::MAX.midpoint(Float::MAX), Float::MAX);
assert_eq!(
(Float::MIN_POSITIVE).midpoint(Float::MIN_POSITIVE),
Float::MIN_POSITIVE
);
assert_eq!(
(-Float::MIN_POSITIVE).midpoint(-Float::MIN_POSITIVE),
-Float::MIN_POSITIVE
);
assert_eq!(Float::MAX.midpoint(5.0), Float::MAX / 2.0 + 2.5);
assert_eq!(Float::MAX.midpoint(-5.0), Float::MAX / 2.0 - 2.5);
assert_eq!(Float::INFINITY.midpoint(Float::INFINITY), Float::INFINITY);
assert_eq!(
Float::NEG_INFINITY.midpoint(Float::NEG_INFINITY),
Float::NEG_INFINITY
);
assert!(Float::NAN.midpoint(1.0).is_nan());
assert!((1.0 as Float).midpoint(Float::NAN).is_nan());
assert!(Float::NAN.midpoint(Float::NAN).is_nan());
}
}
// Separate test since the `for` loops cannot be run in `const`.
float_test! {
name: midpoint_large_magnitude,
attrs: {
const: #[cfg(false)],
// FIXME(f16_f128): `powi` does not work in Miri for these types
f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
},
test<Float> {
// test if large differences in magnitude are still correctly computed.
// NOTE: that because of how small x and y are, x + y can never overflow
// so (x + y) / 2.0 is always correct
// in particular, `2.pow(i)` will never be at the max exponent, so it could
// be safely doubled, while j is significantly smaller.
for i in Float::MAX_EXP.saturating_sub(64)..Float::MAX_EXP {
for j in 0..64u8 {
let large = (2.0 as Float).powi(i);
// a much smaller number, such that there is no chance of overflow to test
// potential double rounding in midpoint's implementation.
let small = (2.0 as Float).powi(Float::MAX_EXP - 1)
* Float::EPSILON
* Float::from(j);
let naive = (large + small) / 2.0;
let midpoint = large.midpoint(small);
assert_eq!(naive, midpoint);
}
}
}
}
float_test! {
name: abs,
attrs: {
f16: #[cfg(any(miri, target_has_reliable_f16_math))],
f128: #[cfg(any(miri, target_has_reliable_f128_math))],
},
test<Float> {
assert_eq!((-1.0 as Float).abs(), 1.0);
assert_eq!((1.0 as Float).abs(), 1.0);
assert_eq!(Float::NEG_INFINITY.abs(), Float::INFINITY);
assert_eq!(Float::INFINITY.abs(), Float::INFINITY);
}
}
float_test! {
name: copysign,
attrs: {
f16: #[cfg(any(miri, target_has_reliable_f16_math))],
f128: #[cfg(any(miri, target_has_reliable_f128_math))],
},
test<Float> {
assert_eq!((1.0 as Float).copysign(-2.0), -1.0);
assert_eq!((-1.0 as Float).copysign(2.0), 1.0);
assert_eq!(Float::INFINITY.copysign(-0.0), Float::NEG_INFINITY);
assert_eq!(Float::NEG_INFINITY.copysign(0.0), Float::INFINITY);
}
}
float_test! {
name: rem_euclid,
attrs: {
const: #[cfg(false)],
f16: #[cfg(any(miri, target_has_reliable_f16_math))],
f128: #[cfg(any(miri, target_has_reliable_f128_math))],
},
test<Float> {
assert!(Float::INFINITY.rem_euclid(42.0 as Float).is_nan());
assert_eq!((42.0 as Float).rem_euclid(Float::INFINITY), (42.0 as Float));
assert!((42.0 as Float).rem_euclid(Float::NAN).is_nan());
assert!(Float::INFINITY.rem_euclid(Float::INFINITY).is_nan());
assert!(Float::INFINITY.rem_euclid(Float::NAN).is_nan());
assert!(Float::NAN.rem_euclid(Float::INFINITY).is_nan());
}
}
float_test! {
name: div_euclid,
attrs: {
const: #[cfg(false)],
f16: #[cfg(any(miri, target_has_reliable_f16_math))],
f128: #[cfg(any(miri, target_has_reliable_f128_math))],
},
test<Float> {
assert_eq!((42.0 as Float).div_euclid(Float::INFINITY), 0.0);
assert!((42.0 as Float).div_euclid(Float::NAN).is_nan());
assert!(Float::INFINITY.div_euclid(Float::INFINITY).is_nan());
assert!(Float::INFINITY.div_euclid(Float::NAN).is_nan());
assert!(Float::NAN.div_euclid(Float::INFINITY).is_nan());
}
}
float_test! {
name: floor,
attrs: {
f16: #[cfg(any(miri, target_has_reliable_f16_math))],
f128: #[cfg(any(miri, target_has_reliable_f128_math))],
},
test<Float> {
assert_eq!((0.0 as Float).floor(), 0.0);
assert!((0.0 as Float).floor().is_sign_positive());
assert_eq!((-0.0 as Float).floor(), -0.0);
assert!((-0.0 as Float).floor().is_sign_negative());
assert_eq!((0.5 as Float).floor(), 0.0);
assert_eq!((-0.5 as Float).floor(), -1.0);
assert_eq!((1.5 as Float).floor(), 1.0);
assert_eq!(Float::MAX.floor(), Float::MAX);
assert_eq!(Float::MIN.floor(), Float::MIN);
assert_eq!(Float::MIN_POSITIVE.floor(), 0.0);
assert_eq!((-Float::MIN_POSITIVE).floor(), -1.0);
assert!(Float::NAN.floor().is_nan());
assert_eq!(Float::INFINITY.floor(), Float::INFINITY);
assert_eq!(Float::NEG_INFINITY.floor(), Float::NEG_INFINITY);
}
}
float_test! {
name: ceil,
attrs: {
f16: #[cfg(any(miri, target_has_reliable_f16_math))],
f128: #[cfg(any(miri, target_has_reliable_f128_math))],
},
test<Float> {
assert_eq!((0.0 as Float).ceil(), 0.0);
assert!((0.0 as Float).ceil().is_sign_positive());
assert_eq!((-0.0 as Float).ceil(), 0.0);
assert!((-0.0 as Float).ceil().is_sign_negative());
assert_eq!((0.5 as Float).ceil(), 1.0);
assert_eq!((-0.5 as Float).ceil(), 0.0);
assert_eq!(Float::MAX.ceil(), Float::MAX);
assert_eq!(Float::MIN.ceil(), Float::MIN);
assert_eq!(Float::MIN_POSITIVE.ceil(), 1.0);
assert_eq!((-Float::MIN_POSITIVE).ceil(), 0.0);
assert!(Float::NAN.ceil().is_nan());
assert_eq!(Float::INFINITY.ceil(), Float::INFINITY);
assert_eq!(Float::NEG_INFINITY.ceil(), Float::NEG_INFINITY);
}
}
float_test! {
name: round,
attrs: {
f16: #[cfg(any(miri, target_has_reliable_f16_math))],
f128: #[cfg(any(miri, target_has_reliable_f128_math))],
},
test<Float> {
assert_eq!((0.0 as Float).round(), 0.0);
assert!((0.0 as Float).round().is_sign_positive());
assert_eq!((-0.0 as Float).round(), -0.0);
assert!((-0.0 as Float).round().is_sign_negative());
assert_eq!((0.5 as Float).round(), 1.0);
assert_eq!((-0.5 as Float).round(), -1.0);
assert_eq!(Float::MAX.round(), Float::MAX);
assert_eq!(Float::MIN.round(), Float::MIN);
assert_eq!(Float::MIN_POSITIVE.round(), 0.0);
assert_eq!((-Float::MIN_POSITIVE).round(), 0.0);
assert!(Float::NAN.round().is_nan());
assert_eq!(Float::INFINITY.round(), Float::INFINITY);
assert_eq!(Float::NEG_INFINITY.round(), Float::NEG_INFINITY);
}
}
float_test! {
name: round_ties_even,
attrs: {
f16: #[cfg(any(miri, target_has_reliable_f16_math))],
f128: #[cfg(any(miri, target_has_reliable_f128_math))],
},
test<Float> {
assert_eq!((0.0 as Float).round_ties_even(), 0.0);
assert!((0.0 as Float).round_ties_even().is_sign_positive());
assert_eq!((-0.0 as Float).round_ties_even(), -0.0);
assert!((-0.0 as Float).round_ties_even().is_sign_negative());
assert_eq!((0.5 as Float).round_ties_even(), 0.0);
assert!((0.5 as Float).round_ties_even().is_sign_positive());
assert_eq!((-0.5 as Float).round_ties_even(), -0.0);
assert!((-0.5 as Float).round_ties_even().is_sign_negative());
assert_eq!(Float::MAX.round_ties_even(), Float::MAX);
assert_eq!(Float::MIN.round_ties_even(), Float::MIN);
assert_eq!(Float::MIN_POSITIVE.round_ties_even(), 0.0);
assert_eq!((-Float::MIN_POSITIVE).round_ties_even(), 0.0);
assert!(Float::NAN.round_ties_even().is_nan());
assert_eq!(Float::INFINITY.round_ties_even(), Float::INFINITY);
assert_eq!(Float::NEG_INFINITY.round_ties_even(), Float::NEG_INFINITY);
}
}
float_test! {
name: trunc,
attrs: {
f16: #[cfg(any(miri, target_has_reliable_f16_math))],
f128: #[cfg(any(miri, target_has_reliable_f128_math))],
},
test<Float> {
assert_eq!((0.0 as Float).trunc(), 0.0);
assert!((0.0 as Float).trunc().is_sign_positive());
assert_eq!((-0.0 as Float).trunc(), -0.0);
assert!((-0.0 as Float).trunc().is_sign_negative());
assert_eq!((0.5 as Float).trunc(), 0.0);
assert!((0.5 as Float).trunc().is_sign_positive());
assert_eq!((-0.5 as Float).trunc(), -0.0);
assert!((-0.5 as Float).trunc().is_sign_negative());
assert_eq!(Float::MAX.trunc(), Float::MAX);
assert_eq!(Float::MIN.trunc(), Float::MIN);
assert_eq!(Float::MIN_POSITIVE.trunc(), 0.0);
assert_eq!((-Float::MIN_POSITIVE).trunc(), 0.0);
assert!(Float::NAN.trunc().is_nan());
assert_eq!(Float::INFINITY.trunc(), Float::INFINITY);
assert_eq!(Float::NEG_INFINITY.trunc(), Float::NEG_INFINITY);
}
}
float_test! {
name: fract,
attrs: {
f16: #[cfg(any(miri, target_has_reliable_f16_math))],
f128: #[cfg(any(miri, target_has_reliable_f128_math))],
},
test<Float> {
assert_eq!((0.0 as Float).fract(), 0.0);
assert!((0.0 as Float).fract().is_sign_positive());
assert_eq!((-0.0 as Float).fract(), 0.0);
assert!((-0.0 as Float).fract().is_sign_positive());
assert_eq!((0.5 as Float).fract(), 0.5);
assert!((0.5 as Float).fract().is_sign_positive());
assert_eq!((-0.5 as Float).fract(), -0.5);
assert!((-0.5 as Float).fract().is_sign_negative());
assert_eq!(Float::MAX.fract(), 0.0);
assert_eq!(Float::MIN.fract(), 0.0);
assert_eq!(Float::MIN_POSITIVE.fract(), Float::MIN_POSITIVE);
assert!(Float::MIN_POSITIVE.fract().is_sign_positive());
assert_eq!((-Float::MIN_POSITIVE).fract(), -Float::MIN_POSITIVE);
assert!((-Float::MIN_POSITIVE).fract().is_sign_negative());
assert!(Float::NAN.fract().is_nan());
assert!(Float::INFINITY.fract().is_nan());
assert!(Float::NEG_INFINITY.fract().is_nan());
}
}

View File

@@ -730,356 +730,3 @@ assume_usize_width! {
}
}
}
// FIXME(141726): there is a lot of duplication between the following tests and
// the tests in `coretests/tests/floats/f*.rs`
// See issue https://github.com/rust-lang/rust/issues/141726 for more details.
macro_rules! test_float {
($modname: ident, $fassert: ident, $fty: ty) => {
mod $modname {
#[test]
fn min() {
$fassert!((0.0 as $fty).min(0.0), 0.0);
$fassert!((0.0 as $fty).min(0.0).is_sign_positive());
$fassert!((-0.0 as $fty).min(-0.0), -0.0);
$fassert!((-0.0 as $fty).min(-0.0).is_sign_negative());
$fassert!((9.0 as $fty).min(9.0), 9.0);
$fassert!((-9.0 as $fty).min(0.0), -9.0);
$fassert!((0.0 as $fty).min(9.0), 0.0);
$fassert!((0.0 as $fty).min(9.0).is_sign_positive());
$fassert!((-0.0 as $fty).min(9.0), -0.0);
$fassert!((-0.0 as $fty).min(9.0).is_sign_negative());
$fassert!((-0.0 as $fty).min(-9.0), -9.0);
$fassert!(<$fty>::INFINITY.min(9.0), 9.0);
$fassert!((9.0 as $fty).min(<$fty>::INFINITY), 9.0);
$fassert!(<$fty>::INFINITY.min(-9.0), -9.0);
$fassert!((-9.0 as $fty).min(<$fty>::INFINITY), -9.0);
$fassert!(<$fty>::NEG_INFINITY.min(9.0), <$fty>::NEG_INFINITY);
$fassert!((9.0 as $fty).min(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
$fassert!(<$fty>::NEG_INFINITY.min(-9.0), <$fty>::NEG_INFINITY);
$fassert!((-9.0 as $fty).min(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
$fassert!(<$fty>::NAN.min(9.0), 9.0);
$fassert!(<$fty>::NAN.min(-9.0), -9.0);
$fassert!((9.0 as $fty).min(<$fty>::NAN), 9.0);
$fassert!((-9.0 as $fty).min(<$fty>::NAN), -9.0);
$fassert!(<$fty>::NAN.min(<$fty>::NAN).is_nan());
}
#[test]
fn max() {
$fassert!((0.0 as $fty).max(0.0), 0.0);
$fassert!((0.0 as $fty).max(0.0).is_sign_positive());
$fassert!((-0.0 as $fty).max(-0.0), -0.0);
$fassert!((-0.0 as $fty).max(-0.0).is_sign_negative());
$fassert!((9.0 as $fty).max(9.0), 9.0);
$fassert!((-9.0 as $fty).max(0.0), 0.0);
$fassert!((-9.0 as $fty).max(0.0).is_sign_positive());
$fassert!((-9.0 as $fty).max(-0.0), -0.0);
$fassert!((-9.0 as $fty).max(-0.0).is_sign_negative());
$fassert!((0.0 as $fty).max(9.0), 9.0);
$fassert!((0.0 as $fty).max(-9.0), 0.0);
$fassert!((0.0 as $fty).max(-9.0).is_sign_positive());
$fassert!((-0.0 as $fty).max(-9.0), -0.0);
$fassert!((-0.0 as $fty).max(-9.0).is_sign_negative());
$fassert!(<$fty>::INFINITY.max(9.0), <$fty>::INFINITY);
$fassert!((9.0 as $fty).max(<$fty>::INFINITY), <$fty>::INFINITY);
$fassert!(<$fty>::INFINITY.max(-9.0), <$fty>::INFINITY);
$fassert!((-9.0 as $fty).max(<$fty>::INFINITY), <$fty>::INFINITY);
$fassert!(<$fty>::NEG_INFINITY.max(9.0), 9.0);
$fassert!((9.0 as $fty).max(<$fty>::NEG_INFINITY), 9.0);
$fassert!(<$fty>::NEG_INFINITY.max(-9.0), -9.0);
$fassert!((-9.0 as $fty).max(<$fty>::NEG_INFINITY), -9.0);
$fassert!(<$fty>::NAN.max(9.0), 9.0);
$fassert!(<$fty>::NAN.max(-9.0), -9.0);
$fassert!((9.0 as $fty).max(<$fty>::NAN), 9.0);
$fassert!((-9.0 as $fty).max(<$fty>::NAN), -9.0);
$fassert!(<$fty>::NAN.max(<$fty>::NAN).is_nan());
}
#[test]
fn minimum() {
$fassert!((0.0 as $fty).minimum(0.0), 0.0);
$fassert!((0.0 as $fty).minimum(0.0).is_sign_positive());
$fassert!((-0.0 as $fty).minimum(0.0), -0.0);
$fassert!((-0.0 as $fty).minimum(0.0).is_sign_negative());
$fassert!((-0.0 as $fty).minimum(-0.0), -0.0);
$fassert!((-0.0 as $fty).minimum(-0.0).is_sign_negative());
$fassert!((9.0 as $fty).minimum(9.0), 9.0);
$fassert!((-9.0 as $fty).minimum(0.0), -9.0);
$fassert!((0.0 as $fty).minimum(9.0), 0.0);
$fassert!((0.0 as $fty).minimum(9.0).is_sign_positive());
$fassert!((-0.0 as $fty).minimum(9.0), -0.0);
$fassert!((-0.0 as $fty).minimum(9.0).is_sign_negative());
$fassert!((-0.0 as $fty).minimum(-9.0), -9.0);
$fassert!(<$fty>::INFINITY.minimum(9.0), 9.0);
$fassert!((9.0 as $fty).minimum(<$fty>::INFINITY), 9.0);
$fassert!(<$fty>::INFINITY.minimum(-9.0), -9.0);
$fassert!((-9.0 as $fty).minimum(<$fty>::INFINITY), -9.0);
$fassert!(<$fty>::NEG_INFINITY.minimum(9.0), <$fty>::NEG_INFINITY);
$fassert!((9.0 as $fty).minimum(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
$fassert!(<$fty>::NEG_INFINITY.minimum(-9.0), <$fty>::NEG_INFINITY);
$fassert!((-9.0 as $fty).minimum(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
$fassert!(<$fty>::NAN.minimum(9.0).is_nan());
$fassert!(<$fty>::NAN.minimum(-9.0).is_nan());
$fassert!((9.0 as $fty).minimum(<$fty>::NAN).is_nan());
$fassert!((-9.0 as $fty).minimum(<$fty>::NAN).is_nan());
$fassert!(<$fty>::NAN.minimum(<$fty>::NAN).is_nan());
}
#[test]
fn maximum() {
$fassert!((0.0 as $fty).maximum(0.0), 0.0);
$fassert!((0.0 as $fty).maximum(0.0).is_sign_positive());
$fassert!((-0.0 as $fty).maximum(0.0), 0.0);
$fassert!((-0.0 as $fty).maximum(0.0).is_sign_positive());
$fassert!((-0.0 as $fty).maximum(-0.0), -0.0);
$fassert!((-0.0 as $fty).maximum(-0.0).is_sign_negative());
$fassert!((9.0 as $fty).maximum(9.0), 9.0);
$fassert!((-9.0 as $fty).maximum(0.0), 0.0);
$fassert!((-9.0 as $fty).maximum(0.0).is_sign_positive());
$fassert!((-9.0 as $fty).maximum(-0.0), -0.0);
$fassert!((-9.0 as $fty).maximum(-0.0).is_sign_negative());
$fassert!((0.0 as $fty).maximum(9.0), 9.0);
$fassert!((0.0 as $fty).maximum(-9.0), 0.0);
$fassert!((0.0 as $fty).maximum(-9.0).is_sign_positive());
$fassert!((-0.0 as $fty).maximum(-9.0), -0.0);
$fassert!((-0.0 as $fty).maximum(-9.0).is_sign_negative());
$fassert!(<$fty>::INFINITY.maximum(9.0), <$fty>::INFINITY);
$fassert!((9.0 as $fty).maximum(<$fty>::INFINITY), <$fty>::INFINITY);
$fassert!(<$fty>::INFINITY.maximum(-9.0), <$fty>::INFINITY);
$fassert!((-9.0 as $fty).maximum(<$fty>::INFINITY), <$fty>::INFINITY);
$fassert!(<$fty>::NEG_INFINITY.maximum(9.0), 9.0);
$fassert!((9.0 as $fty).maximum(<$fty>::NEG_INFINITY), 9.0);
$fassert!(<$fty>::NEG_INFINITY.maximum(-9.0), -9.0);
$fassert!((-9.0 as $fty).maximum(<$fty>::NEG_INFINITY), -9.0);
$fassert!(<$fty>::NAN.maximum(9.0).is_nan());
$fassert!(<$fty>::NAN.maximum(-9.0).is_nan());
$fassert!((9.0 as $fty).maximum(<$fty>::NAN).is_nan());
$fassert!((-9.0 as $fty).maximum(<$fty>::NAN).is_nan());
$fassert!(<$fty>::NAN.maximum(<$fty>::NAN).is_nan());
}
#[test]
fn midpoint() {
$fassert!((0.5 as $fty).midpoint(0.5), 0.5);
$fassert!((0.5 as $fty).midpoint(2.5), 1.5);
$fassert!((3.0 as $fty).midpoint(4.0), 3.5);
$fassert!((-3.0 as $fty).midpoint(4.0), 0.5);
$fassert!((3.0 as $fty).midpoint(-4.0), -0.5);
$fassert!((-3.0 as $fty).midpoint(-4.0), -3.5);
$fassert!((0.0 as $fty).midpoint(0.0), 0.0);
$fassert!((-0.0 as $fty).midpoint(-0.0), -0.0);
$fassert!((-5.0 as $fty).midpoint(5.0), 0.0);
$fassert!(<$fty>::MAX.midpoint(<$fty>::MIN), 0.0);
$fassert!(<$fty>::MIN.midpoint(<$fty>::MAX), -0.0);
$fassert!(<$fty>::MAX.midpoint(<$fty>::MIN_POSITIVE), <$fty>::MAX / 2.);
$fassert!((-<$fty>::MAX).midpoint(<$fty>::MIN_POSITIVE), -<$fty>::MAX / 2.);
$fassert!(<$fty>::MAX.midpoint(-<$fty>::MIN_POSITIVE), <$fty>::MAX / 2.);
$fassert!((-<$fty>::MAX).midpoint(-<$fty>::MIN_POSITIVE), -<$fty>::MAX / 2.);
$fassert!((<$fty>::MIN_POSITIVE).midpoint(<$fty>::MAX), <$fty>::MAX / 2.);
$fassert!((<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MAX), -<$fty>::MAX / 2.);
$fassert!((-<$fty>::MIN_POSITIVE).midpoint(<$fty>::MAX), <$fty>::MAX / 2.);
$fassert!((-<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MAX), -<$fty>::MAX / 2.);
$fassert!(<$fty>::MAX.midpoint(<$fty>::MAX), <$fty>::MAX);
$fassert!(
(<$fty>::MIN_POSITIVE).midpoint(<$fty>::MIN_POSITIVE),
<$fty>::MIN_POSITIVE
);
$fassert!(
(-<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MIN_POSITIVE),
-<$fty>::MIN_POSITIVE
);
$fassert!(<$fty>::MAX.midpoint(5.0), <$fty>::MAX / 2.0 + 2.5);
$fassert!(<$fty>::MAX.midpoint(-5.0), <$fty>::MAX / 2.0 - 2.5);
$fassert!(<$fty>::INFINITY.midpoint(<$fty>::INFINITY), <$fty>::INFINITY);
$fassert!(
<$fty>::NEG_INFINITY.midpoint(<$fty>::NEG_INFINITY),
<$fty>::NEG_INFINITY
);
$fassert!(<$fty>::NAN.midpoint(1.0).is_nan());
$fassert!((1.0 as $fty).midpoint(<$fty>::NAN).is_nan());
$fassert!(<$fty>::NAN.midpoint(<$fty>::NAN).is_nan());
// test if large differences in magnitude are still correctly computed.
// NOTE: that because of how small x and y are, x + y can never overflow
// so (x + y) / 2.0 is always correct
// in particular, `2.pow(i)` will never be at the max exponent, so it could
// be safely doubled, while j is significantly smaller.
for i in <$fty>::MAX_EXP.saturating_sub(64)..<$fty>::MAX_EXP {
for j in 0..64u8 {
let large = (2.0 as $fty).powi(i);
// a much smaller number, such that there is no chance of overflow to test
// potential double rounding in midpoint's implementation.
let small = (2.0 as $fty).powi(<$fty>::MAX_EXP - 1)
* <$fty>::EPSILON
* <$fty>::from(j);
let naive = (large + small) / 2.0;
let midpoint = large.midpoint(small);
assert_eq!(naive, midpoint);
}
}
}
#[test]
fn abs() {
$fassert!((-1.0 as $fty).abs(), 1.0);
$fassert!((1.0 as $fty).abs(), 1.0);
$fassert!(<$fty>::NEG_INFINITY.abs(), <$fty>::INFINITY);
$fassert!(<$fty>::INFINITY.abs(), <$fty>::INFINITY);
}
#[test]
fn copysign() {
$fassert!((1.0 as $fty).copysign(-2.0), -1.0);
$fassert!((-1.0 as $fty).copysign(2.0), 1.0);
$fassert!(<$fty>::INFINITY.copysign(-0.0), <$fty>::NEG_INFINITY);
$fassert!(<$fty>::NEG_INFINITY.copysign(0.0), <$fty>::INFINITY);
}
#[test]
fn rem_euclid() {
// FIXME: Use $fassert when rem_euclid becomes const
assert!(<$fty>::INFINITY.rem_euclid((42.0 as $fty)).is_nan());
assert_eq!((42.0 as $fty).rem_euclid(<$fty>::INFINITY), (42.0 as $fty));
assert!((42.0 as $fty).rem_euclid(<$fty>::NAN).is_nan());
assert!(<$fty>::INFINITY.rem_euclid(<$fty>::INFINITY).is_nan());
assert!(<$fty>::INFINITY.rem_euclid(<$fty>::NAN).is_nan());
assert!(<$fty>::NAN.rem_euclid(<$fty>::INFINITY).is_nan());
}
#[test]
fn div_euclid() {
// FIXME: Use $fassert when div_euclid becomes const
assert_eq!((42.0 as $fty).div_euclid(<$fty>::INFINITY), 0.0);
assert!((42.0 as $fty).div_euclid(<$fty>::NAN).is_nan());
assert!(<$fty>::INFINITY.div_euclid(<$fty>::INFINITY).is_nan());
assert!(<$fty>::INFINITY.div_euclid(<$fty>::NAN).is_nan());
assert!(<$fty>::NAN.div_euclid(<$fty>::INFINITY).is_nan());
}
#[test]
fn floor() {
$fassert!((0.0 as $fty).floor(), 0.0);
$fassert!((0.0 as $fty).floor().is_sign_positive());
$fassert!((-0.0 as $fty).floor(), -0.0);
$fassert!((-0.0 as $fty).floor().is_sign_negative());
$fassert!((0.5 as $fty).floor(), 0.0);
$fassert!((-0.5 as $fty).floor(), -1.0);
$fassert!((1.5 as $fty).floor(), 1.0);
$fassert!(<$fty>::MAX.floor(), <$fty>::MAX);
$fassert!(<$fty>::MIN.floor(), <$fty>::MIN);
$fassert!(<$fty>::MIN_POSITIVE.floor(), 0.0);
$fassert!((-<$fty>::MIN_POSITIVE).floor(), -1.0);
$fassert!(<$fty>::NAN.floor().is_nan());
$fassert!(<$fty>::INFINITY.floor(), <$fty>::INFINITY);
$fassert!(<$fty>::NEG_INFINITY.floor(), <$fty>::NEG_INFINITY);
}
#[test]
fn ceil() {
$fassert!((0.0 as $fty).ceil(), 0.0);
$fassert!((0.0 as $fty).ceil().is_sign_positive());
$fassert!((-0.0 as $fty).ceil(), 0.0);
$fassert!((-0.0 as $fty).ceil().is_sign_negative());
$fassert!((0.5 as $fty).ceil(), 1.0);
$fassert!((-0.5 as $fty).ceil(), 0.0);
$fassert!(<$fty>::MAX.ceil(), <$fty>::MAX);
$fassert!(<$fty>::MIN.ceil(), <$fty>::MIN);
$fassert!(<$fty>::MIN_POSITIVE.ceil(), 1.0);
$fassert!((-<$fty>::MIN_POSITIVE).ceil(), 0.0);
$fassert!(<$fty>::NAN.ceil().is_nan());
$fassert!(<$fty>::INFINITY.ceil(), <$fty>::INFINITY);
$fassert!(<$fty>::NEG_INFINITY.ceil(), <$fty>::NEG_INFINITY);
}
#[test]
fn round() {
$fassert!((0.0 as $fty).round(), 0.0);
$fassert!((0.0 as $fty).round().is_sign_positive());
$fassert!((-0.0 as $fty).round(), -0.0);
$fassert!((-0.0 as $fty).round().is_sign_negative());
$fassert!((0.5 as $fty).round(), 1.0);
$fassert!((-0.5 as $fty).round(), -1.0);
$fassert!(<$fty>::MAX.round(), <$fty>::MAX);
$fassert!(<$fty>::MIN.round(), <$fty>::MIN);
$fassert!(<$fty>::MIN_POSITIVE.round(), 0.0);
$fassert!((-<$fty>::MIN_POSITIVE).round(), 0.0);
$fassert!(<$fty>::NAN.round().is_nan());
$fassert!(<$fty>::INFINITY.round(), <$fty>::INFINITY);
$fassert!(<$fty>::NEG_INFINITY.round(), <$fty>::NEG_INFINITY);
}
#[test]
fn round_ties_even() {
$fassert!((0.0 as $fty).round_ties_even(), 0.0);
$fassert!((0.0 as $fty).round_ties_even().is_sign_positive());
$fassert!((-0.0 as $fty).round_ties_even(), -0.0);
$fassert!((-0.0 as $fty).round_ties_even().is_sign_negative());
$fassert!((0.5 as $fty).round_ties_even(), 0.0);
$fassert!((0.5 as $fty).round_ties_even().is_sign_positive());
$fassert!((-0.5 as $fty).round_ties_even(), -0.0);
$fassert!((-0.5 as $fty).round_ties_even().is_sign_negative());
$fassert!(<$fty>::MAX.round_ties_even(), <$fty>::MAX);
$fassert!(<$fty>::MIN.round_ties_even(), <$fty>::MIN);
$fassert!(<$fty>::MIN_POSITIVE.round_ties_even(), 0.0);
$fassert!((-<$fty>::MIN_POSITIVE).round_ties_even(), 0.0);
$fassert!(<$fty>::NAN.round_ties_even().is_nan());
$fassert!(<$fty>::INFINITY.round_ties_even(), <$fty>::INFINITY);
$fassert!(<$fty>::NEG_INFINITY.round_ties_even(), <$fty>::NEG_INFINITY);
}
#[test]
fn trunc() {
$fassert!((0.0 as $fty).trunc(), 0.0);
$fassert!((0.0 as $fty).trunc().is_sign_positive());
$fassert!((-0.0 as $fty).trunc(), -0.0);
$fassert!((-0.0 as $fty).trunc().is_sign_negative());
$fassert!((0.5 as $fty).trunc(), 0.0);
$fassert!((0.5 as $fty).trunc().is_sign_positive());
$fassert!((-0.5 as $fty).trunc(), -0.0);
$fassert!((-0.5 as $fty).trunc().is_sign_negative());
$fassert!(<$fty>::MAX.trunc(), <$fty>::MAX);
$fassert!(<$fty>::MIN.trunc(), <$fty>::MIN);
$fassert!(<$fty>::MIN_POSITIVE.trunc(), 0.0);
$fassert!((-<$fty>::MIN_POSITIVE).trunc(), 0.0);
$fassert!(<$fty>::NAN.trunc().is_nan());
$fassert!(<$fty>::INFINITY.trunc(), <$fty>::INFINITY);
$fassert!(<$fty>::NEG_INFINITY.trunc(), <$fty>::NEG_INFINITY);
}
#[test]
fn fract() {
$fassert!((0.0 as $fty).fract(), 0.0);
$fassert!((0.0 as $fty).fract().is_sign_positive());
$fassert!((-0.0 as $fty).fract(), 0.0);
$fassert!((-0.0 as $fty).fract().is_sign_positive());
$fassert!((0.5 as $fty).fract(), 0.5);
$fassert!((0.5 as $fty).fract().is_sign_positive());
$fassert!((-0.5 as $fty).fract(), -0.5);
$fassert!((-0.5 as $fty).fract().is_sign_negative());
$fassert!(<$fty>::MAX.fract(), 0.0);
$fassert!(<$fty>::MIN.fract(), 0.0);
$fassert!(<$fty>::MIN_POSITIVE.fract(), <$fty>::MIN_POSITIVE);
$fassert!(<$fty>::MIN_POSITIVE.fract().is_sign_positive());
$fassert!((-<$fty>::MIN_POSITIVE).fract(), -<$fty>::MIN_POSITIVE);
$fassert!((-<$fty>::MIN_POSITIVE).fract().is_sign_negative());
$fassert!(<$fty>::NAN.fract().is_nan());
$fassert!(<$fty>::INFINITY.fract().is_nan());
$fassert!(<$fty>::NEG_INFINITY.fract().is_nan());
}
}
};
}
// Custom assert macro that distribute between assert! and assert_eq! in a non-const context
macro_rules! float_assert {
($b:expr) => {
assert!($b);
};
($left:expr, $right:expr) => {
assert_eq!($left, $right);
};
}
// Custom assert macro that only uses assert! in a const context
macro_rules! float_const_assert {
($b:expr) => {
assert!(const { $b });
};
($left:expr, $right:expr) => {
assert!(const { $left == $right });
};
}
test_float!(f32, float_assert, f32);
test_float!(f32_const, float_const_assert, f32);
test_float!(f64, float_assert, f64);
test_float!(f64_const, float_const_assert, f64);

View File

@@ -568,7 +568,7 @@ impl OsString {
/// However, keep in mind that trimming the capacity may result in a reallocation and copy.
///
/// [`into_boxed_os_str`]: Self::into_boxed_os_str
#[unstable(feature = "os_string_pathbuf_leak", issue = "125965")]
#[stable(feature = "os_string_pathbuf_leak", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub fn leak<'a>(self) -> &'a mut OsStr {
OsStr::from_inner_mut(self.inner.leak())

View File

@@ -1252,7 +1252,7 @@ impl PathBuf {
/// However, keep in mind that trimming the capacity may result in a reallocation and copy.
///
/// [`into_boxed_path`]: Self::into_boxed_path
#[unstable(feature = "os_string_pathbuf_leak", issue = "125965")]
#[stable(feature = "os_string_pathbuf_leak", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub fn leak<'a>(self) -> &'a mut Path {
Path::from_inner_mut(self.inner.leak())

View File

@@ -3,7 +3,6 @@
path_add_extension,
path_file_prefix,
maybe_uninit_slice,
os_string_pathbuf_leak,
normalize_lexically
)]

View File

@@ -30,6 +30,7 @@ ENV SCRIPT \
python3 ../x.py check && \
python3 ../x.py clippy ci && \
python3 ../x.py test --stage 1 core alloc std test proc_macro && \
python3 ../x.py doc --stage 0 bootstrap && \
# Build both public and internal documentation.
RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 compiler && \
RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 1 library && \

View File

@@ -40,7 +40,9 @@ static HOSTS: &[&str] = &[
"powerpc64le-unknown-linux-musl",
"riscv64gc-unknown-linux-gnu",
"s390x-unknown-linux-gnu",
"sparcv9-sun-solaris",
"x86_64-apple-darwin",
"x86_64-pc-solaris",
"x86_64-pc-windows-gnu",
"x86_64-pc-windows-msvc",
"x86_64-unknown-freebsd",

View File

@@ -2,14 +2,16 @@ error[E0277]: `[usize; usize::MAX]` is not a future
--> $DIR/debug-ice-attempted-to-add-with-overflow.rs:8:37
|
LL | [0usize; 0xffff_ffff_ffff_ffff].await;
| -^^^^^
| ||
| |`[usize; usize::MAX]` is not a future
| help: remove the `.await`
| ^^^^^ `[usize; usize::MAX]` is not a future
|
= help: the trait `Future` is not implemented for `[usize; usize::MAX]`
= note: [usize; usize::MAX] must be a future or must implement `IntoFuture` to be awaited
= note: required for `[usize; usize::MAX]` to implement `IntoFuture`
help: remove the `.await`
|
LL - [0usize; 0xffff_ffff_ffff_ffff].await;
LL + [0usize; 0xffff_ffff_ffff_ffff];
|
error[E0752]: `main` function is not allowed to be `async`
--> $DIR/debug-ice-attempted-to-add-with-overflow.rs:6:1

View File

@@ -10,14 +10,16 @@ error[E0277]: `Option<_>` is not a future
--> $DIR/drop-track-bad-field-in-fru.rs:6:46
|
LL | None { value: (), ..Default::default() }.await;
| -^^^^^
| ||
| |`Option<_>` is not a future
| help: remove the `.await`
| ^^^^^ `Option<_>` is not a future
|
= help: the trait `Future` is not implemented for `Option<_>`
= note: Option<_> must be a future or must implement `IntoFuture` to be awaited
= note: required for `Option<_>` to implement `IntoFuture`
help: remove the `.await`
|
LL - None { value: (), ..Default::default() }.await;
LL + None { value: (), ..Default::default() };
|
error: aborting due to 2 previous errors

View File

@@ -2,14 +2,15 @@ error[E0277]: `()` is not a future
--> $DIR/issue-101715.rs:11:10
|
LL | .await
| -^^^^^
| ||
| |`()` is not a future
| help: remove the `.await`
| ^^^^^ `()` is not a future
|
= help: the trait `Future` is not implemented for `()`
= note: () must be a future or must implement `IntoFuture` to be awaited
= note: required for `()` to implement `IntoFuture`
help: remove the `.await`
|
LL - .await
|
error: aborting due to 1 previous error

View File

@@ -23,14 +23,16 @@ error[E0277]: `()` is not a future
--> $DIR/unnecessary-await.rs:28:10
|
LL | e!().await;
| -^^^^^
| ||
| |`()` is not a future
| help: remove the `.await`
| ^^^^^ `()` is not a future
|
= help: the trait `Future` is not implemented for `()`
= note: () must be a future or must implement `IntoFuture` to be awaited
= note: required for `()` to implement `IntoFuture`
help: remove the `.await`
|
LL - e!().await;
LL + e!();
|
error[E0277]: `()` is not a future
--> $DIR/unnecessary-await.rs:22:15
@@ -53,14 +55,16 @@ error[E0277]: `()` is not a future
--> $DIR/unnecessary-await.rs:36:20
|
LL | for x in [] {}.await
| -^^^^^
| ||
| |`()` is not a future
| help: remove the `.await`
| ^^^^^ `()` is not a future
|
= help: the trait `Future` is not implemented for `()`
= note: () must be a future or must implement `IntoFuture` to be awaited
= note: required for `()` to implement `IntoFuture`
help: remove the `.await`
|
LL - for x in [] {}.await
LL + for x in [] {}
|
error: aborting due to 4 previous errors

View File

@@ -2,17 +2,23 @@ error[E0620]: cast to unsized type: `&[u8]` as `[char]`
--> $DIR/cast-to-slice.rs:2:5
|
LL | "example".as_bytes() as [char];
| ^^^^^^^^^^^^^^^^^^^^^^^^------
| |
| help: try casting to a reference instead: `&[char]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: consider casting to a reference instead
|
LL | "example".as_bytes() as &[char];
| +
error[E0620]: cast to unsized type: `&[u8]` as `[char]`
--> $DIR/cast-to-slice.rs:6:5
|
LL | arr as [char];
| ^^^^^^^------
| |
| help: try casting to a reference instead: `&[char]`
| ^^^^^^^^^^^^^
|
help: consider casting to a reference instead
|
LL | arr as &[char];
| +
error: aborting due to 2 previous errors

View File

@@ -2,17 +2,23 @@ error[E0620]: cast to unsized type: `&{integer}` as `dyn Send`
--> $DIR/cast-to-unsized-trait-object-suggestion.rs:2:5
|
LL | &1 as dyn Send;
| ^^^^^^--------
| |
| help: try casting to a reference instead: `&dyn Send`
| ^^^^^^^^^^^^^^
|
help: consider casting to a reference instead
|
LL | &1 as &dyn Send;
| +
error[E0620]: cast to unsized type: `Box<{integer}>` as `dyn Send`
--> $DIR/cast-to-unsized-trait-object-suggestion.rs:3:5
|
LL | Box::new(1) as dyn Send;
| ^^^^^^^^^^^^^^^--------
| |
| help: you can cast to a `Box` instead: `Box<dyn Send>`
| ^^^^^^^^^^^^^^^^^^^^^^^
|
help: you can cast to a `Box` instead
|
LL | Box::new(1) as Box<dyn Send>;
| ++++ +
error: aborting due to 2 previous errors

View File

@@ -10,9 +10,8 @@ error[E0605]: non-primitive cast: `u32` as `Option<_>`
--> $DIR/issue-73886.rs:4:13
|
LL | let _ = 7u32 as Option<_>;
| ^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
= note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
help: consider using the `From` trait instead
|
LL - let _ = 7u32 as Option<_>;

View File

@@ -2,9 +2,8 @@ error[E0605]: non-primitive cast: `u32` as `Option<_>`
--> $DIR/non-primitive-cast-135412.rs:6:13
|
LL | let _ = 7u32 as Option<_>;
| ^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
= note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
help: consider using the `From` trait instead
|
LL - let _ = 7u32 as Option<_>;
@@ -15,9 +14,8 @@ error[E0605]: non-primitive cast: `&'static str` as `Arc<str>`
--> $DIR/non-primitive-cast-135412.rs:8:13
|
LL | let _ = "String" as Arc<str>;
| ^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
= note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
help: consider using the `From` trait instead
|
LL - let _ = "String" as Arc<str>;

View File

@@ -13,9 +13,8 @@ LL | struct Bar;
|
help: create an inline `const` block
|
LL - let _: [Option<Bar>; 2] = [no_copy(); 2];
LL + let _: [Option<Bar>; 2] = [const { no_copy() }; 2];
|
LL | let _: [Option<Bar>; 2] = [const { no_copy() }; 2];
| +++++++ +
error: aborting due to 1 previous error

View File

@@ -2,10 +2,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
--> $DIR/trait-error.rs:5:6
|
LL | [Foo(String::new()); 4];
| ^^^^^^^^^^^^^^^^^^
| |
| the trait `Copy` is not implemented for `String`
| help: create an inline `const` block: `const { Foo(String::new()) }`
| ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
|
note: required for `Foo<String>` to implement `Copy`
--> $DIR/trait-error.rs:1:10
@@ -13,6 +10,10 @@ note: required for `Foo<String>` to implement `Copy`
LL | #[derive(Copy, Clone)]
| ^^^^ unsatisfied trait bound introduced in this `derive` macro
= note: the `Copy` trait is required because this value will be copied for each element of the array
help: create an inline `const` block
|
LL | [const { Foo(String::new()) }; 4];
| +++++++ +
error: aborting due to 1 previous error

View File

@@ -23,7 +23,7 @@ error[E0604]: only `u8` can be cast as `char`, not `i8`
LL | : [u32; 5i8 as char as usize]
| ^^^^^^^^^^^ invalid cast
|
help: try casting from `u8` instead
help: consider casting from `u8` instead
--> $DIR/const-eval-overflow-4b.rs:24:13
|
LL | : [u32; 5i8 as char as usize]

View File

@@ -2,36 +2,39 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
--> $DIR/const-fn-in-vec.rs:1:47
|
LL | static _MAYBE_STRINGS: [Option<String>; 5] = [None; 5];
| ^^^^
| |
| the trait `Copy` is not implemented for `String`
| help: create an inline `const` block: `const { None }`
| ^^^^ the trait `Copy` is not implemented for `String`
|
= note: required for `Option<String>` to implement `Copy`
= note: the `Copy` trait is required because this value will be copied for each element of the array
help: create an inline `const` block
|
LL | static _MAYBE_STRINGS: [Option<String>; 5] = [const { None }; 5];
| +++++++ +
error[E0277]: the trait bound `String: Copy` is not satisfied
--> $DIR/const-fn-in-vec.rs:7:34
|
LL | let _strings: [String; 5] = [String::new(); 5];
| ^^^^^^^^^^^^^
| |
| the trait `Copy` is not implemented for `String`
| help: create an inline `const` block: `const { String::new() }`
| ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
|
= note: the `Copy` trait is required because this value will be copied for each element of the array
help: create an inline `const` block
|
LL | let _strings: [String; 5] = [const { String::new() }; 5];
| +++++++ +
error[E0277]: the trait bound `String: Copy` is not satisfied
--> $DIR/const-fn-in-vec.rs:12:48
|
LL | let _maybe_strings: [Option<String>; 5] = [None; 5];
| ^^^^
| |
| the trait `Copy` is not implemented for `String`
| help: create an inline `const` block: `const { None }`
| ^^^^ the trait `Copy` is not implemented for `String`
|
= note: required for `Option<String>` to implement `Copy`
= note: the `Copy` trait is required because this value will be copied for each element of the array
help: create an inline `const` block
|
LL | let _maybe_strings: [Option<String>; 5] = [const { None }; 5];
| +++++++ +
error: aborting due to 3 previous errors

View File

@@ -2,15 +2,18 @@ error[E0277]: `[(); _]` is not a future
--> $DIR/unresolved-ct-var.rs:6:45
|
LL | let s = std::array::from_fn(|_| ()).await;
| ----------------------------^^^^^
| | ||
| | |`[(); _]` is not a future
| | help: remove the `.await`
| --------------------------- ^^^^^ `[(); _]` is not a future
| |
| this call returns `[(); _]`
|
= help: the trait `Future` is not implemented for `[(); _]`
= note: [(); _] must be a future or must implement `IntoFuture` to be awaited
= note: required for `[(); _]` to implement `IntoFuture`
help: remove the `.await`
|
LL - let s = std::array::from_fn(|_| ()).await;
LL + let s = std::array::from_fn(|_| ());
|
error: aborting due to 1 previous error

View File

@@ -2,10 +2,13 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
--> $DIR/E0604.rs:2:5
|
LL | 1u32 as char;
| ^^^^^^^^^^^^
| |
| invalid cast
| help: try `char::from_u32` instead: `char::from_u32(1u32)`
| ^^^^^^^^^^^^ invalid cast
|
help: consider using `char::from_u32` instead
|
LL - 1u32 as char;
LL + char::from_u32(1u32);
|
error: aborting due to 1 previous error

View File

@@ -2,9 +2,12 @@ error[E0620]: cast to unsized type: `&[usize; 2]` as `[usize]`
--> $DIR/E0620.rs:2:16
|
LL | let _foo = &[1_usize, 2] as [usize];
| ^^^^^^^^^^^^^^^^^-------
| |
| help: try casting to a reference instead: `&[usize]`
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
help: consider casting to a reference instead
|
LL | let _foo = &[1_usize, 2] as &[usize];
| +
error: aborting due to 1 previous error

View File

@@ -58,10 +58,13 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
--> $DIR/error-festival.rs:27:5
|
LL | 0u32 as char;
| ^^^^^^^^^^^^
| |
| invalid cast
| help: try `char::from_u32` instead: `char::from_u32(0u32)`
| ^^^^^^^^^^^^ invalid cast
|
help: consider using `char::from_u32` instead
|
LL - 0u32 as char;
LL + char::from_u32(0u32);
|
error[E0605]: non-primitive cast: `u8` as `Vec<u8>`
--> $DIR/error-festival.rs:31:5

View File

@@ -11,9 +11,13 @@ error[E0605]: non-primitive cast: `Foo<'a>` as `T`
--> $DIR/issue-16048.rs:24:16
|
LL | return *self as T;
| ^^^^^^^^^^ help: consider using the `From` trait instead: `T::from(*self)`
| ^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
help: consider using the `From` trait instead
|
LL - return *self as T;
LL + return T::from(*self);
|
= note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error: aborting due to 2 previous errors

View File

@@ -2,17 +2,23 @@ error[E0620]: cast to unsized type: `&[usize; 2]` as `[usize]`
--> $DIR/issue-17441.rs:2:16
|
LL | let _foo = &[1_usize, 2] as [usize];
| ^^^^^^^^^^^^^^^^^-------
| |
| help: try casting to a reference instead: `&[usize]`
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
help: consider casting to a reference instead
|
LL | let _foo = &[1_usize, 2] as &[usize];
| +
error[E0620]: cast to unsized type: `Box<usize>` as `dyn Debug`
--> $DIR/issue-17441.rs:5:16
|
LL | let _bar = Box::new(1_usize) as dyn std::fmt::Debug;
| ^^^^^^^^^^^^^^^^^^^^^-------------------
| |
| help: you can cast to a `Box` instead: `Box<dyn std::fmt::Debug>`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: you can cast to a `Box` instead
|
LL | let _bar = Box::new(1_usize) as Box<dyn std::fmt::Debug>;
| ++++ +
error[E0620]: cast to unsized type: `usize` as `dyn Debug`
--> $DIR/issue-17441.rs:8:16

View File

@@ -104,10 +104,13 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
--> $DIR/cast-rfc0401.rs:41:13
|
LL | let _ = 0x61u32 as char;
| ^^^^^^^^^^^^^^^
| |
| invalid cast
| help: try `char::from_u32` instead: `char::from_u32(0x61u32)`
| ^^^^^^^^^^^^^^^ invalid cast
|
help: consider using `char::from_u32` instead
|
LL - let _ = 0x61u32 as char;
LL + let _ = char::from_u32(0x61u32);
|
error[E0606]: casting `bool` as `f32` is invalid
--> $DIR/cast-rfc0401.rs:43:13

View File

@@ -2,9 +2,13 @@ error[E0605]: non-primitive cast: `Foo` as `isize`
--> $DIR/nonscalar-cast.rs:15:20
|
LL | println!("{}", Foo { x: 1 } as isize);
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `isize::from(Foo { x: 1 })`
| ^^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
help: consider using the `From` trait instead
|
LL - println!("{}", Foo { x: 1 } as isize);
LL + println!("{}", isize::from(Foo { x: 1 }));
|
= note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error: aborting due to 1 previous error

View File

@@ -2,12 +2,13 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
--> $DIR/copy-check-when-count-inferred-later.rs:8:14
|
LL | let a = [String::new(); _];
| ^^^^^^^^^^^^^
| |
| the trait `Copy` is not implemented for `String`
| help: create an inline `const` block: `const { String::new() }`
| ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
|
= note: the `Copy` trait is required because this value will be copied for each element of the array
help: create an inline `const` block
|
LL | let a = [const { String::new() }; _];
| +++++++ +
error: aborting due to 1 previous error

View File

@@ -2,10 +2,14 @@ error[E0605]: non-primitive cast: `NonNullary` as `isize`
--> $DIR/tag-variant-cast-non-nullary.rs:19:15
|
LL | let val = v as isize;
| ^^^^^^^^^^ help: consider using the `From` trait instead: `isize::from(v)`
| ^^^^^^^^^^ an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less
|
= note: an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less
= note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information
help: consider using the `From` trait instead
|
LL - let val = v as isize;
LL + let val = isize::from(v);
|
error: aborting due to 1 previous error

View File

@@ -2,7 +2,7 @@ error[E0283]: type annotations needed: cannot satisfy `Foo: Trait<Bar>`
--> $DIR/constrain_in_projection2.rs:28:14
|
LL | let x = <Foo as Trait<Bar>>::Assoc::default();
| ^^^ help: use the fully qualified path to an implementation: `<Type as Trait>::Assoc`
| ^^^
|
note: multiple `impl`s satisfying `Foo: Trait<Bar>` found
--> $DIR/constrain_in_projection2.rs:18:1
@@ -13,6 +13,11 @@ LL | impl Trait<()> for Foo {
LL | impl Trait<u32> for Foo {
| ^^^^^^^^^^^^^^^^^^^^^^^
= note: associated types cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
help: use the fully qualified path to an implementation
|
LL - let x = <Foo as Trait<Bar>>::Assoc::default();
LL + let x = <<Type as Trait>::Assoc as Trait<Bar>>::Assoc::default();
|
error: aborting due to 1 previous error