Skip to content

Commit aabbf84

Browse files
committedJun 23, 2024
Auto merge of #123088 - tgross35:f16-f128-pattern-analysis, r=Nadrieril
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. r? `@Nadrieril`
2 parents c3d7fb3 + 28ce7cd commit aabbf84

File tree

13 files changed

+323
-43
lines changed

13 files changed

+323
-43
lines changed
 

‎compiler/rustc_middle/src/thir.rs

+12
Original file line numberDiff line numberDiff line change
@@ -1047,6 +1047,12 @@ impl<'tcx> PatRangeBoundary<'tcx> {
10471047
let b = other.eval_bits(ty, tcx, param_env);
10481048

10491049
match ty.kind() {
1050+
ty::Float(ty::FloatTy::F16) => {
1051+
use rustc_apfloat::Float;
1052+
let a = rustc_apfloat::ieee::Half::from_bits(a);
1053+
let b = rustc_apfloat::ieee::Half::from_bits(b);
1054+
a.partial_cmp(&b)
1055+
}
10501056
ty::Float(ty::FloatTy::F32) => {
10511057
use rustc_apfloat::Float;
10521058
let a = rustc_apfloat::ieee::Single::from_bits(a);
@@ -1059,6 +1065,12 @@ impl<'tcx> PatRangeBoundary<'tcx> {
10591065
let b = rustc_apfloat::ieee::Double::from_bits(b);
10601066
a.partial_cmp(&b)
10611067
}
1068+
ty::Float(ty::FloatTy::F128) => {
1069+
use rustc_apfloat::Float;
1070+
let a = rustc_apfloat::ieee::Quad::from_bits(a);
1071+
let b = rustc_apfloat::ieee::Quad::from_bits(b);
1072+
a.partial_cmp(&b)
1073+
}
10621074
ty::Int(ity) => {
10631075
let size = rustc_target::abi::Integer::from_int_ty(&tcx, *ity).size();
10641076
let a = size.sign_extend(a) as i128;

‎compiler/rustc_middle/src/ty/util.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1196,7 +1196,7 @@ impl<'tcx> Ty<'tcx> {
11961196
/// Returns the minimum and maximum values for the given numeric type (including `char`s) or
11971197
/// returns `None` if the type is not numeric.
11981198
pub fn numeric_min_and_max_as_bits(self, tcx: TyCtxt<'tcx>) -> Option<(u128, u128)> {
1199-
use rustc_apfloat::ieee::{Double, Single};
1199+
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
12001200
Some(match self.kind() {
12011201
ty::Int(_) | ty::Uint(_) => {
12021202
let (size, signed) = self.int_size_and_signed(tcx);
@@ -1206,12 +1206,14 @@ impl<'tcx> Ty<'tcx> {
12061206
(min, max)
12071207
}
12081208
ty::Char => (0, std::char::MAX as u128),
1209+
ty::Float(ty::FloatTy::F16) => ((-Half::INFINITY).to_bits(), Half::INFINITY.to_bits()),
12091210
ty::Float(ty::FloatTy::F32) => {
12101211
((-Single::INFINITY).to_bits(), Single::INFINITY.to_bits())
12111212
}
12121213
ty::Float(ty::FloatTy::F64) => {
12131214
((-Double::INFINITY).to_bits(), Double::INFINITY.to_bits())
12141215
}
1216+
ty::Float(ty::FloatTy::F128) => ((-Quad::INFINITY).to_bits(), Quad::INFINITY.to_bits()),
12151217
_ => return None,
12161218
})
12171219
}

‎compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -369,10 +369,10 @@ impl<'tcx> ConstToPat<'tcx> {
369369
ty::Float(flt) => {
370370
let v = cv.unwrap_leaf();
371371
let is_nan = match flt {
372-
ty::FloatTy::F16 => unimplemented!("f16_f128"),
372+
ty::FloatTy::F16 => v.to_f16().is_nan(),
373373
ty::FloatTy::F32 => v.to_f32().is_nan(),
374374
ty::FloatTy::F64 => v.to_f64().is_nan(),
375-
ty::FloatTy::F128 => unimplemented!("f16_f128"),
375+
ty::FloatTy::F128 => v.to_f128().is_nan(),
376376
};
377377
if is_nan {
378378
// NaNs are not ever equal to anything so they make no sense as patterns.

‎compiler/rustc_pattern_analysis/src/constructor.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ use std::iter::once;
182182

183183
use smallvec::SmallVec;
184184

185-
use rustc_apfloat::ieee::{DoubleS, IeeeFloat, SingleS};
185+
use rustc_apfloat::ieee::{DoubleS, HalfS, IeeeFloat, QuadS, SingleS};
186186
use rustc_index::bit_set::{BitSet, GrowableBitSet};
187187
use rustc_index::IndexVec;
188188

@@ -692,8 +692,10 @@ pub enum Constructor<Cx: PatCx> {
692692
/// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
693693
IntRange(IntRange),
694694
/// Ranges of floating-point literal values (`2.0..=5.2`).
695+
F16Range(IeeeFloat<HalfS>, IeeeFloat<HalfS>, RangeEnd),
695696
F32Range(IeeeFloat<SingleS>, IeeeFloat<SingleS>, RangeEnd),
696697
F64Range(IeeeFloat<DoubleS>, IeeeFloat<DoubleS>, RangeEnd),
698+
F128Range(IeeeFloat<QuadS>, IeeeFloat<QuadS>, RangeEnd),
697699
/// String literals. Strings are not quite the same as `&[u8]` so we treat them separately.
698700
Str(Cx::StrLit),
699701
/// Constants that must not be matched structurally. They are treated as black boxes for the
@@ -735,8 +737,10 @@ impl<Cx: PatCx> Clone for Constructor<Cx> {
735737
Constructor::UnionField => Constructor::UnionField,
736738
Constructor::Bool(b) => Constructor::Bool(*b),
737739
Constructor::IntRange(range) => Constructor::IntRange(*range),
740+
Constructor::F16Range(lo, hi, end) => Constructor::F16Range(lo.clone(), *hi, *end),
738741
Constructor::F32Range(lo, hi, end) => Constructor::F32Range(lo.clone(), *hi, *end),
739742
Constructor::F64Range(lo, hi, end) => Constructor::F64Range(lo.clone(), *hi, *end),
743+
Constructor::F128Range(lo, hi, end) => Constructor::F128Range(lo.clone(), *hi, *end),
740744
Constructor::Str(value) => Constructor::Str(value.clone()),
741745
Constructor::Opaque(inner) => Constructor::Opaque(inner.clone()),
742746
Constructor::Or => Constructor::Or,
@@ -812,6 +816,14 @@ impl<Cx: PatCx> Constructor<Cx> {
812816
(Bool(self_b), Bool(other_b)) => self_b == other_b,
813817

814818
(IntRange(self_range), IntRange(other_range)) => self_range.is_subrange(other_range),
819+
(F16Range(self_from, self_to, self_end), F16Range(other_from, other_to, other_end)) => {
820+
self_from.ge(other_from)
821+
&& match self_to.partial_cmp(other_to) {
822+
Some(Ordering::Less) => true,
823+
Some(Ordering::Equal) => other_end == self_end,
824+
_ => false,
825+
}
826+
}
815827
(F32Range(self_from, self_to, self_end), F32Range(other_from, other_to, other_end)) => {
816828
self_from.ge(other_from)
817829
&& match self_to.partial_cmp(other_to) {
@@ -828,6 +840,17 @@ impl<Cx: PatCx> Constructor<Cx> {
828840
_ => false,
829841
}
830842
}
843+
(
844+
F128Range(self_from, self_to, self_end),
845+
F128Range(other_from, other_to, other_end),
846+
) => {
847+
self_from.ge(other_from)
848+
&& match self_to.partial_cmp(other_to) {
849+
Some(Ordering::Less) => true,
850+
Some(Ordering::Equal) => other_end == self_end,
851+
_ => false,
852+
}
853+
}
831854
(Str(self_val), Str(other_val)) => {
832855
// FIXME Once valtrees are available we can directly use the bytes
833856
// in the `Str` variant of the valtree for the comparison here.
@@ -906,8 +929,10 @@ impl<Cx: PatCx> Constructor<Cx> {
906929
Bool(b) => write!(f, "{b}")?,
907930
// Best-effort, will render signed ranges incorrectly
908931
IntRange(range) => write!(f, "{range:?}")?,
932+
F16Range(lo, hi, end) => write!(f, "{lo}{end}{hi}")?,
909933
F32Range(lo, hi, end) => write!(f, "{lo}{end}{hi}")?,
910934
F64Range(lo, hi, end) => write!(f, "{lo}{end}{hi}")?,
935+
F128Range(lo, hi, end) => write!(f, "{lo}{end}{hi}")?,
911936
Str(value) => write!(f, "{value:?}")?,
912937
Opaque(..) => write!(f, "<constant pattern>")?,
913938
Or => {

‎compiler/rustc_pattern_analysis/src/rustc.rs

+43-7
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,9 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
247247
}
248248
_ => bug!("bad slice pattern {:?} {:?}", ctor, ty),
249249
},
250-
Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..)
251-
| Never | NonExhaustive | Hidden | Missing | PrivateUninhabited | Wildcard => &[],
250+
Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..)
251+
| F128Range(..) | Str(..) | Opaque(..) | Never | NonExhaustive | Hidden | Missing
252+
| PrivateUninhabited | Wildcard => &[],
252253
Or => {
253254
bug!("called `Fields::wildcards` on an `Or` ctor")
254255
}
@@ -275,8 +276,9 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
275276
},
276277
Ref => 1,
277278
Slice(slice) => slice.arity(),
278-
Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..)
279-
| Never | NonExhaustive | Hidden | Missing | PrivateUninhabited | Wildcard => 0,
279+
Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..)
280+
| F128Range(..) | Str(..) | Opaque(..) | Never | NonExhaustive | Hidden | Missing
281+
| PrivateUninhabited | Wildcard => 0,
280282
Or => bug!("The `Or` constructor doesn't have a fixed arity"),
281283
}
282284
}
@@ -546,6 +548,18 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
546548
fields = vec![];
547549
arity = 0;
548550
}
551+
ty::Float(ty::FloatTy::F16) => {
552+
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
553+
Some(bits) => {
554+
use rustc_apfloat::Float;
555+
let value = rustc_apfloat::ieee::Half::from_bits(bits);
556+
F16Range(value, value, RangeEnd::Included)
557+
}
558+
None => Opaque(OpaqueId::new()),
559+
};
560+
fields = vec![];
561+
arity = 0;
562+
}
549563
ty::Float(ty::FloatTy::F32) => {
550564
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
551565
Some(bits) => {
@@ -570,6 +584,18 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
570584
fields = vec![];
571585
arity = 0;
572586
}
587+
ty::Float(ty::FloatTy::F128) => {
588+
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
589+
Some(bits) => {
590+
use rustc_apfloat::Float;
591+
let value = rustc_apfloat::ieee::Quad::from_bits(bits);
592+
F128Range(value, value, RangeEnd::Included)
593+
}
594+
None => Opaque(OpaqueId::new()),
595+
};
596+
fields = vec![];
597+
arity = 0;
598+
}
573599
ty::Ref(_, t, _) if t.is_str() => {
574600
// We want a `&str` constant to behave like a `Deref` pattern, to be compatible
575601
// with other `Deref` patterns. This could have been done in `const_to_pat`,
@@ -611,7 +637,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
611637
let lo = lo.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env));
612638
let hi = hi.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env));
613639
match fty {
614-
ty::FloatTy::F16 => unimplemented!("f16_f128"),
640+
ty::FloatTy::F16 => {
641+
use rustc_apfloat::ieee::Half;
642+
let lo = lo.map(Half::from_bits).unwrap_or(-Half::INFINITY);
643+
let hi = hi.map(Half::from_bits).unwrap_or(Half::INFINITY);
644+
F16Range(lo, hi, end)
645+
}
615646
ty::FloatTy::F32 => {
616647
use rustc_apfloat::ieee::Single;
617648
let lo = lo.map(Single::from_bits).unwrap_or(-Single::INFINITY);
@@ -624,7 +655,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
624655
let hi = hi.map(Double::from_bits).unwrap_or(Double::INFINITY);
625656
F64Range(lo, hi, end)
626657
}
627-
ty::FloatTy::F128 => unimplemented!("f16_f128"),
658+
ty::FloatTy::F128 => {
659+
use rustc_apfloat::ieee::Quad;
660+
let lo = lo.map(Quad::from_bits).unwrap_or(-Quad::INFINITY);
661+
let hi = hi.map(Quad::from_bits).unwrap_or(Quad::INFINITY);
662+
F128Range(lo, hi, end)
663+
}
628664
}
629665
}
630666
_ => bug!("invalid type for range pattern: {}", ty.inner()),
@@ -837,7 +873,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
837873
"trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
838874
`Missing` should have been processed in `apply_constructors`"
839875
),
840-
F32Range(..) | F64Range(..) | Opaque(..) | Or => {
876+
F16Range(..) | F32Range(..) | F64Range(..) | F128Range(..) | Opaque(..) | Or => {
841877
bug!("can't convert to pattern: {:?}", pat)
842878
}
843879
};

