-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Consider infering floats from integer literals #260
Comments
This would be nice for 1.0 or soon after. It would fix something first time users may easily run into on the rust-lang.org landing page. See rust-lang/rust#23994 for more details. |
Just pointing out that this seems to harmonize with the 2017 goal of "lower learning curve". In languages like C/C++/Java, it works using an integer constant when assigning values to floats. In languages like python,javascript,etc, everything is a "float", and it just works using "whole numbers" without any decimal point notation. This is also a nice ergonomic boost. |
I don't like Rust to infer floats from integer literals. Think about this code that should work with your change:
It's going to print:
Integer literals can't be represented exactly in f32/f64, so if you don't put a ".0" to them you are giving the programmer a false expectation of exactness. Copying the other languages is not an improvement here. |
If someone is not familiar with the accuracy problems of floating point numbers, I don't think sticking a ".0" at the end will make them realize. |
That's why |
@petrochenkov @crumblingstatue In those languages (okay I'm not sure about Java, but in C and C++), it is an integer type (usually |
@leonardo-m In theory the compiler could produce an error in that case (if there is no point). Arguably it should produce a warning even if there is one. |
It would be trivial to add a warning when a loss of information may occur during the implicit cast of a const value. That chain of thought could also lead to small constant positive integers to be implicitly castable as just about any numerical value. In fact, this would be MUCH safer than developers getting into the habit of "as" casting everywhere. |
The wide usage of "as" should be deprecaterd, discouraged, warned-off, and clipped-off. Using .into() and T::from() is the way to go. |
Unfortunately, there are various issues with
|
This is a real pain point. @leonardo-m's point isn't really valid because: a) The compiler can easily warn about these situations - in fact it already does for integers:
b) You can already write a floating point number that can't be exactly represented:
Currently this gives no warning and prints Assuming there was a smart warning like (I say "smart" because you probably don't want a warning about |
I'm not sure how one would check that needless precision was added, but simply checking that every non-zero digit actually affects the stored data is a good starting point. |
I'd be concerned about divisions - if I write |
That's a great point. I think an error here would still make a lot of sense. Allowing the implicit cast of literal constants to float doesn't have to mean allowing implicit casting in the operation or of its result. |
I wouldn't call such a feature "implicit cast" because it would make literals behave as if they had Anyway, I don't think there is a way to disallow |
I think we need some sort of intermediary literal type, that is guaranteed to be castable to a set of types. The literal
1 and 3 are assumed to be ints for the purpose of the operation, and the result of the operation is therefore an int. |
Additionally, if that intermediary type is accessible to the user, we could have very easy to use constants that render most as-casting obsolete. Something like:
Should those types not be compatible, the usual warning would appear, which is not the case with the current:
|
lgarczyn your |
Constants do look quite powerful in go, but it does raise the question of what would be the result of
If 1 is untyped instead of i32, the operation is legal, but only makes sense for an u64. Should rust guess the type of x? Go uses infinite precision in numeric consts, which is well and good, but not exactly rust-like. Unless we add an entirely new, arbitrary-precision, compile-time numeric type. |
On the subject of adding "Go constants" to Rust, see the interrelated and overlapping discussions in: I believe the main points that are relevant here are that:
|
I have been doing a lot of work with numerics recently and it is extremely grating to not have this. I do not think there is anything ambiguous about my intent when I write let x: f64 = 0; I think arbitrary precision literals or constants should be out of scope for this, as they would take a more detailed spec. I think this should be added as a standalone feature. We should add warnings for floating point literals that don't fit into their inferred type. Nothing we do with regards to this should conflict with eventually adding arbitrary precisions literals and constants as both features would probably need an edition change. I have never written a Rust RFC before, would it be acceptable for me to write one for this? |
The idea of accepting
is far too dangerous. The reason is simple:
|
I am personally fine with disallowing any ambiguous case. My main desire is that if an integer literal is put in a context where it would immediately be used as a floating point then it should be inferred as a floating point. In other words, assignment, |
That'd require some careful error message design work so the compiler can recognize your intent and reject the more complex cases with a message explaining that the complex cases are rejected because they're footguns. Otherwise, you'll be frustrating and confusing people when there's int→float inference in some places but not others. Granted, that sort of thing is not unheard-of, given that's how Rust's error messages about needing explicit type annotations work, but it is a potential "much more difficult to implement acceptably than it looks". (Specifically, the distinction between when to report a type mismatch and when to report "I refuse to infer that here because it could lead to ambiguous results" in the general case.) |
cc #183
The text was updated successfully, but these errors were encountered: