about summary refs log tree commit diff
diff options
context:
space:
mode:
authorllogiq <bogusandre@gmail.com>2016-01-27 22:22:43 +0100
committerllogiq <bogusandre@gmail.com>2016-01-27 22:23:21 +0100
commit291b73b8e89c20e72d0e16da150fc6a8a1e8d188 (patch)
treed4ce76be5cbbbc67220e0a3fbc441cd00cb8e659
parenta1ac3125de6ae7cb0ffffd845df28b3ba3872a19 (diff)
parent148667ce05d718105d91b7b91b31893150d4f121 (diff)
downloadrust-291b73b8e89c20e72d0e16da150fc6a8a1e8d188.tar.gz
rust-291b73b8e89c20e72d0e16da150fc6a8a1e8d188.zip
Merge master and re-run update_lints.py
-rw-r--r--README.md3
-rw-r--r--src/lib.rs2
-rw-r--r--src/types.rs40
-rw-r--r--tests/compile-fail/char_lit_as_u8.rs8
-rwxr-xr-xutil/update_lints.py2
5 files changed, 53 insertions, 2 deletions
diff --git a/README.md b/README.md
index 290684d3bad..04b0bd0e384 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code.
 [Jump to usage instructions](#usage)
 
 ##Lints
-There are 99 lints included in this crate:
+There are 100 lints included in this crate:
 
 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_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`
+[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
 [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()`
diff --git a/src/lib.rs b/src/lib.rs
index f44191b562d..6d706888fc3 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![
@@ -239,6 +240,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
         temporary_assignment::TEMPORARY_ASSIGNMENT,
         transmute::USELESS_TRANSMUTE,
         types::BOX_VEC,
+        types::CHAR_LIT_AS_U8,
         types::LET_UNIT_VALUE,
         types::LINKEDLIST,
         types::TYPE_COMPLEXITY,
diff --git a/src/types.rs b/src/types.rs
index 427b695d385..d41896cd490 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -517,3 +517,43 @@ 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. `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);
+                    }
+                }
+            }
+        }
+    }
+}
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
+}
diff --git a/util/update_lints.py b/util/update_lints.py
index 94b2a3a57ba..6a59abcdc15 100755
--- a/util/update_lints.py
+++ b/util/update_lints.py
@@ -9,7 +9,7 @@ import sys
 
 declare_lint_re = re.compile(r'''
     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<desc>(?:[^"\\]+|\\.)*) " \s* [})]
 ''', re.X | re.S)