From 04f9d35f64b0a08a6ea2ff6ce8ceab358526cade Mon Sep 17 00:00:00 2001 From: Florian Hartwig Date: Wed, 27 Jan 2016 20:23:59 +0100 Subject: [PATCH] Add a lint for casts from char literals to u8 --- src/lib.rs | 1 + src/types.rs | 38 ++++++++++++++++++++++++++++ tests/compile-fail/char_lit_as_u8.rs | 8 ++++++ 3 files changed, 47 insertions(+) create mode 100644 tests/compile-fail/char_lit_as_u8.rs diff --git a/src/lib.rs b/src/lib.rs index c43c01268fe..731778db606 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -140,6 +140,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_late_lint_pass(box panic::PanicPass); reg.register_late_lint_pass(box strings::StringLitAsBytes); reg.register_late_lint_pass(box derive::Derive); + reg.register_late_lint_pass(box types::CharLitAsU8); reg.register_lint_group("clippy_pedantic", vec![ diff --git a/src/types.rs b/src/types.rs index 427b695d385..42824c36ec6 100644 --- a/src/types.rs +++ b/src/types.rs @@ -517,3 +517,41 @@ impl<'v> Visitor<'v> for TypeComplexityVisitor { self.nest -= sub_nest; } } + +/// **What it does:** This lint points out expressions where a character literal is casted to u8 and suggests using a byte literal instead. +/// +/// **Why is this bad?** In general, casting values to smaller types is error-prone and should be avoided where possible. In the particular case of converting a character literal to u8, it is easy to avoid by just using a byte literal instead. As an added bonus, `b'a'` is even slightly shorter than `'a' as u8`. +/// +/// **Known problems:** None +/// +/// **Example:** `'x' as u8` +declare_lint!(pub CHAR_LIT_AS_U8, Warn, + "Casting a character literal to u8"); + +pub struct CharLitAsU8; + +impl LintPass for CharLitAsU8 { + fn get_lints(&self) -> LintArray { + lint_array!(CHAR_LIT_AS_U8) + } +} + +impl LateLintPass for CharLitAsU8 { + fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { + use syntax::ast::{Lit_, UintTy}; + + if let ExprCast(ref e, _) = expr.node { + if let ExprLit(ref l) = e.node { + if let Lit_::LitChar(_) = l.node { + if ty::TyUint(UintTy::TyU8) == cx.tcx.expr_ty(expr).sty && !in_macro(cx, expr.span) { + let msg = "casting character literal to u8."; + 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); + } + } + } + } + } +} diff --git a/tests/compile-fail/char_lit_as_u8.rs b/tests/compile-fail/char_lit_as_u8.rs new file mode 100644 index 00000000000..4fca878c4da --- /dev/null +++ b/tests/compile-fail/char_lit_as_u8.rs @@ -0,0 +1,8 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#![deny(char_lit_as_u8)] +#![allow(unused_variables)] +fn main() { + let c = 'a' as u8; //~ERROR casting character literal +}