mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-23 05:03:21 +00:00
use a structured suggestion for char-lit-as-u8
This commit is contained in:
parent
70e7d075df
commit
4ea246b0b3
6 changed files with 88 additions and 24 deletions
|
@ -15,7 +15,7 @@ use rustc::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
|
|||
use rustc_errors::Applicability;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_typeck::hir_ty_to_ty;
|
||||
use syntax::ast::{FloatTy, IntTy, UintTy};
|
||||
use syntax::ast::{FloatTy, IntTy, LitIntType, LitKind, UintTy};
|
||||
use syntax::errors::DiagnosticBuilder;
|
||||
use syntax::source_map::Span;
|
||||
use syntax::symbol::sym;
|
||||
|
@ -1122,7 +1122,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Casts {
|
|||
let (cast_from, cast_to) = (cx.tables.expr_ty(ex), cx.tables.expr_ty(expr));
|
||||
lint_fn_to_numeric_cast(cx, expr, ex, cast_from, cast_to);
|
||||
if let ExprKind::Lit(ref lit) = ex.node {
|
||||
use syntax::ast::{LitIntType, LitKind};
|
||||
if let LitKind::Int(n, _) = lit.node {
|
||||
if cast_to.is_floating_point() {
|
||||
let from_nbits = 128 - n.leading_zeros();
|
||||
|
@ -1473,29 +1472,40 @@ declare_clippy_lint! {
|
|||
/// ```
|
||||
pub CHAR_LIT_AS_U8,
|
||||
complexity,
|
||||
"casting a character literal to u8"
|
||||
"casting a character literal to u8 truncates"
|
||||
}
|
||||
|
||||
declare_lint_pass!(CharLitAsU8 => [CHAR_LIT_AS_U8]);
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CharLitAsU8 {
|
||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||
use syntax::ast::LitKind;
|
||||
if_chain! {
|
||||
if !expr.span.from_expansion();
|
||||
if let ExprKind::Cast(e, _) = &expr.node;
|
||||
if let ExprKind::Lit(l) = &e.node;
|
||||
if let LitKind::Char(c) = l.node;
|
||||
if ty::Uint(UintTy::U8) == cx.tables.expr_ty(expr).sty;
|
||||
then {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let snippet = snippet_with_applicability(cx, e.span, "'x'", &mut applicability);
|
||||
|
||||
if let ExprKind::Cast(ref e, _) = expr.node {
|
||||
if let ExprKind::Lit(ref l) = e.node {
|
||||
if let LitKind::Char(_) = l.node {
|
||||
if ty::Uint(UintTy::U8) == cx.tables.expr_ty(expr).sty && !expr.span.from_expansion() {
|
||||
let msg = "casting character literal to u8. `char`s \
|
||||
are 4 bytes wide in rust, so casting to u8 \
|
||||
truncates them";
|
||||
let help = format!(
|
||||
"Consider using a byte literal instead:\nb{}",
|
||||
snippet(cx, e.span, "'x'")
|
||||
);
|
||||
span_help_and_lint(cx, CHAR_LIT_AS_U8, expr.span, msg, &help);
|
||||
}
|
||||
}
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
CHAR_LIT_AS_U8,
|
||||
expr.span,
|
||||
"casting a character literal to `u8` truncates",
|
||||
|db| {
|
||||
db.note("`char` is four bytes wide, but `u8` is a single byte");
|
||||
|
||||
if c.is_ascii() {
|
||||
db.span_suggestion(
|
||||
expr.span,
|
||||
"use a byte literal instead",
|
||||
format!("b{}", snippet),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![warn(clippy::char_lit_as_u8)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
fn main() {
|
||||
let c = 'a' as u8;
|
||||
let _ = '❤' as u8; // no suggestion, since a byte literal won't work.
|
||||
}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
error: casting character literal to u8. `char`s are 4 bytes wide in rust, so casting to u8 truncates them
|
||||
error: casting a character literal to `u8` truncates
|
||||
--> $DIR/char_lit_as_u8.rs:4:13
|
||||
|
|
||||
LL | let c = 'a' as u8;
|
||||
LL | let _ = '❤' as u8; // no suggestion, since a byte literal won't work.
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::char-lit-as-u8` implied by `-D warnings`
|
||||
= help: Consider using a byte literal instead:
|
||||
b'a'
|
||||
= note: `char` is four bytes wide, but `u8` is a single byte
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
10
tests/ui/char_lit_as_u8_suggestions.fixed
Normal file
10
tests/ui/char_lit_as_u8_suggestions.fixed
Normal file
|
@ -0,0 +1,10 @@
|
|||
// run-rustfix
|
||||
|
||||
#![warn(clippy::char_lit_as_u8)]
|
||||
|
||||
fn main() {
|
||||
let _ = b'a';
|
||||
let _ = b'\n';
|
||||
let _ = b'\0';
|
||||
let _ = b'\x01';
|
||||
}
|
10
tests/ui/char_lit_as_u8_suggestions.rs
Normal file
10
tests/ui/char_lit_as_u8_suggestions.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
// run-rustfix
|
||||
|
||||
#![warn(clippy::char_lit_as_u8)]
|
||||
|
||||
fn main() {
|
||||
let _ = 'a' as u8;
|
||||
let _ = '\n' as u8;
|
||||
let _ = '\0' as u8;
|
||||
let _ = '\x01' as u8;
|
||||
}
|
35
tests/ui/char_lit_as_u8_suggestions.stderr
Normal file
35
tests/ui/char_lit_as_u8_suggestions.stderr
Normal file
|
@ -0,0 +1,35 @@
|
|||
error: casting a character literal to `u8` truncates
|
||||
--> $DIR/char_lit_as_u8_suggestions.rs:6:13
|
||||
|
|
||||
LL | let _ = 'a' as u8;
|
||||
| ^^^^^^^^^ help: use a byte literal instead: `b'a'`
|
||||
|
|
||||
= note: `-D clippy::char-lit-as-u8` implied by `-D warnings`
|
||||
= note: `char` is four bytes wide, but `u8` is a single byte
|
||||
|
||||
error: casting a character literal to `u8` truncates
|
||||
--> $DIR/char_lit_as_u8_suggestions.rs:7:13
|
||||
|
|
||||
LL | let _ = '/n' as u8;
|
||||
| ^^^^^^^^^^ help: use a byte literal instead: `b'/n'`
|
||||
|
|
||||
= note: `char` is four bytes wide, but `u8` is a single byte
|
||||
|
||||
error: casting a character literal to `u8` truncates
|
||||
--> $DIR/char_lit_as_u8_suggestions.rs:8:13
|
||||
|
|
||||
LL | let _ = '/0' as u8;
|
||||
| ^^^^^^^^^^ help: use a byte literal instead: `b'/0'`
|
||||
|
|
||||
= note: `char` is four bytes wide, but `u8` is a single byte
|
||||
|
||||
error: casting a character literal to `u8` truncates
|
||||
--> $DIR/char_lit_as_u8_suggestions.rs:9:13
|
||||
|
|
||||
LL | let _ = '/x01' as u8;
|
||||
| ^^^^^^^^^^^^ help: use a byte literal instead: `b'/x01'`
|
||||
|
|
||||
= note: `char` is four bytes wide, but `u8` is a single byte
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
Loading…
Reference in a new issue