Skip to content

Commit 284129a

Browse files
committed
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.
1 parent 73476d4 commit 284129a

File tree

3 files changed

+76
-9
lines changed

3 files changed

+76
-9
lines changed

Diff for: compiler/rustc_pattern_analysis/src/constructor.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ use std::iter::once;
154154

155155
use smallvec::SmallVec;
156156

157-
use rustc_apfloat::ieee::{DoubleS, IeeeFloat, SingleS};
157+
use rustc_apfloat::ieee::{DoubleS, HalfS, IeeeFloat, QuadS, SingleS};
158158
use rustc_index::bit_set::GrowableBitSet;
159159

160160
use self::Constructor::*;
@@ -664,8 +664,10 @@ pub enum Constructor<Cx: PatCx> {
664664
/// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
665665
IntRange(IntRange),
666666
/// Ranges of floating-point literal values (`2.0..=5.2`).
667+
F16Range(IeeeFloat<HalfS>, IeeeFloat<HalfS>, RangeEnd),
667668
F32Range(IeeeFloat<SingleS>, IeeeFloat<SingleS>, RangeEnd),
668669
F64Range(IeeeFloat<DoubleS>, IeeeFloat<DoubleS>, RangeEnd),
670+
F128Range(IeeeFloat<QuadS>, IeeeFloat<QuadS>, RangeEnd),
669671
/// String literals. Strings are not quite the same as `&[u8]` so we treat them separately.
670672
Str(Cx::StrLit),
671673
/// Constants that must not be matched structurally. They are treated as black boxes for the
@@ -707,8 +709,10 @@ impl<Cx: PatCx> Clone for Constructor<Cx> {
707709
Constructor::UnionField => Constructor::UnionField,
708710
Constructor::Bool(b) => Constructor::Bool(*b),
709711
Constructor::IntRange(range) => Constructor::IntRange(*range),
712+
Constructor::F16Range(lo, hi, end) => Constructor::F16Range(lo.clone(), *hi, *end),
710713
Constructor::F32Range(lo, hi, end) => Constructor::F32Range(lo.clone(), *hi, *end),
711714
Constructor::F64Range(lo, hi, end) => Constructor::F64Range(lo.clone(), *hi, *end),
715+
Constructor::F128Range(lo, hi, end) => Constructor::F128Range(lo.clone(), *hi, *end),
712716
Constructor::Str(value) => Constructor::Str(value.clone()),
713717
Constructor::Opaque(inner) => Constructor::Opaque(inner.clone()),
714718
Constructor::Or => Constructor::Or,
@@ -784,6 +788,7 @@ impl<Cx: PatCx> Constructor<Cx> {
784788
(Bool(self_b), Bool(other_b)) => self_b == other_b,
785789

786790
(IntRange(self_range), IntRange(other_range)) => self_range.is_subrange(other_range),
791+
// FIXME(f32_f128): add implementations for f16 and f128 when `cmp` is available
787792
(F32Range(self_from, self_to, self_end), F32Range(other_from, other_to, other_end)) => {
788793
self_from.ge(other_from)
789794
&& match self_to.partial_cmp(other_to) {
@@ -878,8 +883,10 @@ impl<Cx: PatCx> Constructor<Cx> {
878883
Bool(b) => write!(f, "{b}")?,
879884
// Best-effort, will render signed ranges incorrectly
880885
IntRange(range) => write!(f, "{range:?}")?,
886+
F16Range(lo, hi, end) => write!(f, "{lo}{end}{hi}")?,
881887
F32Range(lo, hi, end) => write!(f, "{lo}{end}{hi}")?,
882888
F64Range(lo, hi, end) => write!(f, "{lo}{end}{hi}")?,
889+
F128Range(lo, hi, end) => write!(f, "{lo}{end}{hi}")?,
883890
Str(value) => write!(f, "{value:?}")?,
884891
Opaque(..) => write!(f, "<constant pattern>")?,
885892
Or => {

Diff for: compiler/rustc_pattern_analysis/src/rustc.rs

+43-7
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,9 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
246246
}
247247
_ => bug!("bad slice pattern {:?} {:?}", ctor, ty),
248248
},
249-
Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..)
250-
| Never | NonExhaustive | Hidden | Missing | PrivateUninhabited | Wildcard => &[],
249+
Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..)
250+
| F128Range(..) | Str(..) | Opaque(..) | Never | NonExhaustive | Hidden | Missing
251+
| PrivateUninhabited | Wildcard => &[],
251252
Or => {
252253
bug!("called `Fields::wildcards` on an `Or` ctor")
253254
}
@@ -274,8 +275,9 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
274275
},
275276
Ref => 1,
276277
Slice(slice) => slice.arity(),
277-
Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..)
278-
| Never | NonExhaustive | Hidden | Missing | PrivateUninhabited | Wildcard => 0,
278+
Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..)
279+
| F128Range(..) | Str(..) | Opaque(..) | Never | NonExhaustive | Hidden | Missing
280+
| PrivateUninhabited | Wildcard => 0,
279281
Or => bug!("The `Or` constructor doesn't have a fixed arity"),
280282
}
281283
}
@@ -545,6 +547,18 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
545547
fields = vec![];
546548
arity = 0;
547549
}
550+
ty::Float(ty::FloatTy::F16) => {
551+
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
552+
Some(bits) => {
553+
use rustc_apfloat::Float;
554+
let value = rustc_apfloat::ieee::Half::from_bits(bits);
555+
F16Range(value, value, RangeEnd::Included)
556+
}
557+
None => Opaque(OpaqueId::new()),
558+
};
559+
fields = vec![];
560+
arity = 0;
561+
}
548562
ty::Float(ty::FloatTy::F32) => {
549563
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
550564
Some(bits) => {
@@ -569,6 +583,18 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
569583
fields = vec![];
570584
arity = 0;
571585
}
586+
ty::Float(ty::FloatTy::F128) => {
587+
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
588+
Some(bits) => {
589+
use rustc_apfloat::Float;
590+
let value = rustc_apfloat::ieee::Quad::from_bits(bits);
591+
F128Range(value, value, RangeEnd::Included)
592+
}
593+
None => Opaque(OpaqueId::new()),
594+
};
595+
fields = vec![];
596+
arity = 0;
597+
}
572598
ty::Ref(_, t, _) if t.is_str() => {
573599
// We want a `&str` constant to behave like a `Deref` pattern, to be compatible
574600
// with other `Deref` patterns. This could have been done in `const_to_pat`,
@@ -610,7 +636,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
610636
let lo = lo.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env));
611637
let hi = hi.as_finite().map(|c| c.eval_bits(cx.tcx, cx.param_env));
612638
match fty {
613-
ty::FloatTy::F16 => unimplemented!("f16_f128"),
639+
ty::FloatTy::F16 => {
640+
use rustc_apfloat::ieee::Half;
641+
let lo = lo.map(Half::from_bits).unwrap_or(-Half::INFINITY);
642+
let hi = hi.map(Half::from_bits).unwrap_or(Half::INFINITY);
643+
F16Range(lo, hi, end)
644+
}
614645
ty::FloatTy::F32 => {
615646
use rustc_apfloat::ieee::Single;
616647
let lo = lo.map(Single::from_bits).unwrap_or(-Single::INFINITY);
@@ -623,7 +654,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
623654
let hi = hi.map(Double::from_bits).unwrap_or(Double::INFINITY);
624655
F64Range(lo, hi, end)
625656
}
626-
ty::FloatTy::F128 => unimplemented!("f16_f128"),
657+
ty::FloatTy::F128 => {
658+
use rustc_apfloat::ieee::Quad;
659+
let lo = lo.map(Quad::from_bits).unwrap_or(-Quad::INFINITY);
660+
let hi = hi.map(Quad::from_bits).unwrap_or(Quad::INFINITY);
661+
F128Range(lo, hi, end)
662+
}
627663
}
628664
}
629665
_ => bug!("invalid type for range pattern: {}", ty.inner()),
@@ -836,7 +872,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
836872
"trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
837873
`Missing` should have been processed in `apply_constructors`"
838874
),
839-
F32Range(..) | F64Range(..) | Opaque(..) | Or => {
875+
F16Range(..) | F32Range(..) | F64Range(..) | F128Range(..) | Opaque(..) | Or => {
840876
bug!("can't convert to pattern: {:?}", pat)
841877
}
842878
};

Diff for: tests/ui/match/match-float.rs

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

4-
fn main() {
4+
fn check_f16() {
5+
const F1: f16 = 0.0;
6+
const F2: f16 = -0.0;
7+
assert_eq!(F1, F2);
8+
assert_ne!(F1.to_bits(), F2.to_bits());
9+
assert!(matches!(F1, F2));
10+
assert!(matches!(F2, F1));
11+
}
12+
13+
fn check_f32() {
514
const F1: f32 = 0.0;
615
const F2: f32 = -0.0;
716
assert_eq!(F1, F2);
817
assert_ne!(F1.to_bits(), F2.to_bits());
918
assert!(matches!(F1, F2));
1019
assert!(matches!(F2, F1));
1120
}
21+
22+
fn check_f128() {
23+
const F1: f128 = 0.0;
24+
const F2: f128 = -0.0;
25+
assert_eq!(F1, F2);
26+
assert_ne!(F1.to_bits(), F2.to_bits());
27+
assert!(matches!(F1, F2));
28+
assert!(matches!(F2, F1));
29+
}
30+
31+
fn main() {
32+
check_f16();
33+
check_f32();
34+
check_f128();
35+
}

0 commit comments

Comments
 (0)