-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Emit warning when using as
to directly cast function items to any integral type other than usize
#81686
Comments
What would be the "lint group" of this lint? Currently we have: "nonstandard_style", "unused", "rust_2018_idioms", "rustdoc". This one doesn't fit into any of these, I think. Should this be a clippy lint maybe? |
as
to directly cast function pointers to any integral type other than usizeas
to directly cast function items to any integral type other than usize
@osa1 , allow me to expand on my reasoning as to why I believe this should be in the compiler, rather than clippy. Ultimately I believe this to be a flaw in the specification of the type cast operator,
It is my opinion that the presence of "Integer type" in all of these "address"-related casts is an error in the language; all instances of "Integer type" should be replaced by " That said, this would be considered a breaking change if it were to simply be implemented. The only backwards-compatible way of moving forward here is as follows:
This issue is intended to gauge the willingness of the lang team to make such a change. If people are receptive, I would be willing to close this issue in favor of writing a full RFC for the broader change. The specific example chosen is deliberately horrific; no Rust expert that I have yet shown it to has immediately understood what's happening (excerpted responses from said Rust experts: "OH", "oof", "AH", "oh wow", "oh goddddd"). If the problem were just " |
Typo originally reported in the compiler issue tracker: rust-lang/rust#81686 (comment) It doesn't make sense to cast a pointer to a float, and it's currently rejected by the compiler: error[E0606]: casting `*const T` as `f32` is invalid --> test.rs:2:5 | 2 | a as f32 | ^^^^^^^^ error: aborting due to previous error I think what's meant here is "integer type" rather than "numeric type".
OK so the long-term goal you have in mind is to restrict pointer to integer casts to usizes. In that case I agree that this check should be in the compiler. I already implemented the lint. I wasn't sure how to "register" it, but I just realized that we also have built-in lints (like (If anyone could assign this to me that would be helpful) Regarding disallowing pointer to u32 etc. casts I guess we need to get feedback from the lang team first. Should we mark this as "I-nominated"? Even if the lang team decides that the change is not desirable perhaps we can still have a warning in the compiler when casting a pointer to a type other than |
The long-term goal should be to nearly deprecate the usage of naked "as" and use it only for special situations. And use u32::from (here u32::from avoids this problem), try_from, and other future safer conversion functions (like a standard function/macro that performs a range test in debug builds and works like as in release builds). |
I agree that there seems to be a vague and unspoken movement that |
This makes good sense to me. I can't imagine any situation in which casting a function to an (I might even be tempted to go further and require going through And to add to the fun, this also happens with let y = u16::max_value as u32; which is a whole different kind of typo. |
And yes, I considered a proposal to ban both function item and function pointer to address casts, although your suggestion of only banning the function item cast sounds both less disruptive and totally sufficient for preventing confusion. Though even if that were done I would still propose limiting the remaining address casts to usize. |
New lint `invalid_ptr_to_int_cast` detects pointer (or function) to integer casts when the integer is not usize (or u64), and suggests going through usize, e.g. `x as usize as u32`. See rust-lang#81686 for motivation. Closes rust-lang#81686
Here's another really bad case: One of the allowed enum Foo {
A,
B
}
Foo::A as i32; // works Now, what happens when we add data to enum Foo {
A(String),
B
}
Foo::A as i32; // uh oh! This still compiles! The compiler is supposed to produce a non-primitive cast error (and it would have if we had done |
In addition to a good case for a lint on its own, sounds like another good reason to have an (Then we could start suggesting that instead of the |
Now that Rust supports explicit discriminants in data-carrying enums in 1.66, this problem is even more acute and easier to stumble into than ever (even the 1.66 release announcement for this feature made it easy for users to stumble into this footgun, see rust-lang/blog.rust-lang.org#1056 ). |
Clippy has a lint for this, which we could uplift to rustc: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_with_truncation |
Note that there's currently an RFC to forbid these casts entirely in the next edition: rust-lang/rfcs#3526 |
Imagine you have a
u32
. You want to check if it's larger than the maximum value of au16
. Of course, you know that the API will give you au16
, so you will need to cast it to au32
.You write a unit test. 100 million should be above the range of a
u16
, you think.Output:
You begin to doubt your computer science education. In a fugue, you abandon all worldly possessions. You move to the woods. You raise chickens now; sometimes, though, you wonder if they're truly the ones raising you. It is a simpler life.
u16::max
is the UFCS'd form of the default'dmax
method on the prelude'dOrd
trait. To a first approximation, there is no reason to ever directly cast a function item to anything other than ausize
. The compiler should emit a warning when attempting to cast a function item tou8
,u16
,u32
,u64
,u128
,i8
,i16
,i32
,i64
,i128
, andisize
. This would not apply to transitive casts;foo as usize as i8
would not warn.(If I had realized this existed, I would have renamed
u16::MAX
back when I had the chance.)The text was updated successfully, but these errors were encountered: