]> git.lizzy.rs Git - rust.git/commitdiff
Add `zero_prefixed_literal` lint
authormcarton <cartonmartin+git@gmail.com>
Sat, 20 Aug 2016 16:11:15 +0000 (18:11 +0200)
committermcarton <cartonmartin+git@gmail.com>
Tue, 23 Aug 2016 16:15:12 +0000 (18:15 +0200)
CHANGELOG.md
README.md
clippy_lints/src/lib.rs
clippy_lints/src/misc_early.rs
tests/compile-fail/literals.rs

index f0e495961b011f630f317d1e335317cdcf6a6b25..9e198b57073f672938b32ceab8ece5a601b29a36 100644 (file)
@@ -1,6 +1,9 @@
 # Change Log
 All notable changes to this project will be documented in this file.
 
+## 0.0.86 — ?
+* New lint: [`zero_prefixed_literal`]
+
 ## 0.0.85 — 2016-08-19
 * Fix ICE with [`useless_attribute`]
 * [`useless_attribute`] ignores [`unused_imports`] on `use` statements
@@ -329,5 +332,6 @@ All notable changes to this project will be documented in this file.
 [`wrong_self_convention`]: https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention
 [`wrong_transmute`]: https://github.com/Manishearth/rust-clippy/wiki#wrong_transmute
 [`zero_divided_by_zero`]: https://github.com/Manishearth/rust-clippy/wiki#zero_divided_by_zero
+[`zero_prefixed_literal`]: https://github.com/Manishearth/rust-clippy/wiki#zero_prefixed_literal
 [`zero_width_space`]: https://github.com/Manishearth/rust-clippy/wiki#zero_width_space
 <!-- end autogenerated links to wiki -->
index 401126165325388578810f2e788f74ee236bf023..b294c75a756f1e392732b0daf1df418aa2172757 100644 (file)
--- a/README.md
+++ b/README.md
@@ -187,6 +187,7 @@ name
 [wrong_self_convention](https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention)                       | warn    | defining a method named with an established prefix (like "into_") that takes `self` with the wrong convention
 [wrong_transmute](https://github.com/Manishearth/rust-clippy/wiki#wrong_transmute)                                   | warn    | transmutes that are confusing at best, undefined behaviour at worst and always useless
 [zero_divided_by_zero](https://github.com/Manishearth/rust-clippy/wiki#zero_divided_by_zero)                         | warn    | usage of `0.0 / 0.0` to obtain NaN instead of std::f32::NaN or std::f64::NaN
+[zero_prefixed_literal](https://github.com/Manishearth/rust-clippy/wiki#zero_prefixed_literal)                       | warn    | integer literals starting with `0`
 [zero_width_space](https://github.com/Manishearth/rust-clippy/wiki#zero_width_space)                                 | deny    | using a zero-width space in a string literal, which is confusing
 
 More to come, please [file an issue](https://github.com/Manishearth/rust-clippy/issues) if you have ideas!
index 07d504f75ad20828729e219bf40cbfa3a5c1ece9..df0b0d9efffb49fe126d6aa9caecde02a5bedf08 100644 (file)
@@ -387,6 +387,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
         misc_early::MIXED_CASE_HEX_LITERALS,
         misc_early::REDUNDANT_CLOSURE_CALL,
         misc_early::UNNEEDED_FIELD_PATTERN,
+        misc_early::ZERO_PREFIXED_LITERAL,
         module_inception::MODULE_INCEPTION,
         mut_reference::UNNECESSARY_MUT_PASSED,
         mutex_atomic::MUTEX_ATOMIC,
index 63b27f48f0d9caf91102bb3459c24bb1ae7ddfb2..47b6854cfa5e5cd1f8033137001c872e913e845f 100644 (file)
     "literals whose suffix is not separated by an underscore"
 }
 
+/// **What it does:** Warns if a integral constant literal starts with `0`.
+///
+/// **Why is this bad?** In some languages (including the infamous C language and most of its
+/// familly), this marks an octal constant. In Rust however, this is a decimal constant. This could
+/// be confusing for both the writer and a reader of the constant.
+///
+/// **Known problems:** None.
+///
+/// **Example:**
+///
+/// In Rust:
+/// ```rust
+/// fn main() {
+///     let a = 0123;
+///     println!("{}", a);
+/// }
+/// ```
+///
+/// prints `123`, while in C:
+///
+/// ```c
+/// #include <stdio.h>
+///
+/// int main() {
+///     int a = 0123;
+///     printf("%d\n", a);
+/// }
+/// ```
+///
+/// prints `83` (as `89 == 0o123` while `123 == 0o173`).
+declare_lint! {
+    pub ZERO_PREFIXED_LITERAL,
+    Warn,
+    "integer literals starting with `0`"
+}
+
 
 #[derive(Copy, Clone)]
 pub struct MiscEarly;
 impl LintPass for MiscEarly {
     fn get_lints(&self) -> LintArray {
         lint_array!(UNNEEDED_FIELD_PATTERN, DUPLICATE_UNDERSCORE_ARGUMENT, REDUNDANT_CLOSURE_CALL,
-                    DOUBLE_NEG, MIXED_CASE_HEX_LITERALS, UNSEPARATED_LITERAL_SUFFIX)
+                    DOUBLE_NEG, MIXED_CASE_HEX_LITERALS, UNSEPARATED_LITERAL_SUFFIX,
+                    ZERO_PREFIXED_LITERAL)
     }
 }
 
@@ -220,7 +257,7 @@ fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
             }
             ExprKind::Lit(ref lit) => {
                 if_let_chain! {[
-                    let LitKind::Int(..) = lit.node,
+                    let LitKind::Int(value, ..) = lit.node,
                     let Some(src) = snippet_opt(cx, lit.span),
                     let Some(firstch) = src.chars().next(),
                     char::to_digit(firstch, 10).is_some()
@@ -250,6 +287,15 @@ fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
                             span_lint(cx, MIXED_CASE_HEX_LITERALS, lit.span,
                                       "inconsistent casing in hexadecimal literal");
                         }
+                    } else if value != 0 && src.starts_with('0') {
+                        span_lint_and_then(cx,
+                                           ZERO_PREFIXED_LITERAL,
+                                           lit.span,
+                                           "this is a decimal constant",
+                                           |db| {
+                            db.span_suggestion(lit.span, "if you mean to use a decimal constant, remove the `0` to remove confusion:", src[1..].to_string());
+                            db.span_suggestion(lit.span, "if you mean to use an octal constant, use `0o`:", format!("0o{}", &src[1..]));
+                        });
                     }
                 }}
                 if_let_chain! {[
index 7645fb56e20029e7724b525b23517009b4b2b60e..91a63646998c84a009c1c66e882d92cdd82b509c 100644 (file)
@@ -2,6 +2,7 @@
 #![plugin(clippy)]
 #![deny(mixed_case_hex_literals)]
 #![deny(unseparated_literal_suffix)]
+#![deny(zero_prefixed_literal)]
 #![allow(dead_code)]
 
 fn main() {
@@ -22,4 +23,13 @@ fn main() {
     let fail5 = 1234isize;    //~ERROR integer type suffix should be separated
     let fail6 = 1234usize;    //~ERROR integer type suffix should be separated
     let fail7 = 1.5f32;       //~ERROR float type suffix should be separated
+
+    let ok9 = 0;
+    let ok10 = 0_i64;
+    let fail8 = 0123;
+    //~^ERROR decimal constant
+    //~|HELP remove the `0`
+    //~|SUGGESTION = 123;
+    //~|HELP use `0o`
+    //~|SUGGESTION = 0o123;
 }