Skip to content

Conversation

@fruno-bulax
Copy link
Contributor

@fruno-bulax fruno-bulax commented Oct 1, 2025

Closes #5001

Parallel to the implementation for ints, we're now parsing the literal value and passing it along the AST.
This allows us to do smarter useless comparison warnings instead of relying on string comparison.

To maintain the Eq trait impl on many types, I created a NotNan type to wrap f64 that be NaN and can therefore properly implement Eq and Ord. I wasn't quite sure where to put the type, I'll gladly move it.

I noticed that we still do string-based checks in clauses for both ints and floats, I'll create a follow-up issue after this is merged.

Copy link
Member

@giacomocavalieri giacomocavalieri left a comment

Choose a reason for hiding this comment

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

This is great, well done!! I left just a tiny nit inline

Comment on lines 37 to 39
float_value: NotNan(
1.0,
),
Copy link
Member

Choose a reason for hiding this comment

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

Isn't this the ONE constant you defined earlier?

Suggested change
float_value: NotNan(
1.0,
),
float_value: NotNan::ONE,

Copy link
Contributor Author

@fruno-bulax fruno-bulax Oct 2, 2025

Choose a reason for hiding this comment

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

This is the snapshot of the parser test, not rust code! 🕵️

Copy link
Member

Choose a reason for hiding this comment

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

Oh my, sorry for that, I totally missed the context 😆

Comment on lines +12 to +13
1pub fn main() { 1_0.0 == 10.0 }
^^^^^^^^^^^^^ This is always `True`
Copy link
Member

Choose a reason for hiding this comment

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

Really nice!!

/// A thin f64 wrapper that does not permit NaN.
/// This allows us to implement `Eq`, which require reflexivity.
///
/// Used for gleam float literals. May contain infinity.
Copy link
Member

Choose a reason for hiding this comment

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

If this is used for Gleam float literals it shouldn't contain infinity as well, should it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is true for the Erlang target (and there is a compile time check for it), but on JS you can enter float literals that are too large (e.g. 1.0e500) and they turn into (negative) infinity.

Copy link
Member

Choose a reason for hiding this comment

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

Aha, now I see, thanks for explaining! Would you mind adding this explanation to the comment? That would be really helpful for future people wondering the same thing

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point, done!

@fruno-bulax fruno-bulax force-pushed the parse-floats branch 2 times, most recently from 6fa1918 to 573bd5d Compare October 7, 2025 20:30
Copy link
Member

@lpil lpil left a comment

Choose a reason for hiding this comment

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

Fab work! This is really nice!

I've left some small notes inline 🙏

/// While there is no syntax for "infinity", float literals
/// may overflow into (possibly negative) infinity on the JS target.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct NotNan(f64);
Copy link
Member

Choose a reason for hiding this comment

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

This is a rather confusing name to see in the codebase. Can we call it something like FloatValue or LiteralFloatValue instead 🙏

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Naming, my eternal nemesis. I went for LiteralFloatValue, since that more narrowly describes what it is.

CHANGELOG.md Outdated
- Patterns aliasing a string prefix have been optimised to generate faster code
on the Erlang target.
([Giacomo Cavalieri](https://github.com/giacomocavalieri))
- Useless comparison warnings for floats now consider the parsed value.
Copy link
Member

Choose a reason for hiding this comment

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

Space between changelog entries please

This entry describes the compiler internals, but it doesn't tell the Gleam programmer what has changed from their point of view, which is what this document is for. Could we have that here please 🙏

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reworded and moved to bug fixes where it actually belongs!

#[test]
fn float_literals_redundant_comparison_signed_zero() {
assert_warning!("pub fn main() { 0.0 == -0.0 }");
}
Copy link
Member

Choose a reason for hiding this comment

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

Can we have test for floats like 10. please

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added!

@fruno-bulax fruno-bulax force-pushed the parse-floats branch 2 times, most recently from a69fd1c to e1e23f0 Compare October 22, 2025 15:51
Copy link
Member

@lpil lpil left a comment

Choose a reason for hiding this comment

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

Thank you!!! Really nice work

@lpil lpil merged commit b373611 into gleam-lang:main Oct 30, 2025
12 checks passed
ptdewey added a commit to ptdewey/gleam that referenced this pull request Nov 7, 2025
Exhaustiveness checks now correctly account for underscores in
ints/floats. Float checks also now used parsed float values defined in
PR gleam-lang#5030.
ptdewey added a commit to ptdewey/gleam that referenced this pull request Nov 7, 2025
Exhaustiveness checks now correctly account for underscores in
ints/floats. Float checks also now used parsed float values defined in
PR gleam-lang#5030.
ptdewey added a commit to ptdewey/gleam that referenced this pull request Nov 7, 2025
Exhaustiveness checks now correctly account for underscores in
ints/floats. Float checks also now used parsed float values defined in
PR gleam-lang#5030.
@fruno-bulax fruno-bulax deleted the parse-floats branch November 22, 2025 14:58
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.

Incorrect warn on useless comparisons

3 participants