diff --git a/src/lib.rs b/src/lib.rs index c43c01268..731778db6 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 427b695d3..42824c36e 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 000000000..4fca878c4 --- /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 +}