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
11 changed files with 311 additions and 40 deletions
|
@ -182,7 +182,7 @@ use std::iter::once;
|
|||
|
||||
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::IndexVec;
|
||||
|
||||
|
@ -692,8 +692,10 @@ pub enum Constructor<Cx: PatCx> {
|
|||
/// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
|
||||
IntRange(IntRange),
|
||||
/// Ranges of floating-point literal values (`2.0..=5.2`).
|
||||
F16Range(IeeeFloat<HalfS>, IeeeFloat<HalfS>, RangeEnd),
|
||||
F32Range(IeeeFloat<SingleS>, IeeeFloat<SingleS>, 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.
|
||||
Str(Cx::StrLit),
|
||||
/// 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> {
|
|||
Constructor::UnionField => Constructor::UnionField,
|
||||
Constructor::Bool(b) => Constructor::Bool(*b),
|
||||
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::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::Opaque(inner) => Constructor::Opaque(inner.clone()),
|
||||
Constructor::Or => Constructor::Or,
|
||||
|
@ -812,6 +816,14 @@ impl<Cx: PatCx> Constructor<Cx> {
|
|||
(Bool(self_b), Bool(other_b)) => self_b == other_b,
|
||||
|
||||
(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)) => {
|
||||
self_from.ge(other_from)
|
||||
&& match self_to.partial_cmp(other_to) {
|
||||
|
@ -828,6 +840,17 @@ impl<Cx: PatCx> Constructor<Cx> {
|
|||
_ => 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)) => {
|
||||
// FIXME Once valtrees are available we can directly use the bytes
|
||||
// in the `Str` variant of the valtree for the comparison here.
|
||||
|
@ -906,8 +929,10 @@ impl<Cx: PatCx> Constructor<Cx> {
|
|||
Bool(b) => write!(f, "{b}")?,
|
||||
// Best-effort, will render signed ranges incorrectly
|
||||
IntRange(range) => write!(f, "{range:?}")?,
|
||||
F16Range(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}")?,
|
||||
F128Range(lo, hi, end) => write!(f, "{lo}{end}{hi}")?,
|
||||
Str(value) => write!(f, "{value:?}")?,
|
||||
Opaque(..) => write!(f, "<constant pattern>")?,
|
||||
Or => {
|
||||
|
|
|
@ -247,8 +247,9 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||
}
|
||||
_ => bug!("bad slice pattern {:?} {:?}", ctor, ty),
|
||||
},
|
||||
Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..)
|
||||
| Never | NonExhaustive | Hidden | Missing | PrivateUninhabited | Wildcard => &[],
|
||||
Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..)
|
||||
| F128Range(..) | Str(..) | Opaque(..) | Never | NonExhaustive | Hidden | Missing
|
||||
| PrivateUninhabited | Wildcard => &[],
|
||||
Or => {
|
||||
bug!("called `Fields::wildcards` on an `Or` ctor")
|
||||
}
|
||||
|
@ -275,8 +276,9 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||
},
|
||||
Ref => 1,
|
||||
Slice(slice) => slice.arity(),
|
||||
Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..)
|
||||
| Never | NonExhaustive | Hidden | Missing | PrivateUninhabited | Wildcard => 0,
|
||||
Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..)
|
||||
| F128Range(..) | Str(..) | Opaque(..) | Never | NonExhaustive | Hidden | Missing
|
||||
| PrivateUninhabited | Wildcard => 0,
|
||||
Or => bug!("The `Or` constructor doesn't have a fixed arity"),
|
||||
}
|
||||
}
|
||||
|
@ -546,6 +548,18 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||
fields = vec![];
|
||||
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) => {
|
||||
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
|
||||
Some(bits) => {
|
||||
|
@ -570,6 +584,18 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||
fields = vec![];
|
||||
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() => {
|
||||
// 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`,
|
||||
|
@ -611,7 +637,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||
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));
|
||||
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 => {
|
||||
use rustc_apfloat::ieee::Single;
|
||||
let lo = lo.map(Single::from_bits).unwrap_or(-Single::INFINITY);
|
||||
|
@ -624,7 +655,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||
let hi = hi.map(Double::from_bits).unwrap_or(Double::INFINITY);
|
||||
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()),
|
||||
|
@ -837,7 +873,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||
"trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
|
||||
`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)
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue