-
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
Deny the overflowing_literals
lint for the 2018 edition
#2438
Conversation
💯 Honestly I'd prefer to do it in Rust 2015 as well... |
I don't see any reason to wait for the 2018 edition. I wonder if we could even make it a hard error in the 2018 edition. One issue is that the |
I've used something like |
@ollie27 , good point about floats. On the one hand, since the behavior with floats is just "clamp to On the other hand, I don't know if that alone is a good rationale for allowing too-large float literals. Consider our usual guideline for any behavioral change: if we didn't have the current behavior, would we want to transition to the current behavior? In other words, if we already rejected too-large float literals, would we want to start accepting them? Personally, I believe the answer is no.[1] Of course the prior argument has to take potential breakage into account, and it's true that it's technically more likely that one would encounter a too-large float literal in the wild compared to an overflowing integer literal. However, my instinct is that this would still lead to no breakage in practice, since the upper bound of So on balance, I think I'm content with catching too-large floating point literals in the same net. That said I'll edit the RFC to note this behavior, and also add a paragraph to the section on alternatives. [1] Off-topic, but personally I think float literals, in every programming language, are too loosey-goosey already; if I had my way, we'd be writing all float literals as explicit significand/exponent pairs and rejecting any float literals that didn't precisely map to exact representations. But I digress. :P |
@bluetech , what use case is that where people might want to be doing bit-twiddling on signed integers? Note that, for people who didn't want to use |
Off-topic reply: I could get behind a clippy lint for this. |
This would also prevent subtle bugs like fn foo(x: u8) { }
fn main() {
for x in 0 .. 256 {
foo(x);
}
} |
Noticing that @ollie27 mentioned that this could be a hard error rather than merely a deny-by-default lint; I'm not sure if we're allowed to do that according to the rules of the edition, but I'd be all for it. I've added this to the section on alternatives, feedback appreciated! |
@bstrie I think a hard error is a good idea. |
I don't think this is serious enough that it needs to be a hard error. It's not UB, it doesn't block typeck or borrowck, it doesn't cause knock-on errors elsewhere, etc. It's almost certainly wrong, so I'm a big fan of deny-by-default, but Rust seems to be moving away from hard errors where feasible (like #2086). |
C, surprisingly enough, has well defined unsigned integer overflow, which is used quite frequently in constant definitions, such as in the Windows SDK. The fact that I can't directly port those definitions over to Rust is kinda ridiculous. Something as simple as I really wish Rust hadn't taken this stance on overflowing integers. |
@retep998 I have to disagree there. To me, using underflow/overflow to define constants feels like grandfathering a footgun into safe Rust purely because it's a popular idiom in legacy code. I'd only be in favour if one of the following were the case:
|
It's in fact "MAX", not "MAX - 1". And that's what the constant should use, IMHO: const FOO : u32 = std::u32::MAX; |
I'm all for putting this into Rust 2018 and leaving Rust 2015's behavior untouched: Rust's commitment to stability should be taken seriously. This is just a footgun, not a safety critical bug. Shipping this as part of Rust 2018 is the right way to do it. |
@ssokolow Using @retep998 , if you're doing that then your code already contains |
@MajorBreakfast I think the suggestions that this be turned on today are mostly tongue-in-cheek; not only would it be rather controversial in the face of our backwards-compatibility guarantee, it would be mostly moot given that Rust 2018 is only a few months away anyway. :) It won't be added as an alternative to the RFC. |
Ugh. Last night was not a good night for me saying correct things. I should know that. I've used (That said, I suppose it demonstrates one way the footgun could fire if the programmer is tired or distracted.) |
@bstrie I figured that. But, stability is very important. Therefore, I had to write that comment, so that it can remain a just joke :) |
IMHO this is 100% hack, even in C. The correct way to do this IMHO should be either |
It may be a hack but it's an extremely widely used hack. The workaround of |
That surprises me. What are such values used for? |
@bstrie The thing forbidding negative unsigned constants is not this lint, but actually a hard error For example, how would I write these constants if I couldn't have overflowing literals? |
@rpjohnst if this is a concern for code generation via bindgen then bindgen can choose to insert @retep998 , given that the RFC as written would allow the lint to be turned off, I think I'm unclear on what your objection is? You're already using the allow attribute, so you wouldn't notice if this were turned on tomorrow. |
@rfcbot concern extern-C-code I have mixed feelings on various axes. First, I think that using this for "extern bindings" is a very legitimate use case -- as evidence by e.g. @retep998's comments etc. I am concerned that people who are attempting to do this may not realize they can -- and in fact are encouraged to! -- This is part of why I've been reluctant to have deny-by-default lints at all. Ultimately it's probably silly to deny ourselves of the option, but it does feel like it just makes the range of diagnostic settings we offer that much more complex. Perhaps what is missing for me is a good guideline of what makes something a deny-by-default lint: I guess it is "this is almost certainly a bug -- but there are a few legitimate reasons that are quite uncommon"? (This overlaps of course with #2476... traditionally rustc has been warn-by-default for lints whereas clippy has been deny-by-default for some categories...) I wonder if some kind of tailored hint might resolve my first concern. e.g., adding to the lint something like, "If you are intentionally trying to achieve overflow behavior, then feel free to 'allow' the lint and leave a comment" or something like that? Either in the main lint error or perhaps the diagnostics "explain" text for the lint? (Probably we should have made As for the second concern, about wanting stricter guidelines, I don't think we'll decide them here, so that's ok, but I'd like to at some point write them down. |
So, yes, to pull out my concern: I think we should include some text in the lint (possibly in a Presumably nobody will object to including such text, but I'd like it included in the RFC to help ensure it's not forgotten. |
FWIW, before today I was honestly under the impression that deny-by-default lints existed only because we allow users to deny lints and lints have a default status, so the possibility just sort of exists on its own unless we actively prevent it from existing, and we've only started hearing about it recently because it turned out to be ideal for "this would be a hard error if we had a time machine" lints. Several warn-by-default lints already arguably meet "this is almost certainly a bug", so maybe the non-time machine criterion is more like "the cases where you want this are so rare or so domain-specific you should explicitly annotate them with an |
Much of this discussion has been about So, the only code that currently compiles that would make the lint fire is things like |
My test: Is this something that's going to make what I'm trying right now not work? An unused function isn't going to keep another function from working. Extra parens aren't going to keep something from working. An unused Also, #2484 would add |
Are there any other lints going from warn to deny by default in edition 2018? It just seems like an unnecessary complication for the default lint level to differ based on edition here. |
I was hoping we'd do this for rust-lang/rust#49441, but I am not sure if that will actually happen. |
@nikomatsakis Would having |
Probably, yes. I think that all lints should have some kind of "positive change" you can make to make the lint go away -- and ideally it should not be "allow the lint". So having a more explicit way to achieve the same thing seems pretty good to me. If that is rustfix-able (which it sounds like it would be), so much the better. In that case, I am in favor. I don't know if we have to tie this to the edition, but I think we certainly could, at least to start. If we expect a lot of people to be affected (I'm not sure I do), perhaps that makes sense. @rfcbot resolve extern-C-code |
That said, we don't actually have #2484, do we? |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
Or else even the more terse It might look kinda hacky, but |
The final comment period, with a disposition to merge, as per the review above, is now complete. |
Huzzah! This RFC has been merged! Tracking issue: rust-lang/rust#54502 |
Rendered
Tracking issue