Skip to content

fix: f32 and f64 representation during lowering #12395

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 27, 2022

Conversation

feniljain
Copy link
Contributor

should fix #12380


#[derive(Default, Debug, Clone, Eq, PartialEq)]
pub struct FloatTypeWrapper {
//We convert float values into bits and that's how we don't need to deal with f32 and f64.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: missing space after // and I'd probably go for a tuple struct (struct FloatEq(u64);), but it doesn't matter too much.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using tuple struct seemed good, fixed the nit too!

Copy link
Contributor Author

@feniljain feniljain May 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also sorry for bringing it up here, tho I am not able to reach Jake ( @~jhgg ) for further review on this PR:
#12347

I try to press the re-request review button, but it doesn't do anything :(

Can you have a look at that PR too? 😅

Comment on lines 323 to 351
pub fn float_value(&self) -> Option<FloatTypeWrapper> {
let (_, text, _) = self.split_into_parts();
let float_value = text.parse::<f64>().ok()?;
Some(FloatTypeWrapper::new(float_value))
}
}

// 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 {
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))
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't go into syntax, let's put this where it is used by hir-def

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shifted it to same file where Literal::Float is defined

Comment on lines 359 to 365
pub fn value(&self) -> Option<FloatTypeWrapper> {
let float_value = self.text().parse::<f64>().ok()?;
Some(FloatTypeWrapper::new(float_value))
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly this should just return the f64

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made changes for the same

@@ -331,6 +355,11 @@ impl ast::FloatNumber {
}
Some(&text[suffix_start..])
}

pub fn value(&self) -> Option<FloatTypeWrapper> {
let float_value = self.text().parse::<f64>().ok()?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will fail when we have things like 1.0f32, we should probably have a split_into_parts akin to ast::IntNumber (minus the prefix part).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's right, implemented the same too!

expect![[r#"
*FOO*

```rust
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be good to move these tests to hir_ty::consteval::tests

Copy link
Contributor Author

@feniljain feniljain May 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So just have one float literal test here and move other cases to consteval?

Edit: Actually should they go in consteval this was a general problem regarding handling of floats, and they are being used in other places too

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So just have one float literal test here and move other cases to consteval?

Yes, that sounds good to me.

Actually should they go in consteval this was a general problem regarding handling of floats

I think it only affects consteval, and current tests just test this, but if there are other problems fixed/affected by this, then adding test for those in addition to consteval tests is good.

@feniljain
Copy link
Contributor Author

feniljain commented May 27, 2022

So, while re-reviewing the PR and understanding more from the review of @HKalbasi , I realized this does not fix consteval for floats completely, it does fix the base case of a simple float value directly assigned. Exactly what current tests show.

But for cases like const FOO: f64 = 2.0 + 3.0, this won't work because that part is errored out currently, you can see that here:

ComputedExpr::Literal(Literal::Int(v, _)) => v,
ComputedExpr::Literal(Literal::Uint(v, _)) => {
v.try_into().map_err(|_| ConstEvalError::NotSupported("too big u128"))?
}
_ => return Err(ConstEvalError::NotSupported("this kind of operator")),

Though it does fix exactly what the title mentions, so to close the issue #12380 completely I would have to add support for float in consteval.rs too. Now that seems to be some work, testing support for it has to be added, then there would be some significant changes in consteval.rs.

I was wondering should I do it in the same PR or separate one?

We can merge the current one for basic support and as a partial fix to #12380 , then the remaning fix can be made in a separate PR

cc: @lnicola @Veykril @HKalbasi

@HKalbasi
Copy link
Member

I think it is fine to not support float operations for now, since hover on const FOO: f64 = 2.0 + 3.0 will show Foo = 2.0 + 3.0 which is not invalid.

@feniljain
Copy link
Contributor Author

I think it is fine to not support float operations for now, since hover on const FOO: f64 = 2.0 + 3.0 will show Foo = 2.0 + 3.0 which is not invalid.

Then ig it makes sense to leave the current tests where they are :)

@Veykril
Copy link
Member

Veykril commented May 27, 2022

Thanks!
@bors r+

@bors
Copy link
Contributor

bors commented May 27, 2022

📌 Commit 1f4870f has been approved by Veykril

@bors
Copy link
Contributor

bors commented May 27, 2022

⌛ Testing commit 1f4870f with merge bd06902...

@bors
Copy link
Contributor

bors commented May 27, 2022

☀️ Test successful - checks-actions
Approved by: Veykril
Pushing bd06902 to master...

@bors bors merged commit bd06902 into rust-lang:master May 27, 2022
@lnicola
Copy link
Member

lnicola commented May 30, 2022

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Hover on floating consts shows zero if their value is positive
5 participants