-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Suggest type for overflowing bin/hex-literals #48432
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @oli-obk (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The final error message output looks good to me
src/librustc_lint/types.rs
Outdated
if bits < 128 { | ||
// v & 0b0..01..1, |1| = bits | ||
let trimmed = v & ((1 << bits) - 1); | ||
actually = if v & (1 << (bits - 1)) == 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can simplify these conversions by first casting to i128
and then bitshifting by 128 - bits
to the left and then to the right.
src/librustc_lint/types.rs
Outdated
ast::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite), | ||
} | ||
} | ||
ast::LitKind::Float(v, _) | ast::LitKind::FloatUnsuffixed(v) => match t |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unrelated formatting change
src/librustc_lint/types.rs
Outdated
cx.span_lint(OVERFLOWING_LITERALS, | ||
e.span, | ||
&format!("literal out of range for {:?}", t)); | ||
cx.span_lint( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unrelated formatting change
src/librustc_lint/types.rs
Outdated
@@ -340,6 +421,69 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { | |||
_ => false, | |||
} | |||
} | |||
|
|||
fn get_bin_hex_repr(cx: &LateContext, lit: &ast::Lit) -> Option<String> { | |||
if let Some(src) = cx.sess().codemap().span_to_snippet(lit.span).ok() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can rewrite this entire function with the ?
operator instead of if let
src/librustc_lint/types.rs
Outdated
err.emit(); | ||
return; | ||
} | ||
cx.span_lint( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels like there's a lot of duplication between the error reporting of signed and unsigned integers. Is it possible to merge them into a function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think changing the function get_fitting_type(), that it returns the suggestion string directly is the best approach here.
An extra function for the err.note()
part is hard, because we need the actually
value as i128
in the singed case and as u128
in the unsigned case. Same problem with the Type.
Edit: Actually, I will rewrite the error reporting while adding the span suggestion @estebank requested.
($ty:expr, $val:expr, $negative:expr, | ||
$($type:ident => [$($utypes:expr),*] => [$($itypes:expr),*]),+) => { | ||
{ | ||
let _neg = if negative { 1 } else { 0 }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: preceding underscores suppress dead code warnings, so I'd avoid them if that is not intended.
Also the PR has a succint description for what this function does, which you could copy into a comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The underscore is intended: for finding a fitting unsigned type, we don't look at integer types so the expanded macro never uses _neg
in this case. So the line
if let &ty::TyUint(u) = t {
return find_fit!(u, val, negative
...}
gives a warning. If there is a better way to do this, it would be nice to know :)
And yeah maybe I should have wrote a few more comments. Will do this, while implementing the other suggestions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great!
Could you address @oli-obk's and my comments?
src/librustc_lint/types.rs
Outdated
// - `uX` => `uY` | ||
// | ||
// No suggestion for: `isize`, `usize`. | ||
fn get_type_suggestion<'a>(t: &ty::TypeVariants, val: u128, negative: bool) -> String { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could get_type_suggestion
return an Option<String>
instead? That way you communicate intent that the empty String
doesn't.
src/librustc_lint/types.rs
Outdated
match $ty { | ||
$($type => { | ||
$(if !negative && val <= uint_ty_range($utypes).1 { | ||
return format!("Consider using `{:?}`", $utypes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use leading lowercase here and below
"consider using {:?}
instead"
src/librustc_lint/types.rs
Outdated
false, | ||
); | ||
if !sugg_ty.is_empty() { | ||
err.help(&sugg_ty); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be nice if this were a span_suggestion
instead if it is a numeric literal that sets the type, otherwise provide the help (ideally I would check the source of the type constraint and point at it, but it is not necessary to go down that rabbit hole in this PR):
warning: literal out of range for i8
--> $DIR/type-overflow.rs:34:17
|
34 | let fail = -0b1111_1111i8;
| ^^^^^^^^^^^^^ help: consider using `i16` instead: `-0b1111_1111i16`
|
= note: the literal `0b1111_1111i8` (decimal `255`) does not fit into an `i8` and will become `-1i8`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks better. I will add this, this evening.
src/librustc_lint/types.rs
Outdated
); | ||
err.note(&format!( | ||
"the literal `{}` (decimal `{}`) does not fit into \ | ||
an `{:?}` and will become `{}{:?}`.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove trailing .
34 | let fail = -0b1111_1111i8; //~WARNING literal out of range for i8 | ||
| ^^^^^^^^^^^^^ help: consider using `i16` instead: `0b1111_1111i16` | ||
| | ||
= note: the literal `0b1111_1111i8` (decimal `255`) does not fit into an `i8` and will become `-1i8` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The note says that the literal will become -1i8
(which is technically correct), while fail
will have the value 1i8
due to the negation. That is, because I ignore whether the literal is negated in the generation of the note.
I'm not sure if I should change this because it is correct for the given span.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that this is fine for now. Filed #48535 to follow up.
@bors r+ |
📌 Commit de7d375 has been approved by |
@bors rollup |
Whoops. I failed hard on the rebase. Sorry... :( |
If you can fix the rebase, just do a |
Fixed it somehow. That should be good now. |
@bors r+ rollup |
📌 Commit f45f760 has been approved by |
Completely missed this pitfall, @Manishearth. @flip1995, don't test the i/u size cases, as they're platform dependent and are prone to work locally and in travis, but break in the full run on all targets. |
Should I rebase again? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to rebase if Travis passes
src/librustc_lint/types.rs
Outdated
let src = cx.sess().codemap().span_to_snippet(lit.span).ok()?; | ||
let firstch = src.chars().next()?; | ||
|
||
if let Some(0) = char::to_digit(firstch, 10) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why don't you just check firstch == '0'
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't know why I made this so complicated.
No problem. I'm happy for the great support on my first PR to the rust compiler! :)
r? @estebank |
@bors r+ |
📌 Commit fc33b25 has been approved by |
Suggest type for overflowing bin/hex-literals Fixes rust-lang#48073 For hexadecimal and binary literals, which overflow, it gives an additional note to the warning message, like in this [comment](rust-lang#48073 (comment)). Additionally it will suggest a type (`X < Y`): - `iX`: if literal fits in `uX` => `uX`, else => `iY` - `-iX` => `iY` - `uX` => `uY` Exceptions: `isize`, `usize`. I don't think you can make a good suggestion here. The programmer has to figure it out on it's own in this case. r? @oli-obk
Suggest type for overflowing bin/hex-literals Fixes rust-lang#48073 For hexadecimal and binary literals, which overflow, it gives an additional note to the warning message, like in this [comment](rust-lang#48073 (comment)). Additionally it will suggest a type (`X < Y`): - `iX`: if literal fits in `uX` => `uX`, else => `iY` - `-iX` => `iY` - `uX` => `uY` Exceptions: `isize`, `usize`. I don't think you can make a good suggestion here. The programmer has to figure it out on it's own in this case. r? @oli-obk
Suggest type for overflowing bin/hex-literals Fixes rust-lang#48073 For hexadecimal and binary literals, which overflow, it gives an additional note to the warning message, like in this [comment](rust-lang#48073 (comment)). Additionally it will suggest a type (`X < Y`): - `iX`: if literal fits in `uX` => `uX`, else => `iY` - `-iX` => `iY` - `uX` => `uY` Exceptions: `isize`, `usize`. I don't think you can make a good suggestion here. The programmer has to figure it out on it's own in this case. r? @oli-obk
Suggest type for overflowing bin/hex-literals Fixes rust-lang#48073 For hexadecimal and binary literals, which overflow, it gives an additional note to the warning message, like in this [comment](rust-lang#48073 (comment)). Additionally it will suggest a type (`X < Y`): - `iX`: if literal fits in `uX` => `uX`, else => `iY` - `-iX` => `iY` - `uX` => `uY` Exceptions: `isize`, `usize`. I don't think you can make a good suggestion here. The programmer has to figure it out on it's own in this case. r? @oli-obk
Fixes #48073
For hexadecimal and binary literals, which overflow, it gives an additional note to the warning message, like in this comment.
Additionally it will suggest a type (
X < Y
):iX
: if literal fits inuX
=>uX
, else =>iY
-iX
=>iY
uX
=>uY
Exceptions:
isize
,usize
. I don't think you can make a good suggestion here. The programmer has to figure it out on it's own in this case.r? @oli-obk