diff options
| author | feniljain <fkjainco@gmail.com> | 2022-05-26 16:05:25 +0530 |
|---|---|---|
| committer | feniljain <fkjainco@gmail.com> | 2022-05-26 20:03:05 +0530 |
| commit | 1f4870ff1c8e2c2a5d4a0d73fc2b1c196b395f3e (patch) | |
| tree | 17e14ba80cba0fe6a1f1edc4edcba454f7a7e0ad | |
| parent | d7c147406eff20783abba6ff1fe250ecc44cf800 (diff) | |
| download | rust-1f4870ff1c8e2c2a5d4a0d73fc2b1c196b395f3e.tar.gz rust-1f4870ff1c8e2c2a5d4a0d73fc2b1c196b395f3e.zip | |
fix: f32 and f64 representation during lowering
| -rw-r--r-- | crates/hir-def/src/body/lower.rs | 11 | ||||
| -rw-r--r-- | crates/hir-def/src/expr.rs | 23 | ||||
| -rw-r--r-- | crates/ide/src/hover/tests.rs | 66 | ||||
| -rw-r--r-- | crates/syntax/src/ast/token_ext.rs | 42 |
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() } } |
