Skip to content

Commit bd06902

Browse files
committed
Auto merge of rust-lang#12395 - feniljain:fix_bugs, r=Veykril
fix: f32 and f64 representation during lowering should fix rust-lang#12380
2 parents 145bad4 + 1f4870f commit bd06902

File tree

4 files changed

+132
-10
lines changed

4 files changed

+132
-10
lines changed

crates/hir-def/src/body/lower.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ use crate::{
2929
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
3030
db::DefDatabase,
3131
expr::{
32-
dummy_expr_id, Array, BindingAnnotation, Expr, ExprId, Label, LabelId, Literal, MatchArm,
33-
Pat, PatId, RecordFieldPat, RecordLitField, Statement,
32+
dummy_expr_id, Array, BindingAnnotation, Expr, ExprId, FloatTypeWrapper, Label, LabelId,
33+
Literal, MatchArm, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
3434
},
3535
intern::Interned,
3636
item_scope::BuiltinShadowMode,
@@ -968,7 +968,10 @@ impl From<ast::LiteralKind> for Literal {
968968
// FIXME: these should have actual values filled in, but unsure on perf impact
969969
LiteralKind::IntNumber(lit) => {
970970
if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) {
971-
Literal::Float(Default::default(), builtin)
971+
Literal::Float(
972+
FloatTypeWrapper::new(lit.float_value().unwrap_or(Default::default())),
973+
builtin,
974+
)
972975
} else if let builtin @ Some(_) = lit.suffix().and_then(BuiltinInt::from_suffix) {
973976
Literal::Int(lit.value().unwrap_or(0) as i128, builtin)
974977
} else {
@@ -978,7 +981,7 @@ impl From<ast::LiteralKind> for Literal {
978981
}
979982
LiteralKind::FloatNumber(lit) => {
980983
let ty = lit.suffix().and_then(BuiltinFloat::from_suffix);
981-
Literal::Float(Default::default(), ty)
984+
Literal::Float(FloatTypeWrapper::new(lit.value().unwrap_or(Default::default())), ty)
982985
}
983986
LiteralKind::ByteString(bs) => {
984987
let text = bs.value().map(Box::from).unwrap_or_else(Default::default);

crates/hir-def/src/expr.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,24 @@ pub struct Label {
3838
}
3939
pub type LabelId = Idx<Label>;
4040

41+
// We convert float values into bits and that's how we don't need to deal with f32 and f64.
42+
// For PartialEq, bits comparison should work, as ordering is not important
43+
// https://github.com/rust-lang/rust-analyzer/issues/12380#issuecomment-1137284360
44+
#[derive(Default, Debug, Clone, Eq, PartialEq)]
45+
pub struct FloatTypeWrapper(u64);
46+
47+
impl FloatTypeWrapper {
48+
pub fn new(value: f64) -> Self {
49+
Self(value.to_bits())
50+
}
51+
}
52+
53+
impl std::fmt::Display for FloatTypeWrapper {
54+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55+
write!(f, "{}", f64::from_bits(self.0))
56+
}
57+
}
58+
4159
#[derive(Debug, Clone, Eq, PartialEq)]
4260
pub enum Literal {
4361
String(Box<str>),
@@ -46,7 +64,10 @@ pub enum Literal {
4664
Bool(bool),
4765
Int(i128, Option<BuiltinInt>),
4866
Uint(u128, Option<BuiltinUint>),
49-
Float(u64, Option<BuiltinFloat>), // FIXME: f64 is not Eq
67+
// Here we are using a wrapper around float because f32 and f64 do not implement Eq, so they
68+
// could not be used directly here, to understand how the wrapper works go to definition of
69+
// FloatTypeWrapper
70+
Float(FloatTypeWrapper, Option<BuiltinFloat>),
5071
}
5172

5273
#[derive(Debug, Clone, Eq, PartialEq)]

crates/ide/src/hover/tests.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3595,6 +3595,72 @@ const FOO$0: u8 = b'\x61';
35953595
35963596
---
35973597
3598+
This is a doc
3599+
"#]],
3600+
);
3601+
// show float literal
3602+
check(
3603+
r#"
3604+
/// This is a doc
3605+
const FOO$0: f64 = 1.0234;
3606+
"#,
3607+
expect![[r#"
3608+
*FOO*
3609+
3610+
```rust
3611+
test
3612+
```
3613+
3614+
```rust
3615+
const FOO: f64 = 1.0234
3616+
```
3617+
3618+
---
3619+
3620+
This is a doc
3621+
"#]],
3622+
);
3623+
//show float typecasted from int
3624+
check(
3625+
r#"
3626+
/// This is a doc
3627+
const FOO$0: f32 = 1f32;
3628+
"#,
3629+
expect![[r#"
3630+
*FOO*
3631+
3632+
```rust
3633+
test
3634+
```
3635+
3636+
```rust
3637+
const FOO: f32 = 1
3638+
```
3639+
3640+
---
3641+
3642+
This is a doc
3643+
"#]],
3644+
);
3645+
//show f64 typecasted from float
3646+
check(
3647+
r#"
3648+
/// This is a doc
3649+
const FOO$0: f64 = 1.0f64;
3650+
"#,
3651+
expect![[r#"
3652+
*FOO*
3653+
3654+
```rust
3655+
test
3656+
```
3657+
3658+
```rust
3659+
const FOO: f64 = 1
3660+
```
3661+
3662+
---
3663+
35983664
This is a doc
35993665
"#]],
36003666
);

crates/syntax/src/ast/token_ext.rs

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -319,17 +319,49 @@ impl ast::IntNumber {
319319
Some(suffix)
320320
}
321321
}
322+
323+
pub fn float_value(&self) -> Option<f64> {
324+
let (_, text, _) = self.split_into_parts();
325+
text.parse::<f64>().ok()
326+
}
322327
}
323328

324329
impl ast::FloatNumber {
325-
pub fn suffix(&self) -> Option<&str> {
330+
pub fn split_into_parts(&self) -> (&str, &str) {
326331
let text = self.text();
332+
let mut float_text = self.text();
333+
let mut suffix = "";
327334
let mut indices = text.char_indices();
328-
let (mut suffix_start, c) = indices.by_ref().find(|(_, c)| c.is_ascii_alphabetic())?;
329-
if c == 'e' || c == 'E' {
330-
suffix_start = indices.find(|(_, c)| c.is_ascii_alphabetic())?.0;
335+
if let Some((mut suffix_start, c)) = indices.by_ref().find(|(_, c)| c.is_ascii_alphabetic())
336+
{
337+
if c == 'e' || c == 'E' {
338+
if let Some(suffix_start_tuple) = indices.find(|(_, c)| c.is_ascii_alphabetic()) {
339+
suffix_start = suffix_start_tuple.0;
340+
341+
float_text = &text[..suffix_start];
342+
suffix = &text[suffix_start..];
343+
}
344+
} else {
345+
float_text = &text[..suffix_start];
346+
suffix = &text[suffix_start..];
347+
}
331348
}
332-
Some(&text[suffix_start..])
349+
350+
(float_text, suffix)
351+
}
352+
353+
pub fn suffix(&self) -> Option<&str> {
354+
let (_, suffix) = self.split_into_parts();
355+
if suffix.is_empty() {
356+
None
357+
} else {
358+
Some(suffix)
359+
}
360+
}
361+
362+
pub fn value(&self) -> Option<f64> {
363+
let (text, _) = self.split_into_parts();
364+
text.parse::<f64>().ok()
333365
}
334366
}
335367

0 commit comments

Comments
 (0)