Skip to content

Change type deduction rules to allow integer literals to be deduced as floats. #183

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

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions active/0000-make-integer-literals-coerce-to-floats.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
- Start Date: 2014-07-23
- RFC PR #: (leave this empty)
- Rust Issue #: (leave this empty)

# Summary

Currently, numeric literals like "1" can become either signed or unsigned integers of any time, depending on how they're used. For example, in `let x = 3; let y = x + 1u32;`, `x` is deduced to have type `u32`. However, replacing `1u32` with `1f32` leads to a compile error unless `3` is replaced with `3.`. `3` is a perfectly valid floating point number, so it should be able to be a floating point number under type deduction without any explicit suffixes.

# Motivation

Having unnecessary type annotations adds noise to code and makes it harder to follow. Rust's type deduction mechanism greatly reduces the number of type annotations needed for a program, but there are still some spots where it is overly conservative.

# Detailed design

In the current compiler, any integer literal without specific type annotation is deduced to have type "generic integer", which is then narrowed as required by its interaction with parts of the program that do have their types defined, such as function parameters and variables that do have explicit types. It can be deduced to be any of `i8, i16, i32, i64, int, u8, u16, u32, u64, uint`.

This RFC propses adding `f32` and `f64` to that list. The "generic integer" will be renamed "generic number", and it will have its type determined by the rest of its interactions, as it is now. The difference is that when an operation like `+ 3.0` or `cos` is applied to it, its type will be narrowed to "generic float" instead of having the compiler give an error.

The compiler will still warn when a literal is assigned to a type that cannot exactly represent that value, the same way that it does on `let x: u8 = 256;`.

This RFC does not propose allowing generic floats to coerce into integers. Adding the decimal point is an explicit annotation that the number is not intended to be integral.

# Drawbacks

Increased complexity in the type deduction system.

People who expect unsuffixed integer literals to always be integers will be confused.

# Alternatives

Leaving it as it is.

# Unresolved questions

Should a literal still be coerced without warning if it's too big for any float to exactly equal it? For example, `2^60 + 1` cannot be exactly represented as a `f32` or `f64`, but unlike `1000u8` it does have a very close approximation.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think not. 2e60 is a valid floating-point literal with an f64 value of 2000000000000000000000064884426862042680048006680208002800648, but it doesn't produce a warning.


Should a literal that is very large be coerced without warning if it does happen to have an exact float representation? For example, `2^60` does have an exact `f32` representation, but `2^60 + 1` and `2^60 - 1` do not.
Copy link
Contributor

Choose a reason for hiding this comment

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

Even if we added a warning on the no-exact-representation case, why would we have a warning when there is an exact representation?

Choose a reason for hiding this comment

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

Because +1 and -1 will not work as expected if you had actually wanted it to be an integer?