Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/hir.rs')
-rw-r--r--crates/hir-def/src/hir.rs41
1 files changed, 24 insertions, 17 deletions
diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs
index fd6f4a3d08..d306f9be65 100644
--- a/crates/hir-def/src/hir.rs
+++ b/crates/hir-def/src/hir.rs
@@ -20,6 +20,7 @@ use std::fmt;
use hir_expand::name::Name;
use intern::Interned;
use la_arena::{Idx, RawIdx};
+use rustc_apfloat::ieee::{Half as f16, Quad as f128};
use smallvec::SmallVec;
use syntax::ast;
@@ -56,29 +57,38 @@ pub struct Label {
}
pub type LabelId = Idx<Label>;
-// We convert float values into bits and that's how we don't need to deal with f32 and f64.
-// For PartialEq, bits comparison should work, as ordering is not important
+// We leave float values as a string to avoid double rounding.
+// For PartialEq, string comparison should work, as ordering is not important
// https://github.com/rust-lang/rust-analyzer/issues/12380#issuecomment-1137284360
-#[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
-pub struct FloatTypeWrapper(u64);
+#[derive(Default, Debug, Clone, Eq, PartialEq)]
+pub struct FloatTypeWrapper(Box<str>);
+// FIXME(#17451): Use builtin types once stabilised.
impl FloatTypeWrapper {
- pub fn new(value: f64) -> Self {
- Self(value.to_bits())
+ pub fn new(value: String) -> Self {
+ Self(value.into())
}
- pub fn into_f64(self) -> f64 {
- f64::from_bits(self.0)
+ pub fn to_f128(&self) -> f128 {
+ self.0.parse().unwrap_or_default()
}
- pub fn into_f32(self) -> f32 {
- f64::from_bits(self.0) as f32
+ pub fn to_f64(&self) -> f64 {
+ self.0.parse().unwrap_or_default()
+ }
+
+ pub fn to_f32(&self) -> f32 {
+ self.0.parse().unwrap_or_default()
+ }
+
+ pub fn to_f16(&self) -> f16 {
+ self.0.parse().unwrap_or_default()
}
}
impl fmt::Display for FloatTypeWrapper {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{:?}", f64::from_bits(self.0))
+ f.write_str(&self.0)
}
}
@@ -91,7 +101,7 @@ pub enum Literal {
Bool(bool),
Int(i128, Option<BuiltinInt>),
Uint(u128, Option<BuiltinUint>),
- // Here we are using a wrapper around float because f32 and f64 do not implement Eq, so they
+ // Here we are using a wrapper around float because float primitives do not implement Eq, so they
// could not be used directly here, to understand how the wrapper works go to definition of
// FloatTypeWrapper
Float(FloatTypeWrapper, Option<BuiltinFloat>),
@@ -120,10 +130,7 @@ impl From<ast::LiteralKind> for Literal {
match ast_lit_kind {
LiteralKind::IntNumber(lit) => {
if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) {
- Literal::Float(
- FloatTypeWrapper::new(lit.float_value().unwrap_or(Default::default())),
- builtin,
- )
+ Literal::Float(FloatTypeWrapper::new(lit.value_string()), builtin)
} else if let builtin @ Some(_) = lit.suffix().and_then(BuiltinUint::from_suffix) {
Literal::Uint(lit.value().unwrap_or(0), builtin)
} else {
@@ -133,7 +140,7 @@ impl From<ast::LiteralKind> for Literal {
}
LiteralKind::FloatNumber(lit) => {
let ty = lit.suffix().and_then(BuiltinFloat::from_suffix);
- Literal::Float(FloatTypeWrapper::new(lit.value().unwrap_or(Default::default())), ty)
+ Literal::Float(FloatTypeWrapper::new(lit.value_string()), ty)
}
LiteralKind::ByteString(bs) => {
let text = bs.value().map_or_else(|_| Default::default(), Box::from);