Skip to content

Commit 9d27722

Browse files
committed
Auto merge of #4418 - euclio:byte-lit-suggestion, r=flip1995
use a structured suggestion for char-lit-as-u8 changelog: use a structured suggestion for char-lit-as-u8
2 parents ffe57fa + 14d1d04 commit 9d27722

7 files changed

+90
-26
lines changed

clippy_lints/src/types.rs

+29-19
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
1515
use rustc_errors::Applicability;
1616
use rustc_target::spec::abi::Abi;
1717
use rustc_typeck::hir_ty_to_ty;
18-
use syntax::ast::{FloatTy, IntTy, UintTy};
18+
use syntax::ast::{FloatTy, IntTy, LitIntType, LitKind, UintTy};
1919
use syntax::errors::DiagnosticBuilder;
2020
use syntax::source_map::Span;
2121
use syntax::symbol::sym;
@@ -1122,7 +1122,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Casts {
11221122
let (cast_from, cast_to) = (cx.tables.expr_ty(ex), cx.tables.expr_ty(expr));
11231123
lint_fn_to_numeric_cast(cx, expr, ex, cast_from, cast_to);
11241124
if let ExprKind::Lit(ref lit) = ex.node {
1125-
use syntax::ast::{LitIntType, LitKind};
11261125
if let LitKind::Int(n, _) = lit.node {
11271126
if cast_to.is_floating_point() {
11281127
let from_nbits = 128 - n.leading_zeros();
@@ -1487,29 +1486,40 @@ declare_clippy_lint! {
14871486
/// ```
14881487
pub CHAR_LIT_AS_U8,
14891488
complexity,
1490-
"casting a character literal to u8"
1489+
"casting a character literal to u8 truncates"
14911490
}
14921491

14931492
declare_lint_pass!(CharLitAsU8 => [CHAR_LIT_AS_U8]);
14941493

14951494
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CharLitAsU8 {
14961495
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
1497-
use syntax::ast::LitKind;
1498-
1499-
if let ExprKind::Cast(ref e, _) = expr.node {
1500-
if let ExprKind::Lit(ref l) = e.node {
1501-
if let LitKind::Char(_) = l.node {
1502-
if ty::Uint(UintTy::U8) == cx.tables.expr_ty(expr).sty && !expr.span.from_expansion() {
1503-
let msg = "casting character literal to u8. `char`s \
1504-
are 4 bytes wide in rust, so casting to u8 \
1505-
truncates them";
1506-
let help = format!(
1507-
"Consider using a byte literal instead:\nb{}",
1508-
snippet(cx, e.span, "'x'")
1509-
);
1510-
span_help_and_lint(cx, CHAR_LIT_AS_U8, expr.span, msg, &help);
1511-
}
1512-
}
1496+
if_chain! {
1497+
if !expr.span.from_expansion();
1498+
if let ExprKind::Cast(e, _) = &expr.node;
1499+
if let ExprKind::Lit(l) = &e.node;
1500+
if let LitKind::Char(c) = l.node;
1501+
if ty::Uint(UintTy::U8) == cx.tables.expr_ty(expr).sty;
1502+
then {
1503+
let mut applicability = Applicability::MachineApplicable;
1504+
let snippet = snippet_with_applicability(cx, e.span, "'x'", &mut applicability);
1505+
1506+
span_lint_and_then(
1507+
cx,
1508+
CHAR_LIT_AS_U8,
1509+
expr.span,
1510+
"casting a character literal to `u8` truncates",
1511+
|db| {
1512+
db.note("`char` is four bytes wide, but `u8` is a single byte");
1513+
1514+
if c.is_ascii() {
1515+
db.span_suggestion(
1516+
expr.span,
1517+
"use a byte literal instead",
1518+
format!("b{}", snippet),
1519+
applicability,
1520+
);
1521+
}
1522+
});
15131523
}
15141524
}
15151525
}

src/lintlist/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ pub const ALL_LINTS: [Lint; 313] = [
171171
Lint {
172172
name: "char_lit_as_u8",
173173
group: "complexity",
174-
desc: "casting a character literal to u8",
174+
desc: "casting a character literal to u8 truncates",
175175
deprecation: None,
176176
module: "types",
177177
},

tests/ui/char_lit_as_u8.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![warn(clippy::char_lit_as_u8)]
2-
#![allow(unused_variables)]
2+
33
fn main() {
4-
let c = 'a' as u8;
4+
let _ = '' as u8; // no suggestion, since a byte literal won't work.
55
}

tests/ui/char_lit_as_u8.stderr

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
error: casting character literal to u8. `char`s are 4 bytes wide in rust, so casting to u8 truncates them
1+
error: casting a character literal to `u8` truncates
22
--> $DIR/char_lit_as_u8.rs:4:13
33
|
4-
LL | let c = 'a' as u8;
4+
LL | let _ = '' as u8; // no suggestion, since a byte literal won't work.
55
| ^^^^^^^^^
66
|
77
= note: `-D clippy::char-lit-as-u8` implied by `-D warnings`
8-
= help: Consider using a byte literal instead:
9-
b'a'
8+
= note: `char` is four bytes wide, but `u8` is a single byte
109

1110
error: aborting due to previous error
1211

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// run-rustfix
2+
3+
#![warn(clippy::char_lit_as_u8)]
4+
5+
fn main() {
6+
let _ = b'a';
7+
let _ = b'\n';
8+
let _ = b'\0';
9+
let _ = b'\x01';
10+
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// run-rustfix
2+
3+
#![warn(clippy::char_lit_as_u8)]
4+
5+
fn main() {
6+
let _ = 'a' as u8;
7+
let _ = '\n' as u8;
8+
let _ = '\0' as u8;
9+
let _ = '\x01' as u8;
10+
}
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error: casting a character literal to `u8` truncates
2+
--> $DIR/char_lit_as_u8_suggestions.rs:6:13
3+
|
4+
LL | let _ = 'a' as u8;
5+
| ^^^^^^^^^ help: use a byte literal instead: `b'a'`
6+
|
7+
= note: `-D clippy::char-lit-as-u8` implied by `-D warnings`
8+
= note: `char` is four bytes wide, but `u8` is a single byte
9+
10+
error: casting a character literal to `u8` truncates
11+
--> $DIR/char_lit_as_u8_suggestions.rs:7:13
12+
|
13+
LL | let _ = '/n' as u8;
14+
| ^^^^^^^^^^ help: use a byte literal instead: `b'/n'`
15+
|
16+
= note: `char` is four bytes wide, but `u8` is a single byte
17+
18+
error: casting a character literal to `u8` truncates
19+
--> $DIR/char_lit_as_u8_suggestions.rs:8:13
20+
|
21+
LL | let _ = '/0' as u8;
22+
| ^^^^^^^^^^ help: use a byte literal instead: `b'/0'`
23+
|
24+
= note: `char` is four bytes wide, but `u8` is a single byte
25+
26+
error: casting a character literal to `u8` truncates
27+
--> $DIR/char_lit_as_u8_suggestions.rs:9:13
28+
|
29+
LL | let _ = '/x01' as u8;
30+
| ^^^^^^^^^^^^ help: use a byte literal instead: `b'/x01'`
31+
|
32+
= note: `char` is four bytes wide, but `u8` is a single byte
33+
34+
error: aborting due to 4 previous errors
35+

0 commit comments

Comments
 (0)