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},
|
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
expr::{
|
expr::{
|
||||||
dummy_expr_id, Array, BindingAnnotation, Expr, ExprId, Label, LabelId, Literal, MatchArm,
|
dummy_expr_id, Array, BindingAnnotation, Expr, ExprId, FloatTypeWrapper, Label, LabelId,
|
||||||
Pat, PatId, RecordFieldPat, RecordLitField, Statement,
|
Literal, MatchArm, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
|
||||||
},
|
},
|
||||||
intern::Interned,
|
intern::Interned,
|
||||||
item_scope::BuiltinShadowMode,
|
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
|
// FIXME: these should have actual values filled in, but unsure on perf impact
|
||||||
LiteralKind::IntNumber(lit) => {
|
LiteralKind::IntNumber(lit) => {
|
||||||
if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) {
|
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) {
|
} else if let builtin @ Some(_) = lit.suffix().and_then(BuiltinInt::from_suffix) {
|
||||||
Literal::Int(lit.value().unwrap_or(0) as i128, builtin)
|
Literal::Int(lit.value().unwrap_or(0) as i128, builtin)
|
||||||
} else {
|
} else {
|
||||||
@ -978,7 +981,7 @@ fn from(ast_lit_kind: ast::LiteralKind) -> Self {
|
|||||||
}
|
}
|
||||||
LiteralKind::FloatNumber(lit) => {
|
LiteralKind::FloatNumber(lit) => {
|
||||||
let ty = lit.suffix().and_then(BuiltinFloat::from_suffix);
|
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) => {
|
LiteralKind::ByteString(bs) => {
|
||||||
let text = bs.value().map(Box::from).unwrap_or_else(Default::default);
|
let text = bs.value().map(Box::from).unwrap_or_else(Default::default);
|
||||||
|
@ -38,6 +38,24 @@ pub struct Label {
|
|||||||
}
|
}
|
||||||
pub type LabelId = Idx<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)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub enum Literal {
|
pub enum Literal {
|
||||||
String(Box<str>),
|
String(Box<str>),
|
||||||
@ -46,7 +64,10 @@ pub enum Literal {
|
|||||||
Bool(bool),
|
Bool(bool),
|
||||||
Int(i128, Option<BuiltinInt>),
|
Int(i128, Option<BuiltinInt>),
|
||||||
Uint(u128, Option<BuiltinUint>),
|
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)]
|
#[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
|
This is a doc
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
@ -319,17 +319,49 @@ pub fn suffix(&self) -> Option<&str> {
|
|||||||
Some(suffix)
|
Some(suffix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn float_value(&self) -> Option<f64> {
|
||||||
|
let (_, text, _) = self.split_into_parts();
|
||||||
|
text.parse::<f64>().ok()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ast::FloatNumber {
|
impl ast::FloatNumber {
|
||||||
pub fn suffix(&self) -> Option<&str> {
|
pub fn split_into_parts(&self) -> (&str, &str) {
|
||||||
let text = self.text();
|
let text = self.text();
|
||||||
|
let mut float_text = self.text();
|
||||||
|
let mut suffix = "";
|
||||||
let mut indices = text.char_indices();
|
let mut indices = text.char_indices();
|
||||||
let (mut suffix_start, c) = indices.by_ref().find(|(_, c)| c.is_ascii_alphabetic())?;
|
if let Some((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 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