Skip to content

Commit 19c4771

Browse files
committed
Implementing requested changes
1 parent e822e62 commit 19c4771

File tree

1 file changed

+56
-85
lines changed

1 file changed

+56
-85
lines changed

src/librustc_lint/types.rs

Lines changed: 56 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -153,18 +153,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
153153
if (negative && v > max + 1) || (!negative && v > max) {
154154
if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
155155
let bits = int_ty_bits(t, cx.sess().target.isize_ty);
156-
let mut actually = v as i128;
157-
if bits < 128 {
158-
// v & 0b0..01..1, |1| = bits
159-
let trimmed = v & ((1 << bits) - 1);
160-
actually = if v & (1 << (bits - 1)) == 0 {
161-
// positive
162-
trimmed as i128
163-
} else {
164-
// negative -> two's complement
165-
(((-1 as i128 as u128) << bits) | trimmed) as i128
166-
};
167-
}
156+
let actually =
157+
((v << (128 - bits)) as i128) >> (128 - bits);
168158
let mut err = cx.struct_span_lint(
169159
OVERFLOWING_LITERALS,
170160
e.span,
@@ -175,15 +165,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
175165
an `{:?}` and will become `{}{:?}`.",
176166
repr_str, v, t, actually, t
177167
));
178-
let sugg_ty = get_fitting_type(
168+
let sugg_ty = get_type_suggestion(
179169
&cx.tables.node_id_to_type(e.hir_id).sty,
180170
v,
181171
negative,
182-
).map_or(String::new(), |ty| match ty {
183-
ty::TyUint(t) => format!("Consider using `{:?}`", t),
184-
ty::TyInt(t) => format!("Consider using `{:?}`", t),
185-
_ => String::new(),
186-
});
172+
);
187173
if !sugg_ty.is_empty() {
188174
err.help(&sugg_ty);
189175
}
@@ -221,24 +207,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
221207
if let hir::ExprCast(..) = parent_expr.node {
222208
if let ty::TyChar = cx.tables.expr_ty(parent_expr).sty {
223209
let mut err = cx.struct_span_lint(
224-
OVERFLOWING_LITERALS,
225-
parent_expr.span,
226-
"only u8 can be casted into char",
227-
);
228-
err.span_suggestion(
229-
parent_expr.span,
230-
&"use a char literal instead",
231-
format!("'\\u{{{:X}}}'", lit_val),
232-
);
210+
OVERFLOWING_LITERALS,
211+
parent_expr.span,
212+
"only u8 can be casted into char");
213+
err.span_suggestion(parent_expr.span,
214+
&"use a char literal instead",
215+
format!("'\\u{{{:X}}}'", lit_val));
233216
err.emit();
234-
return;
217+
return
235218
}
236219
}
237220
}
238221
if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
239222
let bits = uint_ty_bits(t, cx.sess().target.usize_ty);
240-
// u128 cannot be greater than max -> compiler error
241-
let actually = lit_val & ((1 << bits) - 1);
223+
let actually = (lit_val << (128 - bits)) >> (128 - bits);
242224
let mut err = cx.struct_span_lint(
243225
OVERFLOWING_LITERALS,
244226
e.span,
@@ -249,19 +231,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
249231
an `{:?}` and will become `{}{:?}`.",
250232
repr_str, lit_val, t, actually, t
251233
));
252-
let sugg_ty = get_fitting_type(
234+
let sugg_ty = get_type_suggestion(
253235
&cx.tables.node_id_to_type(e.hir_id).sty,
254236
lit_val,
255237
false,
256-
).map_or(
257-
String::new(),
258-
|ty| {
259-
if let ty::TyUint(t) = ty {
260-
format!("Consider using `{:?}`", t)
261-
} else {
262-
String::new()
263-
}
264-
},
265238
);
266239
if !sugg_ty.is_empty() {
267240
err.help(&sugg_ty);
@@ -279,19 +252,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
279252
}
280253
ty::TyFloat(t) => {
281254
let is_infinite = match lit.node {
282-
ast::LitKind::Float(v, _) | ast::LitKind::FloatUnsuffixed(v) => match t
283-
{
284-
ast::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite),
285-
ast::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite),
286-
},
255+
ast::LitKind::Float(v, _) |
256+
ast::LitKind::FloatUnsuffixed(v) => {
257+
match t {
258+
ast::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite),
259+
ast::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite),
260+
}
261+
}
287262
_ => bug!(),
288263
};
289264
if is_infinite == Ok(true) {
290-
cx.span_lint(
291-
OVERFLOWING_LITERALS,
292-
e.span,
293-
&format!("literal out of range for {:?}", t),
294-
);
265+
cx.span_lint(OVERFLOWING_LITERALS,
266+
e.span,
267+
&format!("literal out of range for {:?}", t));
295268
}
296269
}
297270
_ => (),
@@ -421,26 +394,27 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
421394
}
422395