‎tests/crashes/122587-1.rs

-5
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//@ check-pass
2+
// issue: rust-lang/rust#122587
3+
4+
#![feature(f128)]
5+
#![feature(f16)]
6+
#![allow(non_upper_case_globals)]
7+
8+
const h: f16 = 0.0f16;
9+
const q: f128 = 0.0f128;
10+
11+
pub fn main() {
12+
let h = 0.0f16 else { unreachable!() };
13+
let q = 0.0f128 else { unreachable!() };
14+
}

‎tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs

+78
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
// via `.contains(...)` and make sure the dynamic semantics match.
55

66
#![allow(unreachable_patterns)]
7+
#![feature(f128)]
8+
#![feature(f16)]
79

810
macro_rules! yes {
911
($scrutinee:expr, $($t:tt)+) => {
@@ -39,6 +41,17 @@ fn range_to_inclusive() {
3941
assert!(yes!('a', ..='a'));
4042
assert!(!yes!('b', ..='a'));
4143

44+
// f16; `..=X`
45+
// FIXME(f16_f128): remove gate when ABI issues are resolved
46+
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
47+
{
48+
// FIXME(f16_f128): enable infinity tests when constants are available
49+
// assert!(yes!(f16::NEG_INFINITY, ..=f16::NEG_INFINITY));
50+
// assert!(yes!(f16::NEG_INFINITY, ..=1.0f16));
51+
assert!(yes!(1.5f16, ..=1.5f16));
52+
assert!(!yes!(1.6f16, ..=-1.5f16));
53+
}
54+
4255
// f32; `..=X`
4356
assert!(yes!(f32::NEG_INFINITY, ..=f32::NEG_INFINITY));
4457
assert!(yes!(f32::NEG_INFINITY, ..=1.0f32));
@@ -50,6 +63,17 @@ fn range_to_inclusive() {
5063
assert!(yes!(f64::NEG_INFINITY, ..=1.0f64));
5164
assert!(yes!(1.5f64, ..=1.5f64));
5265
assert!(!yes!(1.6f64, ..=-1.5f64));
66+
67+
// f128; `..=X`
68+
// FIXME(f16_f128): remove gate when ABI issues are resolved
69+
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
70+
{
71+
// FIXME(f16_f128): enable infinity tests when constants are available
72+
// assert!(yes!(f128::NEG_INFINITY, ..=f128::NEG_INFINITY));
73+
// assert!(yes!(f128::NEG_INFINITY, ..=1.0f128));
74+
assert!(yes!(1.5f128, ..=1.5f128));
75+
assert!(!yes!(1.6f128, ..=-1.5f128));
76+
}
5377
}
5478

5579
fn range_to() {
@@ -83,6 +107,18 @@ fn range_to() {
83107
assert!(!yes!('a', ..'a'));
84108
assert!(!yes!('b', ..'a'));
85109

110+
// f16; `..X`
111+
// FIXME(f16_f128): remove gate when ABI issues are resolved
112+
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
113+
{
114+
// FIXME(f16_f128): enable infinity tests when constants are available
115+
// assert!(yes!(f16::NEG_INFINITY, ..1.0f16));
116+
assert!(!yes!(1.5f16, ..1.5f16));
117+
const E16: f16 = 1.5f16 + f16::EPSILON;
118+
assert!(yes!(1.5f16, ..E16));
119+
assert!(!yes!(1.6f16, ..1.5f16));
120+
}
121+
86122
// f32; `..X`
87123
assert!(yes!(f32::NEG_INFINITY, ..1.0f32));
88124
assert!(!yes!(1.5f32, ..1.5f32));
@@ -96,6 +132,18 @@ fn range_to() {
96132
const E64: f64 = 1.5f64 + f64::EPSILON;
97133
assert!(yes!(1.5f64, ..E64));
98134
assert!(!yes!(1.6f64, ..1.5f64));
135+
136+
// f128; `..X`
137+
// FIXME(f16_f128): remove gate when ABI issues are resolved
138+
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
139+
{
140+
// FIXME(f16_f128): enable infinity tests when constants are available
141+
// assert!(yes!(f128::NEG_INFINITY, ..1.0f128));
142+
assert!(!yes!(1.5f128, ..1.5f128));
143+
const E128: f128 = 1.5f128 + f128::EPSILON;
144+
assert!(yes!(1.5f128, ..E128));
145+
assert!(!yes!(1.6f128, ..1.5f128));
146+
}
99147
}
100148

101149
fn range_from() {
@@ -129,6 +177,21 @@ fn range_from() {
129177
assert!(!yes!('a', 'b'..));
130178
assert!(yes!(core::char::MAX, core::char::MAX..));
131179

180+
// f16; `X..`
181+
// FIXME(f16_f128): remove gate when ABI issues are resolved
182+
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
183+
{
184+
// FIXME(f16_f128): enable infinity tests when constants are available
185+
// assert!(yes!(f16::NEG_INFINITY, f16::NEG_INFINITY..));
186+
// assert!(yes!(f16::INFINITY, f16::NEG_INFINITY..));
187+
// assert!(!yes!(f16::NEG_INFINITY, 1.0f16..));
188+
// assert!(yes!(f16::INFINITY, 1.0f16..));
189+
assert!(!yes!(1.0f16 - f16::EPSILON, 1.0f16..));
190+
assert!(yes!(1.0f16, 1.0f16..));
191+
// assert!(yes!(f16::INFINITY, 1.0f16..));
192+
// assert!(yes!(f16::INFINITY, f16::INFINITY..));
193+
}
194+
132195
// f32; `X..`
133196
assert!(yes!(f32::NEG_INFINITY, f32::NEG_INFINITY..));
134197
assert!(yes!(f32::INFINITY, f32::NEG_INFINITY..));
@@ -148,6 +211,21 @@ fn range_from() {
148211
assert!(yes!(1.0f64, 1.0f64..));
149212
assert!(yes!(f64::INFINITY, 1.0f64..));
150213
assert!(yes!(f64::INFINITY, f64::INFINITY..));
214+
215+
// f128; `X..`
216+
// FIXME(f16_f128): remove gate when ABI issues are resolved
217+
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
218+
{
219+
// FIXME(f16_f128): enable infinity tests when constants are available
220+
// assert!(yes!(f128::NEG_INFINITY, f128::NEG_INFINITY..));
221+
// assert!(yes!(f128::INFINITY, f128::NEG_INFINITY..));
222+
// assert!(!yes!(f128::NEG_INFINITY, 1.0f128..));
223+
// assert!(yes!(f128::INFINITY, 1.0f128..));
224+
assert!(!yes!(1.0f128 - f128::EPSILON, 1.0f128..));
225+
assert!(yes!(1.0f128, 1.0f128..));
226+
// assert!(yes!(f128::INFINITY, 1.0f128..));
227+
// assert!(yes!(f128::INFINITY, f128::INFINITY..));
228+
}
151229
}
152230

153231
fn main() {

‎tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ fn main() {
2727
m!(0, ..i128::MIN);
2828
//~^ ERROR lower range bound must be less than upper
2929

30+
// FIXME(f16_f128): add tests when NEG_INFINITY is available
3031
m!(0f32, ..f32::NEG_INFINITY);
3132
//~^ ERROR lower range bound must be less than upper
3233
m!(0f64, ..f64::NEG_INFINITY);

‎tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,19 @@ LL | m!(0, ..i128::MIN);
5959
| ^^^^^^^^^^^
6060

6161
error[E0579]: lower range bound must be less than upper
62-
--> $DIR/half-open-range-pats-thir-lower-empty.rs:30:14
62+
--> $DIR/half-open-range-pats-thir-lower-empty.rs:31:14
6363
|
6464
LL | m!(0f32, ..f32::NEG_INFINITY);
6565
| ^^^^^^^^^^^^^^^^^^^
6666

6767
error[E0579]: lower range bound must be less than upper
68-
--> $DIR/half-open-range-pats-thir-lower-empty.rs:32:14
68+
--> $DIR/half-open-range-pats-thir-lower-empty.rs:33:14
6969
|
7070
LL | m!(0f64, ..f64::NEG_INFINITY);
7171
| ^^^^^^^^^^^^^^^^^^^
7272

7373
error[E0579]: lower range bound must be less than upper
74-
--> $DIR/half-open-range-pats-thir-lower-empty.rs:35:13
74+
--> $DIR/half-open-range-pats-thir-lower-empty.rs:36:13
7575
|
7676
LL | m!('a', ..'\u{0}');
7777
| ^^^^^^^^^

‎tests/ui/match/match-float.rs

+44-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,54 @@
11
//@ run-pass
22
// Makes sure we use `==` (not bitwise) semantics for float comparison.
33

4-
fn main() {
4+
#![feature(f128)]
5+
#![feature(f16)]
6+
7+
// FIXME(f16_f128): remove gates when ABI issues are resolved
8+
9+
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
10+
fn check_f16() {
11+
const F1: f16 = 0.0;
12+
const F2: f16 = -0.0;
13+
assert_eq!(F1, F2);
14+
assert_ne!(F1.to_bits(), F2.to_bits());
15+
assert!(matches!(F1, F2));
16+
assert!(matches!(F2, F1));
17+
}
18+
19+
fn check_f32() {
520
const F1: f32 = 0.0;
621
const F2: f32 = -0.0;
722
assert_eq!(F1, F2);
823
assert_ne!(F1.to_bits(), F2.to_bits());
924
assert!(matches!(F1, F2));
1025
assert!(matches!(F2, F1));
1126
}
27+
28+
fn check_f64() {
29+
const F1: f64 = 0.0;
30+
const F2: f64 = -0.0;
31+
assert_eq!(F1, F2);
32+
assert_ne!(F1.to_bits(), F2.to_bits());
33+
assert!(matches!(F1, F2));
34+
assert!(matches!(F2, F1));
35+
}
36+
37+
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
38+
fn check_f128() {
39+
const F1: f128 = 0.0;
40+
const F2: f128 = -0.0;
41+
assert_eq!(F1, F2);
42+
assert_ne!(F1.to_bits(), F2.to_bits());
43+
assert!(matches!(F1, F2));
44+
assert!(matches!(F2, F1));
45+
}
46+
47+
fn main() {
48+
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
49+
check_f16();
50+
check_f32();
51+
check_f64();
52+
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
53+
check_f128();
54+
}

‎tests/ui/pattern/usefulness/floats.rs

+40-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#![deny(unreachable_patterns)]
2+
#![feature(f128)]
3+
#![feature(f16)]
24

35
fn main() {
46
match 0.0 {
@@ -11,6 +13,32 @@ fn main() {
1113
0.0..=1.0 => {}
1214
}
1315

16+
match 1.0f16 {
17+
0.01f16..=6.5f16 => {}
18+
0.01f16 => {} //~ ERROR unreachable pattern
19+
0.02f16 => {} //~ ERROR unreachable pattern
20+
6.5f16 => {} //~ ERROR unreachable pattern
21+
_ => {}
22+
};
23+
match 1.0f16 {
24+
0.01f16..6.5f16 => {}
25+
6.5f16 => {} // this is reachable
26+
_ => {}
27+
};
28+
29+
match 1.0f32 {
30+
0.01f32..=6.5f32 => {}
31+
0.01f32 => {} //~ ERROR unreachable pattern
32+
0.02f32 => {} //~ ERROR unreachable pattern
33+
6.5f32 => {} //~ ERROR unreachable pattern
34+
_ => {}
35+
};
36+
match 1.0f32 {
37+
0.01f32..6.5f32 => {}
38+
6.5f32 => {} // this is reachable
39+
_ => {}
40+
};
41+
1442
match 1.0f64 {
1543
0.01f64..=6.5f64 => {}
1644
0.005f64 => {}
@@ -28,16 +56,20 @@ fn main() {
2856
_ => {}
2957
};
3058

31-
match 1.0f32 {
32-
0.01f32..=6.5f32 => {}
33-
0.01f32 => {} //~ ERROR unreachable pattern
34-
0.02f32 => {} //~ ERROR unreachable pattern
35-
6.5f32 => {} //~ ERROR unreachable pattern
59+
match 1.0f128 {
60+
0.01f128..=6.5f128 => {}
61+
0.005f128 => {}
62+
0.01f128 => {} //~ ERROR unreachable pattern
63+
0.02f128 => {} //~ ERROR unreachable pattern
64+
6.5f128 => {} //~ ERROR unreachable pattern
65+
6.6f128 => {}
66+
1.0f128..=4.0f128 => {} //~ ERROR unreachable pattern
67+
5.0f128..=7.0f128 => {}
3668
_ => {}
3769
};
38-
match 1.0f32 {
39-
0.01f32..6.5f32 => {}
40-
6.5f32 => {} // this is reachable
70+
match 1.0f128 {
71+
0.01f128..6.5f128 => {}
72+
6.5f128 => {} // this is reachable
4173
_ => {}
4274
};
4375
}
+57-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0004]: non-exhaustive patterns: `_` not covered
2-
--> $DIR/floats.rs:9:11
2+
--> $DIR/floats.rs:11:11
33
|
44
LL | match 0.0 {
55
| ^^^ pattern `_` not covered
@@ -12,9 +12,9 @@ LL + _ => todo!()
1212
|
1313

1414
error: unreachable pattern
15-
--> $DIR/floats.rs:17:9
15+
--> $DIR/floats.rs:18:9
1616
|
17-
LL | 0.01f64 => {}
17+
LL | 0.01f16 => {}
1818
| ^^^^^^^
1919
|
2020
note: the lint level is defined here
@@ -24,41 +24,83 @@ LL | #![deny(unreachable_patterns)]
2424
| ^^^^^^^^^^^^^^^^^^^^
2525

2626
error: unreachable pattern
27-
--> $DIR/floats.rs:18:9
27+
--> $DIR/floats.rs:19:9
28+
|
29+
LL | 0.02f16 => {}
30+
| ^^^^^^^
31+
32+
error: unreachable pattern
33+
--> $DIR/floats.rs:20:9
34+
|
35+
LL | 6.5f16 => {}
36+
| ^^^^^^
37+
38+
error: unreachable pattern
39+
--> $DIR/floats.rs:31:9
40+
|
41+
LL | 0.01f32 => {}
42+
| ^^^^^^^
43+
44+
error: unreachable pattern
45+
--> $DIR/floats.rs:32:9
46+
|
47+
LL | 0.02f32 => {}
48+
| ^^^^^^^
49+
50+
error: unreachable pattern
51+
--> $DIR/floats.rs:33:9
52+
|
53+
LL | 6.5f32 => {}
54+
| ^^^^^^
55+
56+
error: unreachable pattern
57+
--> $DIR/floats.rs:45:9
58+
|
59+
LL | 0.01f64 => {}
60+
| ^^^^^^^
61+
62+
error: unreachable pattern
63+
--> $DIR/floats.rs:46:9
2864
|
2965
LL | 0.02f64 => {}
3066
| ^^^^^^^
3167

3268
error: unreachable pattern
33-
--> $DIR/floats.rs:19:9
69+
--> $DIR/floats.rs:47:9
3470
|
3571
LL | 6.5f64 => {}
3672
| ^^^^^^
3773

3874
error: unreachable pattern
39-
--> $DIR/floats.rs:21:9
75+
--> $DIR/floats.rs:49:9
4076
|
4177
LL | 1.0f64..=4.0f64 => {}
4278
| ^^^^^^^^^^^^^^^
4379

4480
error: unreachable pattern
45-
--> $DIR/floats.rs:33:9
81+
--> $DIR/floats.rs:62:9
4682
|
47-
LL | 0.01f32 => {}
48-
| ^^^^^^^
83+
LL | 0.01f128 => {}
84+
| ^^^^^^^^
4985

5086
error: unreachable pattern
51-
--> $DIR/floats.rs:34:9
87+
--> $DIR/floats.rs:63:9
5288
|
53-
LL | 0.02f32 => {}
89+
LL | 0.02f128 => {}
90+
| ^^^^^^^^
91+
92+
error: unreachable pattern
93+
--> $DIR/floats.rs:64:9
94+
|
95+
LL | 6.5f128 => {}
5496
| ^^^^^^^
5597

5698
error: unreachable pattern
57-
--> $DIR/floats.rs:35:9
99+
--> $DIR/floats.rs:66:9
58100
|
59-
LL | 6.5f32 => {}
60-
| ^^^^^^
101+
LL | 1.0f128..=4.0f128 => {}
102+
| ^^^^^^^^^^^^^^^^^
61103

62-
error: aborting due to 8 previous errors
104+
error: aborting due to 15 previous errors
63105

64106
For more information about this error, try `rustc --explain E0004`.

0 commit comments

Comments
 (0)
Please sign in to comment.