Replace f16
and f128
pattern matching stubs with real implementations
This section of code depends on `rustc_apfloat` rather than our internal types, so this is one potential ICE that we should be able to melt now. This also fixes some missing range and match handling in `rustc_middle`.
This commit is contained in:
parent
acb62737ac
commit
6fb6c19c96
@ -1047,6 +1047,12 @@ pub fn compare_with(
|
|||||||
let b = other.eval_bits(ty, tcx, param_env);
|
let b = other.eval_bits(ty, tcx, param_env);
|
||||||
|
|
||||||
match ty.kind() {
|
match ty.kind() {
|
||||||
|
ty::Float(ty::FloatTy::F16) => {
|
||||||
|
use rustc_apfloat::Float;
|
||||||
|
let a = rustc_apfloat::ieee::Half::from_bits(a);
|
||||||
|
let b = rustc_apfloat::ieee::Half::from_bits(b);
|
||||||
|
a.partial_cmp(&b)
|
||||||
|
}
|
||||||
ty::Float(ty::FloatTy::F32) => {
|
ty::Float(ty::FloatTy::F32) => {
|
||||||
use rustc_apfloat::Float;
|
use rustc_apfloat::Float;
|
||||||
let a = rustc_apfloat::ieee::Single::from_bits(a);
|
let a = rustc_apfloat::ieee::Single::from_bits(a);
|
||||||
@ -1059,6 +1065,12 @@ pub fn compare_with(
|
|||||||
let b = rustc_apfloat::ieee::Double::from_bits(b);
|
let b = rustc_apfloat::ieee::Double::from_bits(b);
|
||||||
a.partial_cmp(&b)
|
a.partial_cmp(&b)
|
||||||
}
|
}
|
||||||
|
ty::Float(ty::FloatTy::F128) => {
|
||||||
|
use rustc_apfloat::Float;
|
||||||
|
let a = rustc_apfloat::ieee::Quad::from_bits(a);
|
||||||
|
let b = rustc_apfloat::ieee::Quad::from_bits(b);
|
||||||
|
a.partial_cmp(&b)
|
||||||
|
}
|
||||||
ty::Int(ity) => {
|
ty::Int(ity) => {
|
||||||
let size = rustc_target::abi::Integer::from_int_ty(&tcx, *ity).size();
|
let size = rustc_target::abi::Integer::from_int_ty(&tcx, *ity).size();
|
||||||
let a = size.sign_extend(a) as i128;
|
let a = size.sign_extend(a) as i128;
|
||||||
|
@ -1196,7 +1196,7 @@ pub fn int_size_and_signed(self, tcx: TyCtxt<'tcx>) -> (Size, bool) {
|
|||||||
/// Returns the minimum and maximum values for the given numeric type (including `char`s) or
|
/// Returns the minimum and maximum values for the given numeric type (including `char`s) or
|
||||||
/// returns `None` if the type is not numeric.
|
/// returns `None` if the type is not numeric.
|
||||||
pub fn numeric_min_and_max_as_bits(self, tcx: TyCtxt<'tcx>) -> Option<(u128, u128)> {
|
pub fn numeric_min_and_max_as_bits(self, tcx: TyCtxt<'tcx>) -> Option<(u128, u128)> {
|
||||||
use rustc_apfloat::ieee::{Double, Single};
|
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
|
||||||
Some(match self.kind() {
|
Some(match self.kind() {
|
||||||
ty::Int(_) | ty::Uint(_) => {
|
ty::Int(_) | ty::Uint(_) => {
|
||||||
let (size, signed) = self.int_size_and_signed(tcx);
|
let (size, signed) = self.int_size_and_signed(tcx);
|
||||||
@ -1206,12 +1206,14 @@ pub fn numeric_min_and_max_as_bits(self, tcx: TyCtxt<'tcx>) -> Option<(u128, u12
|
|||||||
(min, max)
|
(min, max)
|
||||||
}
|
}
|
||||||
ty::Char => (0, std::char::MAX as u128),
|
ty::Char => (0, std::char::MAX as u128),
|
||||||
|
ty::Float(ty::FloatTy::F16) => ((-Half::INFINITY).to_bits(), Half::INFINITY.to_bits()),
|
||||||
ty::Float(ty::FloatTy::F32) => {
|
ty::Float(ty::FloatTy::F32) => {
|
||||||
((-Single::INFINITY).to_bits(), Single::INFINITY.to_bits())
|
((-Single::INFINITY).to_bits(), Single::INFINITY.to_bits())
|
||||||
}
|
}
|
||||||
ty::Float(ty::FloatTy::F64) => {
|
ty::Float(ty::FloatTy::F64) => {
|
||||||
((-Double::INFINITY).to_bits(), Double::INFINITY.to_bits())
|
((-Double::INFINITY).to_bits(), Double::INFINITY.to_bits())
|
||||||
}
|
}
|
||||||
|
ty::Float(ty::FloatTy::F128) => ((-Quad::INFINITY).to_bits(), Quad::INFINITY.to_bits()),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -369,10 +369,10 @@ fn recur(
|
|||||||
ty::Float(flt) => {
|
ty::Float(flt) => {
|
||||||
let v = cv.unwrap_leaf();
|
let v = cv.unwrap_leaf();
|
||||||
let is_nan = match flt {
|
let is_nan = match flt {
|
||||||
ty::FloatTy::F16 => unimplemented!("f16_f128"),
|
ty::FloatTy::F16 => v.to_f16().is_nan(),
|
||||||
ty::FloatTy::F32 => v.to_f32().is_nan(),
|
ty::FloatTy::F32 => v.to_f32().is_nan(),
|
||||||
ty::FloatTy::F64 => v.to_f64().is_nan(),
|
ty::FloatTy::F64 => v.to_f64().is_nan(),
|
||||||
ty::FloatTy::F128 => unimplemented!("f16_f128"),
|
ty::FloatTy::F128 => v.to_f128().is_nan(),
|
||||||
};
|
};
|
||||||
if is_nan {
|
if is_nan {
|
||||||
// NaNs are not ever equal to anything so they make no sense as patterns.
|
// NaNs are not ever equal to anything so they make no sense as patterns.
|
||||||
|
@ -182,7 +182,7 @@
|
|||||||
|
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use rustc_apfloat::ieee::{DoubleS, IeeeFloat, SingleS};
|
use rustc_apfloat::ieee::{DoubleS, HalfS, IeeeFloat, QuadS, SingleS};
|
||||||
use rustc_index::bit_set::{BitSet, GrowableBitSet};
|
use rustc_index::bit_set::{BitSet, GrowableBitSet};
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
|
|
||||||
@ -692,8 +692,10 @@ pub enum Constructor<Cx: PatCx> {
|
|||||||
/// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
|
/// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
|
||||||
IntRange(IntRange),
|
IntRange(IntRange),
|
||||||
/// Ranges of floating-point literal values (`2.0..=5.2`).
|
/// Ranges of floating-point literal values (`2.0..=5.2`).
|
||||||
|
F16Range(IeeeFloat<HalfS>, IeeeFloat<HalfS>, RangeEnd),
|
||||||
F32Range(IeeeFloat<SingleS>, IeeeFloat<SingleS>, RangeEnd),
|
F32Range(IeeeFloat<SingleS>, IeeeFloat<SingleS>, RangeEnd),
|
||||||
F64Range(IeeeFloat<DoubleS>, IeeeFloat<DoubleS>, RangeEnd),
|
F64Range(IeeeFloat<DoubleS>, IeeeFloat<DoubleS>, RangeEnd),
|
||||||
|
F128Range(IeeeFloat<QuadS>, IeeeFloat<QuadS>, RangeEnd),
|
||||||
/// String literals. Strings are not quite the same as `&[u8]` so we treat them separately.
|
/// String literals. Strings are not quite the same as `&[u8]` so we treat them separately.
|
||||||
Str(Cx::StrLit),
|
Str(Cx::StrLit),
|
||||||
/// Constants that must not be matched structurally. They are treated as black boxes for the
|
/// Constants that must not be matched structurally. They are treated as black boxes for the
|
||||||
@ -735,8 +737,10 @@ fn clone(&self) -> Self {
|
|||||||
Constructor::UnionField => Constructor::UnionField,
|
Constructor::UnionField => Constructor::UnionField,
|
||||||
Constructor::Bool(b) => Constructor::Bool(*b),
|
Constructor::Bool(b) => Constructor::Bool(*b),
|
||||||
Constructor::IntRange(range) => Constructor::IntRange(*range),
|
Constructor::IntRange(range) => Constructor::IntRange(*range),
|
||||||
|
Constructor::F16Range(lo, hi, end) => Constructor::F16Range(lo.clone(), *hi, *end),
|
||||||
Constructor::F32Range(lo, hi, end) => Constructor::F32Range(lo.clone(), *hi, *end),
|
Constructor::F32Range(lo, hi, end) => Constructor::F32Range(lo.clone(), *hi, *end),
|
||||||
Constructor::F64Range(lo, hi, end) => Constructor::F64Range(lo.clone(), *hi, *end),
|
Constructor::F64Range(lo, hi, end) => Constructor::F64Range(lo.clone(), *hi, *end),
|
||||||
|
Constructor::F128Range(lo, hi, end) => Constructor::F128Range(lo.clone(), *hi, *end),
|
||||||
Constructor::Str(value) => Constructor::Str(value.clone()),
|
Constructor::Str(value) => Constructor::Str(value.clone()),
|
||||||
Constructor::Opaque(inner) => Constructor::Opaque(inner.clone()),
|
Constructor::Opaque(inner) => Constructor::Opaque(inner.clone()),
|
||||||
Constructor::Or => Constructor::Or,
|
Constructor::Or => Constructor::Or,
|
||||||
@ -812,6 +816,14 @@ pub(crate) fn is_covered_by(&self, cx: &Cx, other: &Self) -> Result<bool, Cx::Er
|
|||||||
(Bool(self_b), Bool(other_b)) => self_b == other_b,
|
(Bool(self_b), Bool(other_b)) => self_b == other_b,
|
||||||
|
|
||||||
(IntRange(self_range), IntRange(other_range)) => self_range.is_subrange(other_range),
|
(IntRange(self_range), IntRange(other_range)) => self_range.is_subrange(other_range),
|
||||||
|
(F16Range(self_from, self_to, self_end), F16Range(other_from, other_to, other_end)) => {
|
||||||
|
self_from.ge(other_from)
|
||||||
|
&& match self_to.partial_cmp(other_to) {
|
||||||
|
Some(Ordering::Less) => true,
|
||||||
|
Some(Ordering::Equal) => other_end == self_end,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
(F32Range(self_from, self_to, self_end), F32Range(other_from, other_to, other_end)) => {
|
(F32Range(self_from, self_to, self_end), F32Range(other_from, other_to, other_end)) => {
|
||||||
self_from.ge(other_from)
|
self_from.ge(other_from)
|
||||||
&& match self_to.partial_cmp(other_to) {
|
&& match self_to.partial_cmp(other_to) {
|
||||||
@ -828,6 +840,17 @@ pub(crate) fn is_covered_by(&self, cx: &Cx, other: &Self) -> Result<bool, Cx::Er
|
|||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(
|
||||||
|
F128Range(self_from, self_to, self_end),
|
||||||
|
F128Range(other_from, other_to, other_end),
|
||||||
|
) => {
|
||||||
|
self_from.ge(other_from)
|
||||||
|
&& match self_to.partial_cmp(other_to) {
|
||||||
|
Some(Ordering::Less) => true,
|
||||||
|
Some(Ordering::Equal) => other_end == self_end,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
(Str(self_val), Str(other_val)) => {
|
(Str(self_val), Str(other_val)) => {
|
||||||
// FIXME Once valtrees are available we can directly use the bytes
|
// FIXME Once valtrees are available we can directly use the bytes
|
||||||
// in the `Str` variant of the valtree for the comparison here.
|
// in the `Str` variant of the valtree for the comparison here.
|
||||||
@ -906,8 +929,10 @@ pub(crate) fn fmt_fields(
|
|||||||
Bool(b) => write!(f, "{b}")?,
|
Bool(b) => write!(f, "{b}")?,
|
||||||
// Best-effort, will render signed ranges incorrectly
|
// Best-effort, will render signed ranges incorrectly
|
||||||
IntRange(range) => write!(f, "{range:?}")?,
|
IntRange(range) => write!(f, "{range:?}")?,
|
||||||
|
F16Range(lo, hi, end) => write!(f, "{lo}{end}{hi}")?,
|
||||||
F32Range(lo, hi, end) => write!(f, "{lo}{end}{hi}")?,
|
F32Range(lo, hi, end) => write!(f, "{lo}{end}{hi}")?,
|
||||||
F64Range(lo, hi, end) => write!(f, "{lo}{end}{hi}")?,
|
F64Range(lo, hi, end) => write!(f, "{lo}{end}{hi}")?,
|
||||||
|
F128Range(lo, hi, end) => write!(f, "{lo}{end}{hi}")?,
|
||||||
Str(value) => write!(f, "{value:?}")?,
|
Str(value) => write!(f, "{value:?}")?,
|
||||||
Opaque(..) => write!(f, "<constant pattern>")?,
|
Opaque(..) => write!(f, "<constant pattern>")?,
|
||||||
Or => {
|
Or => {
|
||||||
|
@ -247,8 +247,9 @@ fn reveal_and_alloc<'a, 'tcx>(
|
|||||||
}
|
}
|
||||||
_ => bug!("bad slice pattern {:?} {:?}", ctor, ty),
|
_ => bug!("bad slice pattern {:?} {:?}", ctor, ty),
|
||||||
},
|
},
|
||||||
Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..)
|
Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..)
|
||||||
| Never | NonExhaustive | Hidden | Missing | PrivateUninhabited | Wildcard => &[],
|
| F128Range(..) | Str(..) | Opaque(..) | Never | NonExhaustive | Hidden | Missing
|
||||||
|
| PrivateUninhabited | Wildcard => &[],
|
||||||
Or => {
|
Or => {
|
||||||
bug!("called `Fields::wildcards` on an `Or` ctor")
|
bug!("called `Fields::wildcards` on an `Or` ctor")
|
||||||
}
|
}
|
||||||
@ -275,8 +276,9 @@ pub(crate) fn ctor_arity(&self, ctor: &Constructor<'p, 'tcx>, ty: RevealedTy<'tc
|
|||||||
},
|
},
|
||||||
Ref => 1,
|
Ref => 1,
|
||||||
Slice(slice) => slice.arity(),
|
Slice(slice) => slice.arity(),
|
||||||
Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..)
|
Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..)
|
||||||
| Never | NonExhaustive | Hidden | Missing | PrivateUninhabited | Wildcard => 0,
|
| F128Range(..) | Str(..) | Opaque(..) | Never | NonExhaustive | Hidden | Missing
|
||||||
|
| PrivateUninhabited | Wildcard => 0,
|
||||||
Or => bug!("The `Or` constructor doesn't have a fixed arity"),
|
Or => bug!("The `Or` constructor doesn't have a fixed arity"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -546,6 +548,18 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> {
|
|||||||
fields = vec![];
|
fields = vec![];
|
||||||
arity = 0;
|
arity = 0;
|
||||||
}
|
}
|
||||||
|
ty::Float(ty::FloatTy::F16) => {
|
||||||
|
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
|
||||||
|
Some(bits) => {
|
||||||
|
use rustc_apfloat::Float;
|
||||||
|
let value = rustc_apfloat::ieee::Half::from_bits(bits);
|
||||||
|
F16Range(value, value, RangeEnd::Included)
|
||||||
|
}
|
||||||
|
None => Opaque(OpaqueId::new()),
|
||||||
|
};
|
||||||
|
fields = vec![];
|
||||||
|
arity = 0;
|
||||||
|
}
|
||||||
ty::Float(ty::FloatTy::F32) => {
|
ty::Float(ty::FloatTy::F32) => {
|
||||||
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
|
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
|
||||||
Some(bits) => {
|
Some(bits) => {
|
||||||
@ -570,6 +584,18 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> {
|
|||||||
fields = vec![];
|
fields = vec![];
|
||||||
arity = 0;
|
arity = 0;
|
||||||
}
|
}
|
||||||
|
ty::Float(ty::FloatTy::F128) => {
|
||||||
|
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
|
||||||
|
Some(bits) => {
|
||||||
|
use rustc_apfloat::Float;
|
||||||
|
let value = rustc_apfloat::ieee::Quad::from_bits(bits);
|
||||||
|
F128Range(value, value, RangeEnd::Included)
|
||||||
|
}
|
||||||
|
None => Opaque(OpaqueId::new()),
|
||||||
|
};
|
||||||
|
fields = vec![];
|
||||||
|
arity = 0;
|
||||||
|
}
|
||||||
ty::Ref(_, t, _) if t.is_str() => {
|
ty::Ref(_, t, _) if t.is_str() => {
|
||||||
// We want a `&str` constant to behave like a `Deref` pattern, to be compatible
|
// We want a `&str` constant to behave like a `Deref` pattern, to be compatible
|
||||||
// with other `Deref` patterns. This could have been done in `const_to_pat`,
|
// with other `Deref` patterns. This could have been done in `const_to_pat`,
|
||||||
@ -611,7 +637,12 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> {
|
|||||||
let lo = lo.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env));
|
let lo = lo.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env));
|
||||||
let hi = hi.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env));
|
let hi = hi.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env));
|
||||||
match fty {
|
match fty {
|
||||||
ty::FloatTy::F16 => unimplemented!("f16_f128"),
|
ty::FloatTy::F16 => {
|
||||||
|
use rustc_apfloat::ieee::Half;
|
||||||
|
let lo = lo.map(Half::from_bits).unwrap_or(-Half::INFINITY);
|
||||||
|
let hi = hi.map(Half::from_bits).unwrap_or(Half::INFINITY);
|
||||||
|
F16Range(lo, hi, end)
|
||||||
|
}
|
||||||
ty::FloatTy::F32 => {
|
ty::FloatTy::F32 => {
|
||||||
use rustc_apfloat::ieee::Single;
|
use rustc_apfloat::ieee::Single;
|
||||||
let lo = lo.map(Single::from_bits).unwrap_or(-Single::INFINITY);
|
let lo = lo.map(Single::from_bits).unwrap_or(-Single::INFINITY);
|
||||||
@ -624,7 +655,12 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> {
|
|||||||
let hi = hi.map(Double::from_bits).unwrap_or(Double::INFINITY);
|
let hi = hi.map(Double::from_bits).unwrap_or(Double::INFINITY);
|
||||||
F64Range(lo, hi, end)
|
F64Range(lo, hi, end)
|
||||||
}
|
}
|
||||||
ty::FloatTy::F128 => unimplemented!("f16_f128"),
|
ty::FloatTy::F128 => {
|
||||||
|
use rustc_apfloat::ieee::Quad;
|
||||||
|
let lo = lo.map(Quad::from_bits).unwrap_or(-Quad::INFINITY);
|
||||||
|
let hi = hi.map(Quad::from_bits).unwrap_or(Quad::INFINITY);
|
||||||
|
F128Range(lo, hi, end)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => bug!("invalid type for range pattern: {}", ty.inner()),
|
_ => bug!("invalid type for range pattern: {}", ty.inner()),
|
||||||
@ -837,7 +873,7 @@ pub fn hoist_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> Pat<'tcx> {
|
|||||||
"trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
|
"trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
|
||||||
`Missing` should have been processed in `apply_constructors`"
|
`Missing` should have been processed in `apply_constructors`"
|
||||||
),
|
),
|
||||||
F32Range(..) | F64Range(..) | Opaque(..) | Or => {
|
F16Range(..) | F32Range(..) | F64Range(..) | F128Range(..) | Opaque(..) | Or => {
|
||||||
bug!("can't convert to pattern: {:?}", pat)
|
bug!("can't convert to pattern: {:?}", pat)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
// via `.contains(...)` and make sure the dynamic semantics match.
|
// via `.contains(...)` and make sure the dynamic semantics match.
|
||||||
|
|
||||||
#![allow(unreachable_patterns)]
|
#![allow(unreachable_patterns)]
|
||||||
|
#![feature(f128)]
|
||||||
|
#![feature(f16)]
|
||||||
|
|
||||||
macro_rules! yes {
|
macro_rules! yes {
|
||||||
($scrutinee:expr, $($t:tt)+) => {
|
($scrutinee:expr, $($t:tt)+) => {
|
||||||
@ -39,6 +41,17 @@ fn range_to_inclusive() {
|
|||||||
assert!(yes!('a', ..='a'));
|
assert!(yes!('a', ..='a'));
|
||||||
assert!(!yes!('b', ..='a'));
|
assert!(!yes!('b', ..='a'));
|
||||||
|
|
||||||
|
// f16; `..=X`
|
||||||
|
// FIXME(f16_f128): remove gate when ABI issues are resolved
|
||||||
|
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
|
||||||
|
{
|
||||||
|
// FIXME(f16_f128): enable infinity tests when constants are available
|
||||||
|
// assert!(yes!(f16::NEG_INFINITY, ..=f16::NEG_INFINITY));
|
||||||
|
// assert!(yes!(f16::NEG_INFINITY, ..=1.0f16));
|
||||||
|
assert!(yes!(1.5f16, ..=1.5f16));
|
||||||
|
assert!(!yes!(1.6f16, ..=-1.5f16));
|
||||||
|
}
|
||||||
|
|
||||||
// f32; `..=X`
|
// f32; `..=X`
|
||||||
assert!(yes!(f32::NEG_INFINITY, ..=f32::NEG_INFINITY));
|
assert!(yes!(f32::NEG_INFINITY, ..=f32::NEG_INFINITY));
|
||||||
assert!(yes!(f32::NEG_INFINITY, ..=1.0f32));
|
assert!(yes!(f32::NEG_INFINITY, ..=1.0f32));
|
||||||
@ -50,6 +63,17 @@ fn range_to_inclusive() {
|
|||||||
assert!(yes!(f64::NEG_INFINITY, ..=1.0f64));
|
assert!(yes!(f64::NEG_INFINITY, ..=1.0f64));
|
||||||
assert!(yes!(1.5f64, ..=1.5f64));
|
assert!(yes!(1.5f64, ..=1.5f64));
|
||||||
assert!(!yes!(1.6f64, ..=-1.5f64));
|
assert!(!yes!(1.6f64, ..=-1.5f64));
|
||||||
|
|
||||||
|
// f128; `..=X`
|
||||||
|
// FIXME(f16_f128): remove gate when ABI issues are resolved
|
||||||
|
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
|
||||||
|
{
|
||||||
|
// FIXME(f16_f128): enable infinity tests when constants are available
|
||||||
|
// assert!(yes!(f128::NEG_INFINITY, ..=f128::NEG_INFINITY));
|
||||||
|
// assert!(yes!(f128::NEG_INFINITY, ..=1.0f128));
|
||||||
|
assert!(yes!(1.5f128, ..=1.5f128));
|
||||||
|
assert!(!yes!(1.6f128, ..=-1.5f128));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn range_to() {
|
fn range_to() {
|
||||||
@ -83,6 +107,18 @@ fn range_to() {
|
|||||||
assert!(!yes!('a', ..'a'));
|
assert!(!yes!('a', ..'a'));
|
||||||
assert!(!yes!('b', ..'a'));
|
assert!(!yes!('b', ..'a'));
|
||||||
|
|
||||||
|
// f16; `..X`
|
||||||
|
// FIXME(f16_f128): remove gate when ABI issues are resolved
|
||||||
|
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
|
||||||
|
{
|
||||||
|
// FIXME(f16_f128): enable infinity tests when constants are available
|
||||||
|
// assert!(yes!(f16::NEG_INFINITY, ..1.0f16));
|
||||||
|
assert!(!yes!(1.5f16, ..1.5f16));
|
||||||
|
const E16: f16 = 1.5f16 + f16::EPSILON;
|
||||||
|
assert!(yes!(1.5f16, ..E16));
|
||||||
|
assert!(!yes!(1.6f16, ..1.5f16));
|
||||||
|
}
|
||||||
|
|
||||||
// f32; `..X`
|
// f32; `..X`
|
||||||
assert!(yes!(f32::NEG_INFINITY, ..1.0f32));
|
assert!(yes!(f32::NEG_INFINITY, ..1.0f32));
|
||||||
assert!(!yes!(1.5f32, ..1.5f32));
|
assert!(!yes!(1.5f32, ..1.5f32));
|
||||||
@ -96,6 +132,18 @@ fn range_to() {
|
|||||||
const E64: f64 = 1.5f64 + f64::EPSILON;
|
const E64: f64 = 1.5f64 + f64::EPSILON;
|
||||||
assert!(yes!(1.5f64, ..E64));
|
assert!(yes!(1.5f64, ..E64));
|
||||||
assert!(!yes!(1.6f64, ..1.5f64));
|
assert!(!yes!(1.6f64, ..1.5f64));
|
||||||
|
|
||||||
|
// f128; `..X`
|
||||||
|
// FIXME(f16_f128): remove gate when ABI issues are resolved
|
||||||
|
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
|
||||||
|
{
|
||||||
|
// FIXME(f16_f128): enable infinity tests when constants are available
|
||||||
|
// assert!(yes!(f128::NEG_INFINITY, ..1.0f128));
|
||||||
|
assert!(!yes!(1.5f128, ..1.5f128));
|
||||||
|
const E128: f128 = 1.5f128 + f128::EPSILON;
|
||||||
|
assert!(yes!(1.5f128, ..E128));
|
||||||
|
assert!(!yes!(1.6f128, ..1.5f128));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn range_from() {
|
fn range_from() {
|
||||||
@ -129,6 +177,21 @@ fn range_from() {
|
|||||||
assert!(!yes!('a', 'b'..));
|
assert!(!yes!('a', 'b'..));
|
||||||
assert!(yes!(core::char::MAX, core::char::MAX..));
|
assert!(yes!(core::char::MAX, core::char::MAX..));
|
||||||
|
|
||||||
|
// f16; `X..`
|
||||||
|
// FIXME(f16_f128): remove gate when ABI issues are resolved
|
||||||
|
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
|
||||||
|
{
|
||||||
|
// FIXME(f16_f128): enable infinity tests when constants are available
|
||||||
|
// assert!(yes!(f16::NEG_INFINITY, f16::NEG_INFINITY..));
|
||||||
|
// assert!(yes!(f16::INFINITY, f16::NEG_INFINITY..));
|
||||||
|
// assert!(!yes!(f16::NEG_INFINITY, 1.0f16..));
|
||||||
|
// assert!(yes!(f16::INFINITY, 1.0f16..));
|
||||||
|
assert!(!yes!(1.0f16 - f16::EPSILON, 1.0f16..));
|
||||||
|
assert!(yes!(1.0f16, 1.0f16..));
|
||||||
|
// assert!(yes!(f16::INFINITY, 1.0f16..));
|
||||||
|
// assert!(yes!(f16::INFINITY, f16::INFINITY..));
|
||||||
|
}
|
||||||
|
|
||||||
// f32; `X..`
|
// f32; `X..`
|
||||||
assert!(yes!(f32::NEG_INFINITY, f32::NEG_INFINITY..));
|
assert!(yes!(f32::NEG_INFINITY, f32::NEG_INFINITY..));
|
||||||
assert!(yes!(f32::INFINITY, f32::NEG_INFINITY..));
|
assert!(yes!(f32::INFINITY, f32::NEG_INFINITY..));
|
||||||
@ -148,6 +211,21 @@ fn range_from() {
|
|||||||
assert!(yes!(1.0f64, 1.0f64..));
|
assert!(yes!(1.0f64, 1.0f64..));
|
||||||
assert!(yes!(f64::INFINITY, 1.0f64..));
|
assert!(yes!(f64::INFINITY, 1.0f64..));
|
||||||
assert!(yes!(f64::INFINITY, f64::INFINITY..));
|
assert!(yes!(f64::INFINITY, f64::INFINITY..));
|
||||||
|
|
||||||
|
// f128; `X..`
|
||||||
|
// FIXME(f16_f128): remove gate when ABI issues are resolved
|
||||||
|
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
|
||||||
|
{
|
||||||
|
// FIXME(f16_f128): enable infinity tests when constants are available
|
||||||
|
// assert!(yes!(f128::NEG_INFINITY, f128::NEG_INFINITY..));
|
||||||
|
// assert!(yes!(f128::INFINITY, f128::NEG_INFINITY..));
|
||||||
|
// assert!(!yes!(f128::NEG_INFINITY, 1.0f128..));
|
||||||
|
// assert!(yes!(f128::INFINITY, 1.0f128..));
|
||||||
|
assert!(!yes!(1.0f128 - f128::EPSILON, 1.0f128..));
|
||||||
|
assert!(yes!(1.0f128, 1.0f128..));
|
||||||
|
// assert!(yes!(f128::INFINITY, 1.0f128..));
|
||||||
|
// assert!(yes!(f128::INFINITY, f128::INFINITY..));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -27,6 +27,7 @@ fn main() {
|
|||||||
m!(0, ..i128::MIN);
|
m!(0, ..i128::MIN);
|
||||||
//~^ ERROR lower range bound must be less than upper
|
//~^ ERROR lower range bound must be less than upper
|
||||||
|
|
||||||
|
// FIXME(f16_f128): add tests when NEG_INFINITY is available
|
||||||
m!(0f32, ..f32::NEG_INFINITY);
|
m!(0f32, ..f32::NEG_INFINITY);
|
||||||
//~^ ERROR lower range bound must be less than upper
|
//~^ ERROR lower range bound must be less than upper
|
||||||
m!(0f64, ..f64::NEG_INFINITY);
|
m!(0f64, ..f64::NEG_INFINITY);
|
||||||
|
@ -59,19 +59,19 @@ LL | m!(0, ..i128::MIN);
|
|||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0579]: lower range bound must be less than upper
|
error[E0579]: lower range bound must be less than upper
|
||||||
--> $DIR/half-open-range-pats-thir-lower-empty.rs:30:14
|
--> $DIR/half-open-range-pats-thir-lower-empty.rs:31:14
|
||||||
|
|
|
|
||||||
LL | m!(0f32, ..f32::NEG_INFINITY);
|
LL | m!(0f32, ..f32::NEG_INFINITY);
|
||||||
| ^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0579]: lower range bound must be less than upper
|
error[E0579]: lower range bound must be less than upper
|
||||||
--> $DIR/half-open-range-pats-thir-lower-empty.rs:32:14
|
--> $DIR/half-open-range-pats-thir-lower-empty.rs:33:14
|
||||||
|
|
|
|
||||||
LL | m!(0f64, ..f64::NEG_INFINITY);
|
LL | m!(0f64, ..f64::NEG_INFINITY);
|
||||||
| ^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0579]: lower range bound must be less than upper
|
error[E0579]: lower range bound must be less than upper
|
||||||
--> $DIR/half-open-range-pats-thir-lower-empty.rs:35:13
|
--> $DIR/half-open-range-pats-thir-lower-empty.rs:36:13
|
||||||
|
|
|
|
||||||
LL | m!('a', ..'\u{0}');
|
LL | m!('a', ..'\u{0}');
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -1,7 +1,22 @@
|
|||||||
//@ run-pass
|
//@ run-pass
|
||||||
// Makes sure we use `==` (not bitwise) semantics for float comparison.
|
// Makes sure we use `==` (not bitwise) semantics for float comparison.
|
||||||
|
|
||||||
fn main() {
|
#![feature(f128)]
|
||||||
|
#![feature(f16)]
|
||||||
|
|
||||||
|
// FIXME(f16_f128): remove gates when ABI issues are resolved
|
||||||
|
|
||||||
|
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
|
||||||
|
fn check_f16() {
|
||||||
|
const F1: f16 = 0.0;
|
||||||
|
const F2: f16 = -0.0;
|
||||||
|
assert_eq!(F1, F2);
|
||||||
|
assert_ne!(F1.to_bits(), F2.to_bits());
|
||||||
|
assert!(matches!(F1, F2));
|
||||||
|
assert!(matches!(F2, F1));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_f32() {
|
||||||
const F1: f32 = 0.0;
|
const F1: f32 = 0.0;
|
||||||
const F2: f32 = -0.0;
|
const F2: f32 = -0.0;
|
||||||
assert_eq!(F1, F2);
|
assert_eq!(F1, F2);
|
||||||
@ -9,3 +24,31 @@ fn main() {
|
|||||||
assert!(matches!(F1, F2));
|
assert!(matches!(F1, F2));
|
||||||
assert!(matches!(F2, F1));
|
assert!(matches!(F2, F1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_f64() {
|
||||||
|
const F1: f64 = 0.0;
|
||||||
|
const F2: f64 = -0.0;
|
||||||
|
assert_eq!(F1, F2);
|
||||||
|
assert_ne!(F1.to_bits(), F2.to_bits());
|
||||||
|
assert!(matches!(F1, F2));
|
||||||
|
assert!(matches!(F2, F1));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
|
||||||
|
fn check_f128() {
|
||||||
|
const F1: f128 = 0.0;
|
||||||
|
const F2: f128 = -0.0;
|
||||||
|
assert_eq!(F1, F2);
|
||||||
|
assert_ne!(F1.to_bits(), F2.to_bits());
|
||||||
|
assert!(matches!(F1, F2));
|
||||||
|
assert!(matches!(F2, F1));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
|
||||||
|
check_f16();
|
||||||
|
check_f32();
|
||||||
|
check_f64();
|
||||||
|
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
|
||||||
|
check_f128();
|
||||||
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#![deny(unreachable_patterns)]
|
#![deny(unreachable_patterns)]
|
||||||
|
#![feature(f128)]
|
||||||
|
#![feature(f16)]
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match 0.0 {
|
match 0.0 {
|
||||||
@ -11,6 +13,32 @@ fn main() {
|
|||||||
0.0..=1.0 => {}
|
0.0..=1.0 => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match 1.0f16 {
|
||||||
|
0.01f16..=6.5f16 => {}
|
||||||
|
0.01f16 => {} //~ ERROR unreachable pattern
|
||||||
|
0.02f16 => {} //~ ERROR unreachable pattern
|
||||||
|
6.5f16 => {} //~ ERROR unreachable pattern
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
match 1.0f16 {
|
||||||
|
0.01f16..6.5f16 => {}
|
||||||
|
6.5f16 => {} // this is reachable
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
match 1.0f32 {
|
||||||
|
0.01f32..=6.5f32 => {}
|
||||||
|
0.01f32 => {} //~ ERROR unreachable pattern
|
||||||
|
0.02f32 => {} //~ ERROR unreachable pattern
|
||||||
|
6.5f32 => {} //~ ERROR unreachable pattern
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
match 1.0f32 {
|
||||||
|
0.01f32..6.5f32 => {}
|
||||||
|
6.5f32 => {} // this is reachable
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
|
||||||
match 1.0f64 {
|
match 1.0f64 {
|
||||||
0.01f64..=6.5f64 => {}
|
0.01f64..=6.5f64 => {}
|
||||||
0.005f64 => {}
|
0.005f64 => {}
|
||||||
@ -28,16 +56,20 @@ fn main() {
|
|||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
match 1.0f32 {
|
match 1.0f128 {
|
||||||
0.01f32..=6.5f32 => {}
|
0.01f128..=6.5f128 => {}
|
||||||
0.01f32 => {} //~ ERROR unreachable pattern
|
0.005f128 => {}
|
||||||
0.02f32 => {} //~ ERROR unreachable pattern
|
0.01f128 => {} //~ ERROR unreachable pattern
|
||||||
6.5f32 => {} //~ ERROR unreachable pattern
|
0.02f128 => {} //~ ERROR unreachable pattern
|
||||||
|
6.5f128 => {} //~ ERROR unreachable pattern
|
||||||
|
6.6f128 => {}
|
||||||
|
1.0f128..=4.0f128 => {} //~ ERROR unreachable pattern
|
||||||
|
5.0f128..=7.0f128 => {}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
match 1.0f32 {
|
match 1.0f128 {
|
||||||
0.01f32..6.5f32 => {}
|
0.01f128..6.5f128 => {}
|
||||||
6.5f32 => {} // this is reachable
|
6.5f128 => {} // this is reachable
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error[E0004]: non-exhaustive patterns: `_` not covered
|
error[E0004]: non-exhaustive patterns: `_` not covered
|
||||||
--> $DIR/floats.rs:9:11
|
--> $DIR/floats.rs:11:11
|
||||||
|
|
|
|
||||||
LL | match 0.0 {
|
LL | match 0.0 {
|
||||||
| ^^^ pattern `_` not covered
|
| ^^^ pattern `_` not covered
|
||||||
@ -12,9 +12,9 @@ LL + _ => todo!()
|
|||||||
|
|
|
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/floats.rs:17:9
|
--> $DIR/floats.rs:18:9
|
||||||
|
|
|
|
||||||
LL | 0.01f64 => {}
|
LL | 0.01f16 => {}
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
@ -24,41 +24,83 @@ LL | #![deny(unreachable_patterns)]
|
|||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/floats.rs:18:9
|
--> $DIR/floats.rs:19:9
|
||||||
|
|
|
|
||||||
LL | 0.02f64 => {}
|
LL | 0.02f16 => {}
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/floats.rs:19:9
|
--> $DIR/floats.rs:20:9
|
||||||
|
|
|
|
||||||
LL | 6.5f64 => {}
|
LL | 6.5f16 => {}
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/floats.rs:21:9
|
--> $DIR/floats.rs:31:9
|
||||||
|
|
|
||||||
LL | 1.0f64..=4.0f64 => {}
|
|
||||||
| ^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: unreachable pattern
|
|
||||||
--> $DIR/floats.rs:33:9
|
|
||||||
|
|
|
|
||||||
LL | 0.01f32 => {}
|
LL | 0.01f32 => {}
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/floats.rs:34:9
|
--> $DIR/floats.rs:32:9
|
||||||
|
|
|
|
||||||
LL | 0.02f32 => {}
|
LL | 0.02f32 => {}
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/floats.rs:35:9
|
--> $DIR/floats.rs:33:9
|
||||||
|
|
|
|
||||||
LL | 6.5f32 => {}
|
LL | 6.5f32 => {}
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
||||||
error: aborting due to 8 previous errors
|
error: unreachable pattern
|
||||||
|
--> $DIR/floats.rs:45:9
|
||||||
|
|
|
||||||
|
LL | 0.01f64 => {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/floats.rs:46:9
|
||||||
|
|
|
||||||
|
LL | 0.02f64 => {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/floats.rs:47:9
|
||||||
|
|
|
||||||
|
LL | 6.5f64 => {}
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/floats.rs:49:9
|
||||||
|
|
|
||||||
|
LL | 1.0f64..=4.0f64 => {}
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/floats.rs:62:9
|
||||||
|
|
|
||||||
|
LL | 0.01f128 => {}
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/floats.rs:63:9
|
||||||
|
|
|
||||||
|
LL | 0.02f128 => {}
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/floats.rs:64:9
|
||||||
|
|
|
||||||
|
LL | 6.5f128 => {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/floats.rs:66:9
|
||||||
|
|
|
||||||
|
LL | 1.0f128..=4.0f128 => {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 15 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0004`.
|
For more information about this error, try `rustc --explain E0004`.
|
||||||
|
Loading…
Reference in New Issue
Block a user