423396
fn get_bin_hex_repr(cx: &LateContext, lit: &ast::Lit) -> Option<String> {
424-
if let Some(src) = cx.sess().codemap().span_to_snippet(lit.span).ok() {
425-
if let Some(firstch) = src.chars().next() {
426-
if let Some(0) = char::to_digit(firstch, 10) {
427-
if let Some(base) = src.chars().nth(1) {
428-
if base == 'x' || base == 'b' {
429-
return Some(src);
430-
}
431-
}
432-
}
397+
let src = cx.sess().codemap().span_to_snippet(lit.span).ok()?;
398+
let firstch = src.chars().next()?;
399+
400+
if let Some(0) = char::to_digit(firstch, 10) {
401+
match src.chars().nth(1) {
402+
Some('x') | Some('b') => return Some(src),
403+
_ => return None,
433404
}
434405
}
435406

436407
None
437408
}
438409

439-
fn get_fitting_type<'a>(
440-
t: &ty::TypeVariants,
441-
val: u128,
442-
negative: bool,
443-
) -> Option<ty::TypeVariants<'a>> {
410+
// This function finds the next fitting type and generates a suggestion string.
411+
// It searches for fitting types in the following way (`X < Y`):
412+
// - `iX`: if literal fits in `uX` => `uX`, else => `iY`
413+
// - `-iX` => `iY`
414+
// - `uX` => `uY`
415+
//
416+
// No suggestion for: `isize`, `usize`.
417+
fn get_type_suggestion<'a>(t: &ty::TypeVariants, val: u128, negative: bool) -> String {
444418
use syntax::ast::IntTy::*;
445419
use syntax::ast::UintTy::*;
446420
macro_rules! find_fit {
@@ -451,36 +425,33 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
451425
match $ty {
452426
$($type => {
453427
$(if !negative && val <= uint_ty_range($utypes).1 {
454-
return Some(ty::TyUint($utypes))
428+
return format!("Consider using `{:?}`", $utypes)
455429
})*
456430
$(if val <= int_ty_range($itypes).1 as u128 + _neg {
457-
return Some(ty::TyInt($itypes))
431+
return format!("Consider using `{:?}`", $itypes)
458432
})*
459-
None
433+
String::new()
460434
},)*
461-
_ => None
435+
_ => String::new()
462436
}
463437
}
464438
}
465439
}
466-
if let &ty::TyInt(i) = t {
467-
return find_fit!(i, val, negative,
468-
I8 => [U8] => [I16, I32, I64, I128],
469-
I16 => [U16] => [I32, I64, I128],
470-
I32 => [U32] => [I64, I128],
471-
I64 => [U64] => [I128],
472-
I128 => [U128] => []);
473-
}
474-
if let &ty::TyUint(u) = t {
475-
return find_fit!(u, val, negative,
476-
U8 => [U8, U16, U32, U64, U128] => [],
477-
U16 => [U16, U32, U64, U128] => [],
478-
U32 => [U32, U64, U128] => [],
479-
U64 => [U64, U128] => [],
480-
U128 => [U128] => []);
440+
match t {
441+
&ty::TyInt(i) => find_fit!(i, val, negative,
442+
I8 => [U8] => [I16, I32, I64, I128],
443+
I16 => [U16] => [I32, I64, I128],
444+
I32 => [U32] => [I64, I128],
445+
I64 => [U64] => [I128],
446+
I128 => [U128] => []),
447+
&ty::TyUint(u) => find_fit!(u, val, negative,
448+
U8 => [U8, U16, U32, U64, U128] => [],
449+
U16 => [U16, U32, U64, U128] => [],
450+
U32 => [U32, U64, U128] => [],
451+
U64 => [U64, U128] => [],
452+
U128 => [U128] => []),
453+
_ => String::new(),
481454
}
482-
483-
None
484455
}
485456
}
486457
}

0 commit comments

Comments
 (0)