# 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
[`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 -->
[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!
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,
"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)
}
}
}
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()
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! {[
#![plugin(clippy)]
#![deny(mixed_case_hex_literals)]
#![deny(unseparated_literal_suffix)]
+#![deny(zero_prefixed_literal)]
#![allow(dead_code)]
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;
}