Skip to content

Commit

Permalink
use a structured suggestion for char-lit-as-u8
Browse files Browse the repository at this point in the history
  • Loading branch information
euclio committed Aug 20, 2019
1 parent 7810652 commit 741d6ee
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 23 deletions.
42 changes: 24 additions & 18 deletions clippy_lints/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -1480,22 +1479,29 @@ 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 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);
}
}
if_chain! {
if let ExprKind::Cast(e, _) = &expr.node;
if let ExprKind::Lit(l) = &e.node;
if let LitKind::Char(_) = l.node;
if ty::Uint(UintTy::U8) == cx.tables.expr_ty(expr).sty && !expr.span.from_expansion();
then {
let mut applicability = Applicability::MachineApplicable;
let snippet = snippet_with_applicability(cx, e.span, "'x'", &mut applicability);

span_lint_and_then(
cx,
CHAR_LIT_AS_U8,
expr.span,
"casting character literal to `u8`",
|db| {
db.note("`char`s are 4 bytes wide, so casting to `u8` truncates")
.span_suggestion(
expr.span,
"use a byte literal instead",
format!("b{}", snippet),
applicability,
);
});
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions tests/ui/char_lit_as_u8.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// run-rustfix

#![warn(clippy::char_lit_as_u8)]
#![allow(unused_variables)]
fn main() {
let c = b'a';
}
2 changes: 2 additions & 0 deletions tests/ui/char_lit_as_u8.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// run-rustfix

#![warn(clippy::char_lit_as_u8)]
#![allow(unused_variables)]
fn main() {
Expand Down
9 changes: 4 additions & 5 deletions tests/ui/char_lit_as_u8.stderr
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
error: casting character literal to u8. `char`s are 4 bytes wide in rust, so casting to u8 truncates them
--> $DIR/char_lit_as_u8.rs:4:13
error: casting character literal to `u8`
--> $DIR/char_lit_as_u8.rs:6:13
|
LL | let c = 'a' as u8;
| ^^^^^^^^^
| ^^^^^^^^^ help: use a byte literal instead: `b'a'`
|
= note: `-D clippy::char-lit-as-u8` implied by `-D warnings`
= help: Consider using a byte literal instead:
b'a'
= note: `char`s are 4 bytes wide, so casting to `u8` truncates

error: aborting due to previous error

0 comments on commit 741d6ee

Please sign in to comment.