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:
@@ -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");
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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()))
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
},
|
||||
|
||||
@@ -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
|
||||
},
|
||||
|
||||
@@ -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
|
||||
},
|
||||
|
||||
@@ -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
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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
|
||||
},
|
||||
|
||||
@@ -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
|
||||
},
|
||||
|
||||
@@ -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
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
},
|
||||
|
||||
@@ -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
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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 },
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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![
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
path_add_extension,
|
||||
path_file_prefix,
|
||||
maybe_uninit_slice,
|
||||
os_string_pathbuf_leak,
|
||||
normalize_lexically
|
||||
)]
|
||||
|
||||
|
||||
@@ -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 && \
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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<_>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user