Merge pull request #585 from fhartwig/char-lit-as-u8
Add a lint for casts from char literals to u8
This commit is contained in:
commit
148667ce05
@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code.
|
|||||||
[Jump to usage instructions](#usage)
|
[Jump to usage instructions](#usage)
|
||||||
|
|
||||||
##Lints
|
##Lints
|
||||||
There are 98 lints included in this crate:
|
There are 99 lints included in this crate:
|
||||||
|
|
||||||
name | default | meaning
|
name | default | meaning
|
||||||
---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -20,6 +20,7 @@ name
|
|||||||
[cast_possible_wrap](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX`
|
[cast_possible_wrap](https://github.com/Manishearth/rust-clippy/wiki#cast_possible_wrap) | allow | casts that may cause wrapping around the value, e.g `x as i32` where `x: u32` and `x > i32::MAX`
|
||||||
[cast_precision_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64`
|
[cast_precision_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_precision_loss) | allow | casts that cause loss of precision, e.g `x as f32` where `x: u64`
|
||||||
[cast_sign_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_sign_loss) | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32`
|
[cast_sign_loss](https://github.com/Manishearth/rust-clippy/wiki#cast_sign_loss) | allow | casts from signed types to unsigned types, e.g `x as u32` where `x: i32`
|
||||||
|
[char_lit_as_u8](https://github.com/Manishearth/rust-clippy/wiki#char_lit_as_u8) | warn | Casting a character literal to u8
|
||||||
[chars_next_cmp](https://github.com/Manishearth/rust-clippy/wiki#chars_next_cmp) | warn | using `.chars().next()` to check if a string starts with a char
|
[chars_next_cmp](https://github.com/Manishearth/rust-clippy/wiki#chars_next_cmp) | warn | using `.chars().next()` to check if a string starts with a char
|
||||||
[cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended)
|
[cmp_nan](https://github.com/Manishearth/rust-clippy/wiki#cmp_nan) | deny | comparisons to NAN (which will always return false, which is probably not intended)
|
||||||
[cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()`
|
[cmp_owned](https://github.com/Manishearth/rust-clippy/wiki#cmp_owned) | warn | creating owned instances for comparing with others, e.g. `x == "foo".to_string()`
|
||||||
|
@ -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 panic::PanicPass);
|
||||||
reg.register_late_lint_pass(box strings::StringLitAsBytes);
|
reg.register_late_lint_pass(box strings::StringLitAsBytes);
|
||||||
reg.register_late_lint_pass(box derive::Derive);
|
reg.register_late_lint_pass(box derive::Derive);
|
||||||
|
reg.register_late_lint_pass(box types::CharLitAsU8);
|
||||||
|
|
||||||
|
|
||||||
reg.register_lint_group("clippy_pedantic", vec![
|
reg.register_lint_group("clippy_pedantic", vec![
|
||||||
@ -238,6 +239,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
|||||||
temporary_assignment::TEMPORARY_ASSIGNMENT,
|
temporary_assignment::TEMPORARY_ASSIGNMENT,
|
||||||
transmute::USELESS_TRANSMUTE,
|
transmute::USELESS_TRANSMUTE,
|
||||||
types::BOX_VEC,
|
types::BOX_VEC,
|
||||||
|
types::CHAR_LIT_AS_U8,
|
||||||
types::LET_UNIT_VALUE,
|
types::LET_UNIT_VALUE,
|
||||||
types::LINKEDLIST,
|
types::LINKEDLIST,
|
||||||
types::TYPE_COMPLEXITY,
|
types::TYPE_COMPLEXITY,
|
||||||
|
40
src/types.rs
40
src/types.rs
@ -517,3 +517,43 @@ impl<'v> Visitor<'v> for TypeComplexityVisitor {
|
|||||||
self.nest -= sub_nest;
|
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. `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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
8
tests/compile-fail/char_lit_as_u8.rs
Normal file
8
tests/compile-fail/char_lit_as_u8.rs
Normal file
@ -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
|
||||||
|
}
|
@ -9,7 +9,7 @@ import sys
|
|||||||
|
|
||||||
declare_lint_re = re.compile(r'''
|
declare_lint_re = re.compile(r'''
|
||||||
declare_lint! \s* [{(] \s*
|
declare_lint! \s* [{(] \s*
|
||||||
pub \s+ (?P<name>[A-Z_]+) \s*,\s*
|
pub \s+ (?P<name>[A-Z_][A-Z_0-9]*) \s*,\s*
|
||||||
(?P<level>Forbid|Deny|Warn|Allow) \s*,\s*
|
(?P<level>Forbid|Deny|Warn|Allow) \s*,\s*
|
||||||
" (?P<desc>(?:[^"\\]+|\\.)*) " \s* [})]
|
" (?P<desc>(?:[^"\\]+|\\.)*) " \s* [})]
|
||||||
''', re.X | re.S)
|
''', re.X | re.S)
|
||||||
|
Loading…
Reference in New Issue
Block a user