fix: f32 and f64 representation during lowering
This commit is contained in:
parent
d7c147406e
commit
1f4870ff1c
@ -29,8 +29,8 @@
|
||||
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 @@ fn from(ast_lit_kind: ast::LiteralKind) -> Self {
|
||||
// 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 @@ fn from(ast_lit_kind: ast::LiteralKind) -> Self {
|
||||
}
|
||||
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);
|
||||
|
@ -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)]
|
||||
|
@ -3595,6 +3595,72 @@ fn hover_const_eval() {
|
||||
|
||||
---
|
||||
|
||||
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
|
||||
"#]],
|
||||
);
|
||||
|
@ -319,17 +319,49 @@ pub fn suffix(&self) -> Option<&str> {
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user