about summary refs log tree commit diff
diff options
context:
space:
mode:
authorfeniljain <fkjainco@gmail.com>2022-05-26 16:05:25 +0530
committerfeniljain <fkjainco@gmail.com>2022-05-26 20:03:05 +0530
commit1f4870ff1c8e2c2a5d4a0d73fc2b1c196b395f3e (patch)
tree17e14ba80cba0fe6a1f1edc4edcba454f7a7e0ad
parentd7c147406eff20783abba6ff1fe250ecc44cf800 (diff)
downloadrust-1f4870ff1c8e2c2a5d4a0d73fc2b1c196b395f3e.tar.gz
rust-1f4870ff1c8e2c2a5d4a0d73fc2b1c196b395f3e.zip
fix: f32 and f64 representation during lowering
-rw-r--r--crates/hir-def/src/body/lower.rs11
-rw-r--r--crates/hir-def/src/expr.rs23
-rw-r--r--crates/ide/src/hover/tests.rs66
-rw-r--r--crates/syntax/src/ast/token_ext.rs42
4 files changed, 132 insertions, 10 deletions
diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs
index 0f9f0e0e1c5..5d7a1100cd5 100644
--- a/crates/hir-def/src/body/lower.rs
+++ b/crates/hir-def/src/body/lower.rs
@@ -29,8 +29,8 @@ use crate::{
     builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
     db::DefDatabase,
     expr::{
-        dummy_expr_id, Array, BindingAnnotation, Expr, ExprId, Label, LabelId, Literal, MatchArm,
-        Pat, PatId, RecordFieldPat, RecordLitField, Statement,
+        dummy_expr_id, Array, BindingAnnotation, Expr, ExprId, FloatTypeWrapper, Label, LabelId,
+        Literal, MatchArm, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
     },
     intern::Interned,
     item_scope::BuiltinShadowMode,
@@ -968,7 +968,10 @@ impl From<ast::LiteralKind> for Literal {
             // FIXME: these should have actual values filled in, but unsure on perf impact
             LiteralKind::IntNumber(lit) => {
                 if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) {
-                    Literal::Float(Default::default(), builtin)
+                    Literal::Float(
+                        FloatTypeWrapper::new(lit.float_value().unwrap_or(Default::default())),
+                        builtin,
+                    )
                 } else if let builtin @ Some(_) = lit.suffix().and_then(BuiltinInt::from_suffix) {
                     Literal::Int(lit.value().unwrap_or(0) as i128, builtin)
                 } else {
@@ -978,7 +981,7 @@ impl From<ast::LiteralKind> for Literal {
             }
             LiteralKind::FloatNumber(lit) => {
                 let ty = lit.suffix().and_then(BuiltinFloat::from_suffix);
-                Literal::Float(Default::default(), ty)
+                Literal::Float(FloatTypeWrapper::new(lit.value().unwrap_or(Default::default())), ty)
             }
             LiteralKind::ByteString(bs) => {
                 let text = bs.value().map(Box::from).unwrap_or_else(Default::default);
diff --git a/crates/hir-def/src/expr.rs b/crates/hir-def/src/expr.rs
index fd09e651c99..97681abab1f 100644
--- a/crates/hir-def/src/expr.rs
+++ b/crates/hir-def/src/expr.rs
@@ -38,6 +38,24 @@ 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
+// https://github.com/rust-lang/rust-analyzer/issues/12380#issuecomment-1137284360
+#[derive(Default, Debug, Clone, Eq, PartialEq)]
+pub struct FloatTypeWrapper(u64);
+
+impl FloatTypeWrapper {
+    pub fn new(value: f64) -> Self {
+        Self(value.to_bits())
+    }
+}
+
+impl std::fmt::Display for FloatTypeWrapper {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}", f64::from_bits(self.0))
+    }
+}
+
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub enum Literal {
     String(Box<str>),
@@ -46,7 +64,10 @@ pub enum Literal {
     Bool(bool),
     Int(i128, Option<BuiltinInt>),
     Uint(u128, Option<BuiltinUint>),
-    Float(u64, Option<BuiltinFloat>), // FIXME: f64 is not Eq
+    // Here we are using a wrapper around float because f32 and f64 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>),
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index 5d084ac955b..07f224da66c 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -3598,6 +3598,72 @@ const FOO$0: u8 = b'\x61';
             This is a doc
         "#]],
     );
+    // show float literal
+    check(
+        r#"
+    /// This is a doc
+    const FOO$0: f64 = 1.0234;
+    "#,
+        expect![[r#"
+            *FOO*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            const FOO: f64 = 1.0234
+            ```
+
+            ---
+
+            This is a doc
+        "#]],
+    );
+    //show float typecasted from int
+    check(
+        r#"
+/// This is a doc
+const FOO$0: f32 = 1f32;
+"#,
+        expect![[r#"
+            *FOO*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            const FOO: f32 = 1
+            ```
+
+            ---
+
+            This is a doc
+        "#]],
+    );
+    //show f64 typecasted from float
+    check(
+        r#"
+/// This is a doc
+const FOO$0: f64 = 1.0f64;
+"#,
+        expect![[r#"
+            *FOO*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            const FOO: f64 = 1
+            ```
+
+            ---
+
+            This is a doc
+        "#]],
+    );
 }
 
 #[test]
diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs
index 4b6dc236b53..28976d837b8 100644
--- a/crates/syntax/src/ast/token_ext.rs
+++ b/crates/syntax/src/ast/token_ext.rs
@@ -319,17 +319,49 @@ impl ast::IntNumber {
             Some(suffix)
         }
     }
+
+    pub fn float_value(&self) -> Option<f64> {
+        let (_, text, _) = self.split_into_parts();
+        text.parse::<f64>().ok()
+    }
 }
 
 impl ast::FloatNumber {
-    pub fn suffix(&self) -> Option<&str> {
+    pub fn split_into_parts(&self) -> (&str, &str) {
         let text = self.text();
+        let mut float_text = self.text();
+        let mut suffix = "";
         let mut indices = text.char_indices();
-        let (mut suffix_start, c) = indices.by_ref().find(|(_, c)| c.is_ascii_alphabetic())?;
-        if c == 'e' || c == 'E' {
-            suffix_start = indices.find(|(_, c)| c.is_ascii_alphabetic())?.0;
+        if let Some((mut suffix_start, c)) = indices.by_ref().find(|(_, c)| c.is_ascii_alphabetic())
+        {
+            if c == 'e' || c == 'E' {
+                if let Some(suffix_start_tuple) = indices.find(|(_, c)| c.is_ascii_alphabetic()) {
+                    suffix_start = suffix_start_tuple.0;
+
+                    float_text = &text[..suffix_start];
+                    suffix = &text[suffix_start..];
+                }
+            } else {
+                float_text = &text[..suffix_start];
+                suffix = &text[suffix_start..];
+            }
         }
-        Some(&text[suffix_start..])
+
+        (float_text, suffix)
+    }
+
+    pub fn suffix(&self) -> Option<&str> {
+        let (_, suffix) = self.split_into_parts();
+        if suffix.is_empty() {
+            None
+        } else {
+            Some(suffix)
+        }
+    }
+
+    pub fn value(&self) -> Option<f64> {
+        let (text, _) = self.split_into_parts();
+        text.parse::<f64>().ok()
     }
 }