Merge branch 'master' into option_option_pr

This commit is contained in:
Michael Wright
2018-01-17 06:52:00 +02:00
45 changed files with 1066 additions and 479 deletions

View File

@@ -14,6 +14,15 @@ env:
- secure: dj8SwwuRGuzbo2wZq5z7qXIf7P3p7cbSGs1I3pvXQmB6a58gkLiRn/qBcIIegdt/nzXs+Z0Nug+DdesYVeUPxk1hIa/eeU8p6mpyTtZ+30H4QVgVzd0VCthB5F/NUiPVxTgpGpEgCM9/p72xMwTn7AAJfsGqk7AJ4FS5ZZKhqFI= - secure: dj8SwwuRGuzbo2wZq5z7qXIf7P3p7cbSGs1I3pvXQmB6a58gkLiRn/qBcIIegdt/nzXs+Z0Nug+DdesYVeUPxk1hIa/eeU8p6mpyTtZ+30H4QVgVzd0VCthB5F/NUiPVxTgpGpEgCM9/p72xMwTn7AAJfsGqk7AJ4FS5ZZKhqFI=
- RUST_BACKTRACE=1 - RUST_BACKTRACE=1
before_install:
- |
# work-around for issue https://github.com/travis-ci/travis-ci/issues/6307
# might not be necessary in the future
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
command curl -sSL https://rvm.io/mpapis.asc | gpg --import -
rvm get stable
fi
install: install:
- . $HOME/.nvm/nvm.sh - . $HOME/.nvm/nvm.sh
- nvm install stable - nvm install stable

View File

@@ -1,6 +1,15 @@
# Change Log # Change Log
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## 0.0.180
* Rustup to *rustc 1.25.0-nightly (3f92e8d89 2018-01-14)*
## 0.0.179
* Rustup to *rustc 1.25.0-nightly (61452e506 2018-01-09)*
## 0.0.178
* Rustup to *rustc 1.25.0-nightly (ee220daca 2018-01-07)*
## 0.0.177 ## 0.0.177
* Rustup to *rustc 1.24.0-nightly (250b49205 2017-12-21)* * Rustup to *rustc 1.24.0-nightly (250b49205 2017-12-21)*
* New lint: [`match_as_ref`] * New lint: [`match_as_ref`]
@@ -664,6 +673,7 @@ All notable changes to this project will be documented in this file.
[`redundant_closure_call`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_closure_call [`redundant_closure_call`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_closure_call
[`redundant_pattern`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_pattern [`redundant_pattern`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#redundant_pattern
[`regex_macro`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#regex_macro [`regex_macro`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#regex_macro
[`replace_consts`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#replace_consts
[`result_map_unwrap_or_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else [`result_map_unwrap_or_else`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else
[`result_unwrap_used`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#result_unwrap_used [`result_unwrap_used`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#result_unwrap_used
[`reverse_range_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#reverse_range_loop [`reverse_range_loop`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#reverse_range_loop

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "clippy" name = "clippy"
version = "0.0.177" version = "0.0.180"
authors = [ authors = [
"Manish Goregaokar <manishsmail@gmail.com>", "Manish Goregaokar <manishsmail@gmail.com>",
"Andre Bogus <bogusandre@gmail.com>", "Andre Bogus <bogusandre@gmail.com>",
@@ -37,7 +37,7 @@ path = "src/driver.rs"
[dependencies] [dependencies]
# begin automatic update # begin automatic update
clippy_lints = { version = "0.0.177", path = "clippy_lints" } clippy_lints = { version = "0.0.180", path = "clippy_lints" }
# end automatic update # end automatic update
cargo_metadata = "0.2" cargo_metadata = "0.2"
regex = "0.2" regex = "0.2"

View File

@@ -26,18 +26,35 @@ as an included feature during build. All of these options are detailed below.
As a general rule clippy will only work with the *latest* Rust nightly for now. As a general rule clippy will only work with the *latest* Rust nightly for now.
### As a cargo subcommand (`cargo clippy`)
One way to use clippy is by installing clippy through cargo as a cargo
subcommand.
```terminal
cargo +nightly install clippy
```
(The `+nightly` is not necessary if your default `rustup` install is nightly)
Now you can run clippy by invoking `cargo +nightly clippy`.
In case you are not using rustup, you need to set the environment flag
`SYSROOT` during installation so clippy knows where to find `librustc` and
similar crates.
```terminal
SYSROOT=/path/to/rustc/sysroot cargo install clippy
```
### Optional dependency ### Optional dependency
If you want to make clippy an optional dependency, you can do the following: In some cases you might want to include clippy in your project directly, as an
optional dependency. To do this, just modify `Cargo.toml`:
In your `Cargo.toml`:
```toml ```toml
[dependencies] [dependencies]
clippy = { version = "*", optional = true } clippy = { version = "*", optional = true }
[features]
default = []
``` ```
And, in your `main.rs` or `lib.rs`, add these lines: And, in your `main.rs` or `lib.rs`, add these lines:
@@ -54,25 +71,18 @@ Instead of adding the `cfg_attr` attributes you can also run clippy on demand:
(the `-Z no trans`, while not necessary, will stop the compilation process after (the `-Z no trans`, while not necessary, will stop the compilation process after
typechecking (and lints) have completed, which can significantly reduce the runtime). typechecking (and lints) have completed, which can significantly reduce the runtime).
### As a cargo subcommand (`cargo clippy`) Alternatively, to only run clippy when testing:
An alternate way to use clippy is by installing clippy through cargo as a cargo ```toml
subcommand. [dev-dependencies]
clippy = { version = "*" }
```terminal
cargo install clippy
``` ```
Now you can run clippy by invoking `cargo clippy`, or and add to `main.rs` or `lib.rs`:
`rustup run nightly cargo clippy` directly from a directory that is usually
compiled with stable.
In case you are not using rustup, you need to set the environment flag ```
`SYSROOT` during installation so clippy knows where to find `librustc` and #![cfg_attr(test, feature(plugin))]
similar crates. #![cfg_attr(test, plugin(clippy))]
```terminal
SYSROOT=/path/to/rustc/sysroot cargo install clippy
``` ```
### Running clippy from the command line without installing ### Running clippy from the command line without installing
@@ -143,7 +153,7 @@ blacklisted-names = ["toto", "tata", "titi"]
cyclomatic-complexity-threshold = 30 cyclomatic-complexity-threshold = 30
``` ```
See the wiki for more information about which lints can be configured and the See the [list of lints](https://rust-lang-nursery.github.io/rust-clippy/master/index.html) for more information about which lints can be configured and the
meaning of the variables. meaning of the variables.
You can also specify the path to the configuration file with: You can also specify the path to the configuration file with:
@@ -152,7 +162,7 @@ You can also specify the path to the configuration file with:
#![plugin(clippy(conf_file="path/to/clippy's/configuration"))] #![plugin(clippy(conf_file="path/to/clippy's/configuration"))]
``` ```
To deactivate the “for further information visit *wiki-link*” message you can To deactivate the “for further information visit *lint-link*” message you can
define the `CLIPPY_DISABLE_DOCS_LINKS` environment variable. define the `CLIPPY_DISABLE_DOCS_LINKS` environment variable.
### Allowing/denying lints ### Allowing/denying lints

View File

@@ -1,7 +1,7 @@
[package] [package]
name = "clippy_lints" name = "clippy_lints"
# begin automatic update # begin automatic update
version = "0.0.177" version = "0.0.180"
# end automatic update # end automatic update
authors = [ authors = [
"Manish Goregaokar <manishsmail@gmail.com>", "Manish Goregaokar <manishsmail@gmail.com>",

View File

@@ -1,6 +1,6 @@
use syntax::ast::{Item, ItemKind, Ty, TyKind}; use syntax::ast::{Item, ItemKind, Ty, TyKind};
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use utils::{in_macro, span_lint_and_then}; use utils::{in_macro, snippet, span_lint_and_then};
/// **What it does:** Checks for constants with an explicit `'static` lifetime. /// **What it does:** Checks for constants with an explicit `'static` lifetime.
/// ///
@@ -51,14 +51,15 @@ impl StaticConst {
TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) | TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) |
TyKind::Tup(..) => { TyKind::Tup(..) => {
if lifetime.ident.name == "'static" { if lifetime.ident.name == "'static" {
let mut sug: String = String::new(); let snip = snippet(cx, borrow_type.ty.span, "<type>");
let sugg = format!("&{}", snip);
span_lint_and_then( span_lint_and_then(
cx, cx,
CONST_STATIC_LIFETIME, CONST_STATIC_LIFETIME,
lifetime.span, lifetime.span,
"Constants have by default a `'static` lifetime", "Constants have by default a `'static` lifetime",
|db| { |db| {
db.span_suggestion(lifetime.span, "consider removing `'static`", sug); db.span_suggestion(ty.span, "consider removing `'static`", sugg);
}, },
); );
} }

View File

@@ -148,6 +148,13 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref
return; return;
} }
} }
for subst in substs {
if let Some(subst) = subst.as_type() {
if let ty::TyParam(_) = subst.sty {
return;
}
}
}
}, },
_ => (), _ => (),
} }

View File

@@ -86,7 +86,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions {
use rustc::hir::map::Node::*; use rustc::hir::map::Node::*;
let is_impl = if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(nodeid)) { let is_impl = if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(nodeid)) {
matches!(item.node, hir::ItemImpl(_, _, _, _, Some(_), _, _) | hir::ItemAutoImpl(..)) matches!(item.node, hir::ItemImpl(_, _, _, _, Some(_), _, _))
} else { } else {
false false
}; };

View File

@@ -150,6 +150,7 @@ pub mod ptr;
pub mod ranges; pub mod ranges;
pub mod reference; pub mod reference;
pub mod regex; pub mod regex;
pub mod replace_consts;
pub mod returns; pub mod returns;
pub mod serde_api; pub mod serde_api;
pub mod shadow; pub mod shadow;
@@ -361,6 +362,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
reg.register_late_lint_pass(box types::ImplicitHasher); reg.register_late_lint_pass(box types::ImplicitHasher);
reg.register_early_lint_pass(box const_static_lifetime::StaticConst); reg.register_early_lint_pass(box const_static_lifetime::StaticConst);
reg.register_late_lint_pass(box fallible_impl_from::FallibleImplFrom); reg.register_late_lint_pass(box fallible_impl_from::FallibleImplFrom);
reg.register_late_lint_pass(box replace_consts::ReplaceConsts);
reg.register_lint_group("clippy_restrictions", vec![ reg.register_lint_group("clippy_restrictions", vec![
arithmetic::FLOAT_ARITHMETIC, arithmetic::FLOAT_ARITHMETIC,
@@ -399,6 +401,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
print::PRINT_STDOUT, print::PRINT_STDOUT,
print::USE_DEBUG, print::USE_DEBUG,
ranges::RANGE_PLUS_ONE, ranges::RANGE_PLUS_ONE,
replace_consts::REPLACE_CONSTS,
shadow::SHADOW_REUSE, shadow::SHADOW_REUSE,
shadow::SHADOW_SAME, shadow::SHADOW_SAME,
shadow::SHADOW_UNRELATED, shadow::SHADOW_UNRELATED,

View File

@@ -361,9 +361,8 @@ declare_lint! {
/// ```rust /// ```rust
/// x.clone() /// x.clone()
/// ``` /// ```
declare_lint! { declare_restriction_lint! {
pub CLONE_ON_REF_PTR, pub CLONE_ON_REF_PTR,
Warn,
"using 'clone' on a ref-counted pointer" "using 'clone' on a ref-counted pointer"
} }
@@ -1013,6 +1012,7 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t
fn lint_clone_on_ref_ptr(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) { fn lint_clone_on_ref_ptr(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) {
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tables.expr_ty(arg)); let (obj_ty, _) = walk_ptrs_ty_depth(cx.tables.expr_ty(arg));
if let ty::TyAdt(_, subst) = obj_ty.sty {
let caller_type = if match_type(cx, obj_ty, &paths::RC) { let caller_type = if match_type(cx, obj_ty, &paths::RC) {
"Rc" "Rc"
} else if match_type(cx, obj_ty, &paths::ARC) { } else if match_type(cx, obj_ty, &paths::ARC) {
@@ -1029,9 +1029,10 @@ fn lint_clone_on_ref_ptr(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) {
expr.span, expr.span,
"using '.clone()' on a ref-counted pointer", "using '.clone()' on a ref-counted pointer",
"try this", "try this",
format!("{}::clone(&{})", caller_type, snippet(cx, arg.span, "_")), format!("{}::<{}>::clone(&{})", caller_type, subst.type_at(0), snippet(cx, arg.span, "_")),
); );
} }
}
fn lint_string_extend(cx: &LateContext, expr: &hir::Expr, args: &[hir::Expr]) { fn lint_string_extend(cx: &LateContext, expr: &hir::Expr, args: &[hir::Expr]) {

View File

@@ -124,7 +124,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
let desc = match it.node { let desc = match it.node {
hir::ItemConst(..) => "a constant", hir::ItemConst(..) => "a constant",
hir::ItemEnum(..) => "an enum", hir::ItemEnum(..) => "an enum",
hir::ItemFn(..) => "a function", hir::ItemFn(..) => {
// ignore main()
if it.name == "main" {
let def_id = cx.tcx.hir.local_def_id(it.id);
let def_key = cx.tcx.hir.def_key(def_id);
if def_key.parent == Some(hir::def_id::CRATE_DEF_INDEX) {
return;
}
}
"a function"
},
hir::ItemMod(..) => "a module", hir::ItemMod(..) => "a module",
hir::ItemStatic(..) => "a static", hir::ItemStatic(..) => "a static",
hir::ItemStruct(..) => "a struct", hir::ItemStruct(..) => "a struct",
@@ -133,7 +143,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
hir::ItemGlobalAsm(..) => "an assembly blob", hir::ItemGlobalAsm(..) => "an assembly blob",
hir::ItemTy(..) => "a type alias", hir::ItemTy(..) => "a type alias",
hir::ItemUnion(..) => "a union", hir::ItemUnion(..) => "a union",
hir::ItemAutoImpl(..) |
hir::ItemExternCrate(..) | hir::ItemExternCrate(..) |
hir::ItemForeignMod(..) | hir::ItemForeignMod(..) |
hir::ItemImpl(..) | hir::ItemImpl(..) |

View File

@@ -69,8 +69,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutexAtomic {
atomic_name atomic_name
); );
match mutex_param.sty { match mutex_param.sty {
ty::TyUint(t) if t != ast::UintTy::Us => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), ty::TyUint(t) if t != ast::UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg),
ty::TyInt(t) if t != ast::IntTy::Is => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), ty::TyInt(t) if t != ast::IntTy::Isize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg),
_ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg), _ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg),
}; };
} }

View File

@@ -38,7 +38,7 @@ use utils::{in_macro, snippet, span_lint_and_then};
/// let mut v = Vec::<String>::new(); /// let mut v = Vec::<String>::new();
/// let _ = v.iter_mut().filter(|&ref a| a.is_empty()); /// let _ = v.iter_mut().filter(|&ref a| a.is_empty());
/// ``` /// ```
/// This clojure takes a reference on something that has been matched as a /// This closure takes a reference on something that has been matched as a
/// reference and /// reference and
/// de-referenced. /// de-referenced.
/// As such, it could just be |a| a.is_empty() /// As such, it could just be |a| a.is_empty()

View File

@@ -87,7 +87,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
// Exclude non-inherent impls // Exclude non-inherent impls
if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) { if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) {
if matches!(item.node, ItemImpl(_, _, _, _, Some(_), _, _) | ItemAutoImpl(..) | if matches!(item.node, ItemImpl(_, _, _, _, Some(_), _, _) |
ItemTrait(..)) ItemTrait(..))
{ {
return; return;

View File

@@ -35,7 +35,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
if let ExprStruct(_, ref fields, Some(ref base)) = expr.node { if let ExprStruct(_, ref fields, Some(ref base)) = expr.node {
let ty = cx.tables.expr_ty(expr); let ty = cx.tables.expr_ty(expr);
if let ty::TyAdt(def, _) = ty.sty { if let ty::TyAdt(def, _) = ty.sty {
if fields.len() == def.struct_variant().fields.len() { if fields.len() == def.non_enum_variant().fields.len() {
span_lint( span_lint(
cx, cx,
NEEDLESS_UPDATE, NEEDLESS_UPDATE,

View File

@@ -5,7 +5,7 @@ use rustc::lint::*;
use syntax::ast::LitKind; use syntax::ast::LitKind;
use syntax::symbol::InternedString; use syntax::symbol::InternedString;
use syntax_pos::Span; use syntax_pos::Span;
use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint}; use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint, span_lint_and_sugg};
use utils::{opt_def_id, paths}; use utils::{opt_def_id, paths};
/// **What it does:** This lint warns when you using `println!("")` to /// **What it does:** This lint warns when you using `println!("")` to
@@ -182,8 +182,14 @@ fn check_println<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, fmtstr: Inter
if let Ok(snippet) = cx.sess().codemap().span_to_snippet(span); if let Ok(snippet) = cx.sess().codemap().span_to_snippet(span);
if snippet.contains("\"\""); if snippet.contains("\"\"");
then { then {
span_lint(cx, PRINT_WITH_NEWLINE, span, span_lint_and_sugg(
"using `println!(\"\")`, consider using `println!()` instead"); cx,
PRINT_WITH_NEWLINE,
span,
"using `println!(\"\")`",
"replace it with",
"println!()".to_string(),
);
} }
} }
} }

View File

@@ -0,0 +1,102 @@
use rustc::lint::*;
use rustc::hir;
use rustc::hir::def::Def;
use utils::{match_def_path, span_lint_and_sugg};
/// **What it does:** Checks for usage of `ATOMIC_X_INIT`, `ONCE_INIT`, and
/// `uX/iX::MIN/MAX`.
///
/// **Why is this bad?** `const fn`s exist
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// static FOO: AtomicIsize = ATOMIC_ISIZE_INIT;
/// ```
///
/// Could be written:
///
/// ```rust
/// static FOO: AtomicIsize = AtomicIsize::new(0);
/// ```
declare_lint! {
pub REPLACE_CONSTS,
Allow,
"Lint usages of standard library `const`s that could be replaced by `const fn`s"
}
pub struct ReplaceConsts;
impl LintPass for ReplaceConsts {
fn get_lints(&self) -> LintArray {
lint_array!(REPLACE_CONSTS)
}
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ReplaceConsts {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
if_chain! {
if let hir::ExprPath(ref qp) = expr.node;
if let Def::Const(def_id) = cx.tables.qpath_def(qp, expr.hir_id);
then {
for &(const_path, repl_snip) in REPLACEMENTS {
if match_def_path(cx.tcx, def_id, const_path) {
span_lint_and_sugg(
cx,
REPLACE_CONSTS,
expr.span,
&format!("using `{}`", const_path.last().expect("empty path")),
"try this",
repl_snip.to_string(),
);
return;
}
}
}
}
}
}
const REPLACEMENTS: &[(&[&str], &str)] = &[
// Once
(&["core", "sync", "ONCE_INIT"], "Once::new()"),
// Atomic
(&["core", "sync", "atomic", "ATOMIC_BOOL_INIT"], "AtomicBool::new(false)"),
(&["core", "sync", "atomic", "ATOMIC_ISIZE_INIT"], "AtomicIsize::new(0)"),
(&["core", "sync", "atomic", "ATOMIC_I8_INIT"], "AtomicI8::new(0)"),
(&["core", "sync", "atomic", "ATOMIC_I16_INIT"], "AtomicI16::new(0)"),
(&["core", "sync", "atomic", "ATOMIC_I32_INIT"], "AtomicI32::new(0)"),
(&["core", "sync", "atomic", "ATOMIC_I64_INIT"], "AtomicI64::new(0)"),
(&["core", "sync", "atomic", "ATOMIC_USIZE_INIT"], "AtomicUsize::new(0)"),
(&["core", "sync", "atomic", "ATOMIC_U8_INIT"], "AtomicU8::new(0)"),
(&["core", "sync", "atomic", "ATOMIC_U16_INIT"], "AtomicU16::new(0)"),
(&["core", "sync", "atomic", "ATOMIC_U32_INIT"], "AtomicU32::new(0)"),
(&["core", "sync", "atomic", "ATOMIC_U64_INIT"], "AtomicU64::new(0)"),
// Min
(&["core", "isize", "MIN"], "isize::min_value()"),
(&["core", "i8", "MIN"], "i8::min_value()"),
(&["core", "i16", "MIN"], "i16::min_value()"),
(&["core", "i32", "MIN"], "i32::min_value()"),
(&["core", "i64", "MIN"], "i64::min_value()"),
(&["core", "i128", "MIN"], "i128::min_value()"),
(&["core", "usize", "MIN"], "usize::min_value()"),
(&["core", "u8", "MIN"], "u8::min_value()"),
(&["core", "u16", "MIN"], "u16::min_value()"),
(&["core", "u32", "MIN"], "u32::min_value()"),
(&["core", "u64", "MIN"], "u64::min_value()"),
(&["core", "u128", "MIN"], "u128::min_value()"),
// Max
(&["core", "isize", "MAX"], "isize::max_value()"),
(&["core", "i8", "MAX"], "i8::max_value()"),
(&["core", "i16", "MAX"], "i16::max_value()"),
(&["core", "i32", "MAX"], "i32::max_value()"),
(&["core", "i64", "MAX"], "i64::max_value()"),
(&["core", "i128", "MAX"], "i128::max_value()"),
(&["core", "usize", "MAX"], "usize::max_value()"),
(&["core", "u8", "MAX"], "u8::max_value()"),
(&["core", "u16", "MAX"], "u16::max_value()"),
(&["core", "u32", "MAX"], "u32::max_value()"),
(&["core", "u64", "MAX"], "u64::max_value()"),
(&["core", "u128", "MAX"], "u128::max_value()"),
];

View File

@@ -36,6 +36,14 @@ pub struct TypePass;
/// values: Box<Vec<Foo>>, /// values: Box<Vec<Foo>>,
/// } /// }
/// ``` /// ```
///
/// Better:
///
/// ```rust
/// struct X {
/// values: Vec<Foo>,
/// }
/// ```
declare_lint! { declare_lint! {
pub BOX_VEC, pub BOX_VEC,
Warn, Warn,
@@ -109,6 +117,12 @@ declare_lint! {
/// ```rust /// ```rust
/// fn foo(bar: &Box<T>) { ... } /// fn foo(bar: &Box<T>) { ... }
/// ``` /// ```
///
/// Better:
///
/// ```rust
/// fn foo(bar: &T) { ... }
/// ```
declare_lint! { declare_lint! {
pub BORROWED_BOX, pub BORROWED_BOX,
Warn, Warn,
@@ -553,6 +567,12 @@ declare_lint! {
/// ```rust /// ```rust
/// fn as_u64(x: u8) -> u64 { x as u64 } /// fn as_u64(x: u8) -> u64 { x as u64 }
/// ``` /// ```
///
/// Using `::from` would look like this:
///
/// ```rust
/// fn as_u64(x: u8) -> u64 { u64::from(x) }
/// ```
declare_lint! { declare_lint! {
pub CAST_LOSSLESS, pub CAST_LOSSLESS,
Warn, Warn,
@@ -580,7 +600,7 @@ declare_lint! {
fn int_ty_to_nbits(typ: Ty, tcx: TyCtxt) -> u64 { fn int_ty_to_nbits(typ: Ty, tcx: TyCtxt) -> u64 {
match typ.sty { match typ.sty {
ty::TyInt(i) => match i { ty::TyInt(i) => match i {
IntTy::Is => tcx.data_layout.pointer_size.bits(), IntTy::Isize => tcx.data_layout.pointer_size.bits(),
IntTy::I8 => 8, IntTy::I8 => 8,
IntTy::I16 => 16, IntTy::I16 => 16,
IntTy::I32 => 32, IntTy::I32 => 32,
@@ -588,7 +608,7 @@ fn int_ty_to_nbits(typ: Ty, tcx: TyCtxt) -> u64 {
IntTy::I128 => 128, IntTy::I128 => 128,
}, },
ty::TyUint(i) => match i { ty::TyUint(i) => match i {
UintTy::Us => tcx.data_layout.pointer_size.bits(), UintTy::Usize => tcx.data_layout.pointer_size.bits(),
UintTy::U8 => 8, UintTy::U8 => 8,
UintTy::U16 => 16, UintTy::U16 => 16,
UintTy::U32 => 32, UintTy::U32 => 32,
@@ -601,7 +621,7 @@ fn int_ty_to_nbits(typ: Ty, tcx: TyCtxt) -> u64 {
fn is_isize_or_usize(typ: Ty) -> bool { fn is_isize_or_usize(typ: Ty) -> bool {
match typ.sty { match typ.sty {
ty::TyInt(IntTy::Is) | ty::TyUint(UintTy::Us) => true, ty::TyInt(IntTy::Isize) | ty::TyUint(UintTy::Usize) => true,
_ => false, _ => false,
} }
} }
@@ -1033,6 +1053,12 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
/// ```rust /// ```rust
/// 'x' as u8 /// 'x' as u8
/// ``` /// ```
///
/// A better version, using the byte literal:
///
/// ```rust
/// b'x'
/// ```
declare_lint! { declare_lint! {
pub CHAR_LIT_AS_U8, pub CHAR_LIT_AS_U8,
Warn, Warn,
@@ -1119,6 +1145,20 @@ enum AbsurdComparisonResult {
} }
fn is_cast_between_fixed_and_target<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>,
expr: &'tcx Expr
) -> bool {
if let ExprCast(ref cast_exp, _) = expr.node {
let precast_ty = cx.tables.expr_ty(cast_exp);
let cast_ty = cx.tables.expr_ty(expr);
return is_isize_or_usize(precast_ty) != is_isize_or_usize(cast_ty)
}
return false;
}
fn detect_absurd_comparison<'a, 'tcx>( fn detect_absurd_comparison<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>, cx: &LateContext<'a, 'tcx>,
@@ -1136,6 +1176,11 @@ fn detect_absurd_comparison<'a, 'tcx>(
return None; return None;
} }
// comparisons between fix sized types and target sized types are considered unanalyzable
if is_cast_between_fixed_and_target(cx, lhs) || is_cast_between_fixed_and_target(cx, rhs) {
return None;
}
let normalized = normalize_comparison(op, lhs, rhs); let normalized = normalize_comparison(op, lhs, rhs);
let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized { let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized {
val val
@@ -1190,15 +1235,15 @@ fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -
let which = match (&ty.sty, cv.val) { let which = match (&ty.sty, cv.val) {
(&ty::TyBool, Bool(false)) | (&ty::TyBool, Bool(false)) |
(&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MIN)))) | (&ty::TyInt(IntTy::Isize), Integral(Isize(Is32(::std::i32::MIN)))) |
(&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MIN)))) | (&ty::TyInt(IntTy::Isize), Integral(Isize(Is64(::std::i64::MIN)))) |
(&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MIN))) | (&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MIN))) |
(&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MIN))) | (&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MIN))) |
(&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MIN))) | (&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MIN))) |
(&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MIN))) | (&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MIN))) |
(&ty::TyInt(IntTy::I128), Integral(I128(::std::i128::MIN))) | (&ty::TyInt(IntTy::I128), Integral(I128(::std::i128::MIN))) |
(&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MIN)))) | (&ty::TyUint(UintTy::Usize), Integral(Usize(Us32(::std::u32::MIN)))) |
(&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MIN)))) | (&ty::TyUint(UintTy::Usize), Integral(Usize(Us64(::std::u64::MIN)))) |
(&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MIN))) | (&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MIN))) |
(&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MIN))) | (&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MIN))) |
(&ty::TyUint(UintTy::U32), Integral(U32(::std::u32::MIN))) | (&ty::TyUint(UintTy::U32), Integral(U32(::std::u32::MIN))) |
@@ -1206,15 +1251,15 @@ fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -
(&ty::TyUint(UintTy::U128), Integral(U128(::std::u128::MIN))) => Minimum, (&ty::TyUint(UintTy::U128), Integral(U128(::std::u128::MIN))) => Minimum,
(&ty::TyBool, Bool(true)) | (&ty::TyBool, Bool(true)) |
(&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MAX)))) | (&ty::TyInt(IntTy::Isize), Integral(Isize(Is32(::std::i32::MAX)))) |
(&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MAX)))) | (&ty::TyInt(IntTy::Isize), Integral(Isize(Is64(::std::i64::MAX)))) |
(&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MAX))) | (&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MAX))) |
(&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MAX))) | (&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MAX))) |
(&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MAX))) | (&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MAX))) |
(&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MAX))) | (&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MAX))) |
(&ty::TyInt(IntTy::I128), Integral(I128(::std::i128::MAX))) | (&ty::TyInt(IntTy::I128), Integral(I128(::std::i128::MAX))) |
(&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MAX)))) | (&ty::TyUint(UintTy::Usize), Integral(Usize(Us32(::std::u32::MAX)))) |
(&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MAX)))) | (&ty::TyUint(UintTy::Usize), Integral(Usize(Us64(::std::u64::MAX)))) |
(&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MAX))) | (&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MAX))) |
(&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MAX))) | (&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MAX))) |
(&ty::TyUint(UintTy::U32), Integral(U32(::std::u32::MAX))) | (&ty::TyUint(UintTy::U32), Integral(U32(::std::u32::MAX))) |
@@ -1368,7 +1413,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(
FullInt::S(i128::from(i64::max_value())), FullInt::S(i128::from(i64::max_value())),
), ),
IntTy::I128 => (FullInt::S(i128::min_value() as i128), FullInt::S(i128::max_value() as i128)), IntTy::I128 => (FullInt::S(i128::min_value() as i128), FullInt::S(i128::max_value() as i128)),
IntTy::Is => (FullInt::S(isize::min_value() as i128), FullInt::S(isize::max_value() as i128)), IntTy::Isize => (FullInt::S(isize::min_value() as i128), FullInt::S(isize::max_value() as i128)),
}), }),
ty::TyUint(uint_ty) => Some(match uint_ty { ty::TyUint(uint_ty) => Some(match uint_ty {
UintTy::U8 => (FullInt::U(u128::from(u8::min_value())), FullInt::U(u128::from(u8::max_value()))), UintTy::U8 => (FullInt::U(u128::from(u8::min_value())), FullInt::U(u128::from(u8::max_value()))),
@@ -1385,7 +1430,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(
FullInt::U(u128::from(u64::max_value())), FullInt::U(u128::from(u64::max_value())),
), ),
UintTy::U128 => (FullInt::U(u128::min_value() as u128), FullInt::U(u128::max_value() as u128)), UintTy::U128 => (FullInt::U(u128::min_value() as u128), FullInt::U(u128::max_value() as u128)),
UintTy::Us => (FullInt::U(usize::min_value() as u128), FullInt::U(usize::max_value() as u128)), UintTy::Usize => (FullInt::U(usize::min_value() as u128), FullInt::U(usize::max_value() as u128)),
}), }),
_ => None, _ => None,
} }
@@ -1634,7 +1679,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher {
let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target); let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target);
ctr_vis.visit_body(body); ctr_vis.visit_body(body);
assert!(ctr_vis.suggestions.is_empty());
span_lint_and_then( span_lint_and_then(
cx, cx,

View File

@@ -152,10 +152,10 @@ define_Conf! {
"DirectX", "DirectX",
"ECMAScript", "ECMAScript",
"GPLv2", "GPLv3", "GPLv2", "GPLv3",
"GitHub", "GitHub", "GitLab",
"IPv4", "IPv6", "IPv4", "IPv6",
"JavaScript", "JavaScript",
"NaN", "NaN", "NaNs",
"OAuth", "OAuth",
"OpenGL", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenGL", "OpenSSH", "OpenSSL", "OpenStreetMap",
"TrueType", "TrueType",

View File

@@ -406,9 +406,6 @@ fn print_item(cx: &LateContext, item: &hir::Item) {
hir::ItemTraitAlias(..) => { hir::ItemTraitAlias(..) => {
println!("trait alias"); println!("trait alias");
} }
hir::ItemAutoImpl(_, ref _trait_ref) => {
println!("auto impl");
},
hir::ItemImpl(_, _, _, _, Some(ref _trait_ref), _, _) => { hir::ItemImpl(_, _, _, _, Some(ref _trait_ref), _, _) => {
println!("trait impl"); println!("trait impl");
}, },

View File

@@ -50,3 +50,8 @@ impl PartialOrd<u32> for U {
pub fn foo(val: U) -> bool { pub fn foo(val: U) -> bool {
val > std::u32::MAX val > std::u32::MAX
} }
pub fn bar(len: u64) -> bool {
// This is OK as we are casting from target sized to fixed size
len >= std::usize::MAX as u64
}

View File

@@ -25,36 +25,6 @@ fn main() {
1u32 as i32; 1u32 as i32;
1u64 as i64; 1u64 as i64;
1usize as isize; 1usize as isize;
// Test cast_lossless with casts to integer types
1i8 as i16;
1i8 as i32;
1i8 as i64;
1u8 as i16;
1u8 as i32;
1u8 as i64;
1u8 as u16;
1u8 as u32;
1u8 as u64;
1i16 as i32;
1i16 as i64;
1u16 as i32;
1u16 as i64;
1u16 as u32;
1u16 as u64;
1i32 as i64;
1u32 as i64;
1u32 as u64;
// Test cast_lossless with casts to floating-point types
1i8 as f32;
1i8 as f64;
1u8 as f32;
1u8 as f64;
1i16 as f32;
1i16 as f64;
1u16 as f32;
1u16 as f64;
1i32 as f64;
1u32 as f64;
// Test cast_lossless with casts from floating-point types // Test cast_lossless with casts from floating-point types
1.0f32 as f64; 1.0f32 as f64;
// Test cast_lossless with an expression wrapped in parens // Test cast_lossless with an expression wrapped in parens
@@ -63,25 +33,6 @@ fn main() {
1i32 as u32; 1i32 as u32;
1isize as usize; 1isize as usize;
// Extra checks for *size // Extra checks for *size
// Casting from *size
1isize as i8;
1isize as f64;
1usize as f64;
1isize as f32;
1usize as f32;
1isize as i32;
1isize as u32;
1usize as u32;
1usize as i32;
// Casting to *size
1i64 as isize;
1i64 as usize;
1u64 as isize;
1u64 as usize;
1u32 as isize;
1u32 as usize; // Should not trigger any lint
1i32 as isize; // Neither should this
1i32 as usize;
// Test cast_unnecessary // Test cast_unnecessary
1i32 as i32; 1i32 as i32;
1f32 as f32; 1f32 as f32;

View File

@@ -132,331 +132,49 @@ error: casting usize to isize may wrap around the value
27 | 1usize as isize; 27 | 1usize as isize;
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
error: casting i8 to i16 may become silently lossy if types change error: casting f32 to f64 may become silently lossy if types change
--> $DIR/cast.rs:29:5 --> $DIR/cast.rs:29:5
| |
29 | 1i8 as i16; 29 | 1.0f32 as f64;
| ^^^^^^^^^^ help: try: `i16::from(1i8)` | ^^^^^^^^^^^^^ help: try: `f64::from(1.0f32)`
| |
= note: `-D cast-lossless` implied by `-D warnings` = note: `-D cast-lossless` implied by `-D warnings`
error: casting i8 to i32 may become silently lossy if types change error: casting u8 to u16 may become silently lossy if types change
--> $DIR/cast.rs:30:5
|
30 | 1i8 as i32;
| ^^^^^^^^^^ help: try: `i32::from(1i8)`
error: casting i8 to i64 may become silently lossy if types change
--> $DIR/cast.rs:31:5 --> $DIR/cast.rs:31:5
| |
31 | 1i8 as i64; 31 | (1u8 + 1u8) as u16;
| ^^^^^^^^^^ help: try: `i64::from(1i8)`
error: casting u8 to i16 may become silently lossy if types change
--> $DIR/cast.rs:32:5
|
32 | 1u8 as i16;
| ^^^^^^^^^^ help: try: `i16::from(1u8)`
error: casting u8 to i32 may become silently lossy if types change
--> $DIR/cast.rs:33:5
|
33 | 1u8 as i32;
| ^^^^^^^^^^ help: try: `i32::from(1u8)`
error: casting u8 to i64 may become silently lossy if types change
--> $DIR/cast.rs:34:5
|
34 | 1u8 as i64;
| ^^^^^^^^^^ help: try: `i64::from(1u8)`
error: casting u8 to u16 may become silently lossy if types change
--> $DIR/cast.rs:35:5
|
35 | 1u8 as u16;
| ^^^^^^^^^^ help: try: `u16::from(1u8)`
error: casting u8 to u32 may become silently lossy if types change
--> $DIR/cast.rs:36:5
|
36 | 1u8 as u32;
| ^^^^^^^^^^ help: try: `u32::from(1u8)`
error: casting u8 to u64 may become silently lossy if types change
--> $DIR/cast.rs:37:5
|
37 | 1u8 as u64;
| ^^^^^^^^^^ help: try: `u64::from(1u8)`
error: casting i16 to i32 may become silently lossy if types change
--> $DIR/cast.rs:38:5
|
38 | 1i16 as i32;
| ^^^^^^^^^^^ help: try: `i32::from(1i16)`
error: casting i16 to i64 may become silently lossy if types change
--> $DIR/cast.rs:39:5
|
39 | 1i16 as i64;
| ^^^^^^^^^^^ help: try: `i64::from(1i16)`
error: casting u16 to i32 may become silently lossy if types change
--> $DIR/cast.rs:40:5
|
40 | 1u16 as i32;
| ^^^^^^^^^^^ help: try: `i32::from(1u16)`
error: casting u16 to i64 may become silently lossy if types change
--> $DIR/cast.rs:41:5
|
41 | 1u16 as i64;
| ^^^^^^^^^^^ help: try: `i64::from(1u16)`
error: casting u16 to u32 may become silently lossy if types change
--> $DIR/cast.rs:42:5
|
42 | 1u16 as u32;
| ^^^^^^^^^^^ help: try: `u32::from(1u16)`
error: casting u16 to u64 may become silently lossy if types change
--> $DIR/cast.rs:43:5
|
43 | 1u16 as u64;
| ^^^^^^^^^^^ help: try: `u64::from(1u16)`
error: casting i32 to i64 may become silently lossy if types change
--> $DIR/cast.rs:44:5
|
44 | 1i32 as i64;
| ^^^^^^^^^^^ help: try: `i64::from(1i32)`
error: casting u32 to i64 may become silently lossy if types change
--> $DIR/cast.rs:45:5
|
45 | 1u32 as i64;
| ^^^^^^^^^^^ help: try: `i64::from(1u32)`
error: casting u32 to u64 may become silently lossy if types change
--> $DIR/cast.rs:46:5
|
46 | 1u32 as u64;
| ^^^^^^^^^^^ help: try: `u64::from(1u32)`
error: casting i8 to f32 may become silently lossy if types change
--> $DIR/cast.rs:48:5
|
48 | 1i8 as f32;
| ^^^^^^^^^^ help: try: `f32::from(1i8)`
error: casting i8 to f64 may become silently lossy if types change
--> $DIR/cast.rs:49:5
|
49 | 1i8 as f64;
| ^^^^^^^^^^ help: try: `f64::from(1i8)`
error: casting u8 to f32 may become silently lossy if types change
--> $DIR/cast.rs:50:5
|
50 | 1u8 as f32;
| ^^^^^^^^^^ help: try: `f32::from(1u8)`
error: casting u8 to f64 may become silently lossy if types change
--> $DIR/cast.rs:51:5
|
51 | 1u8 as f64;
| ^^^^^^^^^^ help: try: `f64::from(1u8)`
error: casting i16 to f32 may become silently lossy if types change
--> $DIR/cast.rs:52:5
|
52 | 1i16 as f32;
| ^^^^^^^^^^^ help: try: `f32::from(1i16)`
error: casting i16 to f64 may become silently lossy if types change
--> $DIR/cast.rs:53:5
|
53 | 1i16 as f64;
| ^^^^^^^^^^^ help: try: `f64::from(1i16)`
error: casting u16 to f32 may become silently lossy if types change
--> $DIR/cast.rs:54:5
|
54 | 1u16 as f32;
| ^^^^^^^^^^^ help: try: `f32::from(1u16)`
error: casting u16 to f64 may become silently lossy if types change
--> $DIR/cast.rs:55:5
|
55 | 1u16 as f64;
| ^^^^^^^^^^^ help: try: `f64::from(1u16)`
error: casting i32 to f64 may become silently lossy if types change
--> $DIR/cast.rs:56:5
|
56 | 1i32 as f64;
| ^^^^^^^^^^^ help: try: `f64::from(1i32)`
error: casting u32 to f64 may become silently lossy if types change
--> $DIR/cast.rs:57:5
|
57 | 1u32 as f64;
| ^^^^^^^^^^^ help: try: `f64::from(1u32)`
error: casting f32 to f64 may become silently lossy if types change
--> $DIR/cast.rs:59:5
|
59 | 1.0f32 as f64;
| ^^^^^^^^^^^^^ help: try: `f64::from(1.0f32)`
error: casting u8 to u16 may become silently lossy if types change
--> $DIR/cast.rs:61:5
|
61 | (1u8 + 1u8) as u16;
| ^^^^^^^^^^^^^^^^^^ help: try: `u16::from(1u8 + 1u8)` | ^^^^^^^^^^^^^^^^^^ help: try: `u16::from(1u8 + 1u8)`
error: casting i32 to u32 may lose the sign of the value error: casting i32 to u32 may lose the sign of the value
--> $DIR/cast.rs:63:5 --> $DIR/cast.rs:33:5
| |
63 | 1i32 as u32; 33 | 1i32 as u32;
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: casting isize to usize may lose the sign of the value error: casting isize to usize may lose the sign of the value
--> $DIR/cast.rs:64:5 --> $DIR/cast.rs:34:5
| |
64 | 1isize as usize; 34 | 1isize as usize;
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
error: casting isize to i8 may truncate the value
--> $DIR/cast.rs:67:5
|
67 | 1isize as i8;
| ^^^^^^^^^^^^
error: casting isize to f64 causes a loss of precision on targets with 64-bit wide pointers (isize is 64 bits wide, but f64's mantissa is only 52 bits wide)
--> $DIR/cast.rs:68:5
|
68 | 1isize as f64;
| ^^^^^^^^^^^^^
error: casting usize to f64 causes a loss of precision on targets with 64-bit wide pointers (usize is 64 bits wide, but f64's mantissa is only 52 bits wide)
--> $DIR/cast.rs:69:5
|
69 | 1usize as f64;
| ^^^^^^^^^^^^^
error: casting isize to f32 causes a loss of precision (isize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide)
--> $DIR/cast.rs:70:5
|
70 | 1isize as f32;
| ^^^^^^^^^^^^^
error: casting usize to f32 causes a loss of precision (usize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide)
--> $DIR/cast.rs:71:5
|
71 | 1usize as f32;
| ^^^^^^^^^^^^^
error: casting isize to i32 may truncate the value on targets with 64-bit wide pointers
--> $DIR/cast.rs:72:5
|
72 | 1isize as i32;
| ^^^^^^^^^^^^^
error: casting isize to u32 may lose the sign of the value
--> $DIR/cast.rs:73:5
|
73 | 1isize as u32;
| ^^^^^^^^^^^^^
error: casting isize to u32 may truncate the value on targets with 64-bit wide pointers
--> $DIR/cast.rs:73:5
|
73 | 1isize as u32;
| ^^^^^^^^^^^^^
error: casting usize to u32 may truncate the value on targets with 64-bit wide pointers
--> $DIR/cast.rs:74:5
|
74 | 1usize as u32;
| ^^^^^^^^^^^^^
error: casting usize to i32 may truncate the value on targets with 64-bit wide pointers
--> $DIR/cast.rs:75:5
|
75 | 1usize as i32;
| ^^^^^^^^^^^^^
error: casting usize to i32 may wrap around the value on targets with 32-bit wide pointers
--> $DIR/cast.rs:75:5
|
75 | 1usize as i32;
| ^^^^^^^^^^^^^
error: casting i64 to isize may truncate the value on targets with 32-bit wide pointers
--> $DIR/cast.rs:77:5
|
77 | 1i64 as isize;
| ^^^^^^^^^^^^^
error: casting i64 to usize may lose the sign of the value
--> $DIR/cast.rs:78:5
|
78 | 1i64 as usize;
| ^^^^^^^^^^^^^
error: casting i64 to usize may truncate the value on targets with 32-bit wide pointers
--> $DIR/cast.rs:78:5
|
78 | 1i64 as usize;
| ^^^^^^^^^^^^^
error: casting u64 to isize may truncate the value on targets with 32-bit wide pointers
--> $DIR/cast.rs:79:5
|
79 | 1u64 as isize;
| ^^^^^^^^^^^^^
error: casting u64 to isize may wrap around the value on targets with 64-bit wide pointers
--> $DIR/cast.rs:79:5
|
79 | 1u64 as isize;
| ^^^^^^^^^^^^^
error: casting u64 to usize may truncate the value on targets with 32-bit wide pointers
--> $DIR/cast.rs:80:5
|
80 | 1u64 as usize;
| ^^^^^^^^^^^^^
error: casting u32 to isize may wrap around the value on targets with 32-bit wide pointers
--> $DIR/cast.rs:81:5
|
81 | 1u32 as isize;
| ^^^^^^^^^^^^^
error: casting i32 to usize may lose the sign of the value
--> $DIR/cast.rs:84:5
|
84 | 1i32 as usize;
| ^^^^^^^^^^^^^
error: casting to the same type is unnecessary (`i32` -> `i32`) error: casting to the same type is unnecessary (`i32` -> `i32`)
--> $DIR/cast.rs:86:5 --> $DIR/cast.rs:37:5
| |
86 | 1i32 as i32; 37 | 1i32 as i32;
| ^^^^^^^^^^^ | ^^^^^^^^^^^
| |
= note: `-D unnecessary-cast` implied by `-D warnings` = note: `-D unnecessary-cast` implied by `-D warnings`
error: casting to the same type is unnecessary (`f32` -> `f32`) error: casting to the same type is unnecessary (`f32` -> `f32`)
--> $DIR/cast.rs:87:5 --> $DIR/cast.rs:38:5
| |
87 | 1f32 as f32; 38 | 1f32 as f32;
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: casting to the same type is unnecessary (`bool` -> `bool`) error: casting to the same type is unnecessary (`bool` -> `bool`)
--> $DIR/cast.rs:88:5 --> $DIR/cast.rs:39:5
| |
88 | false as bool; 39 | false as bool;
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^

View File

@@ -0,0 +1,15 @@
#[warn(cast_lossless)]
#[allow(no_effect, unnecessary_operation)]
fn main() {
// Test cast_lossless with casts to floating-point types
1i8 as f32;
1i8 as f64;
1u8 as f32;
1u8 as f64;
1i16 as f32;
1i16 as f64;
1u16 as f32;
1u16 as f64;
1i32 as f64;
1u32 as f64;
}

View File

@@ -0,0 +1,62 @@
error: casting i8 to f32 may become silently lossy if types change
--> $DIR/cast_lossless_float.rs:5:5
|
5 | 1i8 as f32;
| ^^^^^^^^^^ help: try: `f32::from(1i8)`
|
= note: `-D cast-lossless` implied by `-D warnings`
error: casting i8 to f64 may become silently lossy if types change
--> $DIR/cast_lossless_float.rs:6:5
|
6 | 1i8 as f64;
| ^^^^^^^^^^ help: try: `f64::from(1i8)`
error: casting u8 to f32 may become silently lossy if types change
--> $DIR/cast_lossless_float.rs:7:5
|
7 | 1u8 as f32;
| ^^^^^^^^^^ help: try: `f32::from(1u8)`
error: casting u8 to f64 may become silently lossy if types change
--> $DIR/cast_lossless_float.rs:8:5
|
8 | 1u8 as f64;
| ^^^^^^^^^^ help: try: `f64::from(1u8)`
error: casting i16 to f32 may become silently lossy if types change
--> $DIR/cast_lossless_float.rs:9:5
|
9 | 1i16 as f32;
| ^^^^^^^^^^^ help: try: `f32::from(1i16)`
error: casting i16 to f64 may become silently lossy if types change
--> $DIR/cast_lossless_float.rs:10:5
|
10 | 1i16 as f64;
| ^^^^^^^^^^^ help: try: `f64::from(1i16)`
error: casting u16 to f32 may become silently lossy if types change
--> $DIR/cast_lossless_float.rs:11:5
|
11 | 1u16 as f32;
| ^^^^^^^^^^^ help: try: `f32::from(1u16)`
error: casting u16 to f64 may become silently lossy if types change
--> $DIR/cast_lossless_float.rs:12:5
|
12 | 1u16 as f64;
| ^^^^^^^^^^^ help: try: `f64::from(1u16)`
error: casting i32 to f64 may become silently lossy if types change
--> $DIR/cast_lossless_float.rs:13:5
|
13 | 1i32 as f64;
| ^^^^^^^^^^^ help: try: `f64::from(1i32)`
error: casting u32 to f64 may become silently lossy if types change
--> $DIR/cast_lossless_float.rs:14:5
|
14 | 1u32 as f64;
| ^^^^^^^^^^^ help: try: `f64::from(1u32)`

View File

@@ -0,0 +1,24 @@
#[warn(cast_lossless)]
#[allow(no_effect, unnecessary_operation)]
fn main() {
// Test cast_lossless with casts to integer types
1i8 as i16;
1i8 as i32;
1i8 as i64;
1u8 as i16;
1u8 as i32;
1u8 as i64;
1u8 as u16;
1u8 as u32;
1u8 as u64;
1i16 as i32;
1i16 as i64;
1u16 as i32;
1u16 as i64;
1u16 as u32;
1u16 as u64;
1i32 as i64;
1u32 as i64;
1u32 as u64;
}

View File

@@ -0,0 +1,110 @@
error: casting i8 to i16 may become silently lossy if types change
--> $DIR/cast_lossless_integer.rs:6:5
|
6 | 1i8 as i16;
| ^^^^^^^^^^ help: try: `i16::from(1i8)`
|
= note: `-D cast-lossless` implied by `-D warnings`
error: casting i8 to i32 may become silently lossy if types change
--> $DIR/cast_lossless_integer.rs:7:5
|
7 | 1i8 as i32;
| ^^^^^^^^^^ help: try: `i32::from(1i8)`
error: casting i8 to i64 may become silently lossy if types change
--> $DIR/cast_lossless_integer.rs:8:5
|
8 | 1i8 as i64;
| ^^^^^^^^^^ help: try: `i64::from(1i8)`
error: casting u8 to i16 may become silently lossy if types change
--> $DIR/cast_lossless_integer.rs:9:5
|
9 | 1u8 as i16;
| ^^^^^^^^^^ help: try: `i16::from(1u8)`
error: casting u8 to i32 may become silently lossy if types change
--> $DIR/cast_lossless_integer.rs:10:5
|
10 | 1u8 as i32;
| ^^^^^^^^^^ help: try: `i32::from(1u8)`
error: casting u8 to i64 may become silently lossy if types change
--> $DIR/cast_lossless_integer.rs:11:5
|
11 | 1u8 as i64;
| ^^^^^^^^^^ help: try: `i64::from(1u8)`
error: casting u8 to u16 may become silently lossy if types change
--> $DIR/cast_lossless_integer.rs:12:5
|
12 | 1u8 as u16;
| ^^^^^^^^^^ help: try: `u16::from(1u8)`
error: casting u8 to u32 may become silently lossy if types change
--> $DIR/cast_lossless_integer.rs:13:5
|
13 | 1u8 as u32;
| ^^^^^^^^^^ help: try: `u32::from(1u8)`
error: casting u8 to u64 may become silently lossy if types change
--> $DIR/cast_lossless_integer.rs:14:5
|
14 | 1u8 as u64;
| ^^^^^^^^^^ help: try: `u64::from(1u8)`
error: casting i16 to i32 may become silently lossy if types change
--> $DIR/cast_lossless_integer.rs:15:5
|
15 | 1i16 as i32;
| ^^^^^^^^^^^ help: try: `i32::from(1i16)`
error: casting i16 to i64 may become silently lossy if types change
--> $DIR/cast_lossless_integer.rs:16:5
|
16 | 1i16 as i64;
| ^^^^^^^^^^^ help: try: `i64::from(1i16)`
error: casting u16 to i32 may become silently lossy if types change
--> $DIR/cast_lossless_integer.rs:17:5
|
17 | 1u16 as i32;
| ^^^^^^^^^^^ help: try: `i32::from(1u16)`
error: casting u16 to i64 may become silently lossy if types change
--> $DIR/cast_lossless_integer.rs:18:5
|
18 | 1u16 as i64;
| ^^^^^^^^^^^ help: try: `i64::from(1u16)`
error: casting u16 to u32 may become silently lossy if types change
--> $DIR/cast_lossless_integer.rs:19:5
|
19 | 1u16 as u32;
| ^^^^^^^^^^^ help: try: `u32::from(1u16)`
error: casting u16 to u64 may become silently lossy if types change
--> $DIR/cast_lossless_integer.rs:20:5
|
20 | 1u16 as u64;
| ^^^^^^^^^^^ help: try: `u64::from(1u16)`
error: casting i32 to i64 may become silently lossy if types change
--> $DIR/cast_lossless_integer.rs:21:5
|
21 | 1i32 as i64;
| ^^^^^^^^^^^ help: try: `i64::from(1i32)`
error: casting u32 to i64 may become silently lossy if types change
--> $DIR/cast_lossless_integer.rs:22:5
|
22 | 1u32 as i64;
| ^^^^^^^^^^^ help: try: `i64::from(1u32)`
error: casting u32 to u64 may become silently lossy if types change
--> $DIR/cast_lossless_integer.rs:23:5
|
23 | 1u32 as u64;
| ^^^^^^^^^^^ help: try: `u64::from(1u32)`

23
tests/ui/cast_size.rs Normal file
View File

@@ -0,0 +1,23 @@
#[warn(cast_precision_loss, cast_possible_truncation, cast_sign_loss, cast_possible_wrap, cast_lossless)]
#[allow(no_effect, unnecessary_operation)]
fn main() {
// Casting from *size
1isize as i8;
1isize as f64;
1usize as f64;
1isize as f32;
1usize as f32;
1isize as i32;
1isize as u32;
1usize as u32;
1usize as i32;
// Casting to *size
1i64 as isize;
1i64 as usize;
1u64 as isize;
1u64 as usize;
1u32 as isize;
1u32 as usize; // Should not trigger any lint
1i32 as isize; // Neither should this
1i32 as usize;
}

122
tests/ui/cast_size.stderr Normal file
View File

@@ -0,0 +1,122 @@
error: casting isize to i8 may truncate the value
--> $DIR/cast_size.rs:5:5
|
5 | 1isize as i8;
| ^^^^^^^^^^^^
|
= note: `-D cast-possible-truncation` implied by `-D warnings`
error: casting isize to f64 causes a loss of precision on targets with 64-bit wide pointers (isize is 64 bits wide, but f64's mantissa is only 52 bits wide)
--> $DIR/cast_size.rs:6:5
|
6 | 1isize as f64;
| ^^^^^^^^^^^^^
|
= note: `-D cast-precision-loss` implied by `-D warnings`
error: casting usize to f64 causes a loss of precision on targets with 64-bit wide pointers (usize is 64 bits wide, but f64's mantissa is only 52 bits wide)
--> $DIR/cast_size.rs:7:5
|
7 | 1usize as f64;
| ^^^^^^^^^^^^^
error: casting isize to f32 causes a loss of precision (isize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide)
--> $DIR/cast_size.rs:8:5
|
8 | 1isize as f32;
| ^^^^^^^^^^^^^
error: casting usize to f32 causes a loss of precision (usize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide)
--> $DIR/cast_size.rs:9:5
|
9 | 1usize as f32;
| ^^^^^^^^^^^^^
error: casting isize to i32 may truncate the value on targets with 64-bit wide pointers
--> $DIR/cast_size.rs:10:5
|
10 | 1isize as i32;
| ^^^^^^^^^^^^^
error: casting isize to u32 may lose the sign of the value
--> $DIR/cast_size.rs:11:5
|
11 | 1isize as u32;
| ^^^^^^^^^^^^^
|
= note: `-D cast-sign-loss` implied by `-D warnings`
error: casting isize to u32 may truncate the value on targets with 64-bit wide pointers
--> $DIR/cast_size.rs:11:5
|
11 | 1isize as u32;
| ^^^^^^^^^^^^^
error: casting usize to u32 may truncate the value on targets with 64-bit wide pointers
--> $DIR/cast_size.rs:12:5
|
12 | 1usize as u32;
| ^^^^^^^^^^^^^
error: casting usize to i32 may truncate the value on targets with 64-bit wide pointers
--> $DIR/cast_size.rs:13:5
|
13 | 1usize as i32;
| ^^^^^^^^^^^^^
error: casting usize to i32 may wrap around the value on targets with 32-bit wide pointers
--> $DIR/cast_size.rs:13:5
|
13 | 1usize as i32;
| ^^^^^^^^^^^^^
|
= note: `-D cast-possible-wrap` implied by `-D warnings`
error: casting i64 to isize may truncate the value on targets with 32-bit wide pointers
--> $DIR/cast_size.rs:15:5
|
15 | 1i64 as isize;
| ^^^^^^^^^^^^^
error: casting i64 to usize may lose the sign of the value
--> $DIR/cast_size.rs:16:5
|
16 | 1i64 as usize;
| ^^^^^^^^^^^^^
error: casting i64 to usize may truncate the value on targets with 32-bit wide pointers
--> $DIR/cast_size.rs:16:5
|
16 | 1i64 as usize;
| ^^^^^^^^^^^^^
error: casting u64 to isize may truncate the value on targets with 32-bit wide pointers
--> $DIR/cast_size.rs:17:5
|
17 | 1u64 as isize;
| ^^^^^^^^^^^^^
error: casting u64 to isize may wrap around the value on targets with 64-bit wide pointers
--> $DIR/cast_size.rs:17:5
|
17 | 1u64 as isize;
| ^^^^^^^^^^^^^
error: casting u64 to usize may truncate the value on targets with 32-bit wide pointers
--> $DIR/cast_size.rs:18:5
|
18 | 1u64 as usize;
| ^^^^^^^^^^^^^
error: casting u32 to isize may wrap around the value on targets with 32-bit wide pointers
--> $DIR/cast_size.rs:19:5
|
19 | 1u32 as isize;
| ^^^^^^^^^^^^^
error: casting i32 to usize may lose the sign of the value
--> $DIR/cast_size.rs:22:5
|
22 | 1i32 as usize;
| ^^^^^^^^^^^^^

View File

@@ -0,0 +1,22 @@
use std::marker::PhantomData;
use std::fmt;
pub struct Key<T> {
#[doc(hidden)]
pub __name: &'static str,
#[doc(hidden)]
pub __phantom: PhantomData<T>,
}
impl<T> Copy for Key<T> {}
impl<T> Clone for Key<T> {
fn clone(&self) -> Self {
Key {
__name: self.__name,
__phantom: self.__phantom,
}
}
}
fn main() {}

View File

@@ -1,4 +1,4 @@
error: compiler plugins are experimental and possibly buggy (see issue #29597) error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597)
--> $DIR/conf_bad_arg.rs:4:1 --> $DIR/conf_bad_arg.rs:4:1
| |
4 | #![plugin(clippy(conf_file))] 4 | #![plugin(clippy(conf_file))]

View File

@@ -1,4 +1,4 @@
error: compiler plugins are experimental and possibly buggy (see issue #29597) error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597)
--> $DIR/conf_bad_toml.rs:4:1 --> $DIR/conf_bad_toml.rs:4:1
| |
4 | #![plugin(clippy(conf_file="../ui/conf_bad_toml.toml"))] 4 | #![plugin(clippy(conf_file="../ui/conf_bad_toml.toml"))]

View File

@@ -1,4 +1,4 @@
error: compiler plugins are experimental and possibly buggy (see issue #29597) error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597)
--> $DIR/conf_bad_type.rs:4:1 --> $DIR/conf_bad_type.rs:4:1
| |
4 | #![plugin(clippy(conf_file="../ui/conf_bad_type.toml"))] 4 | #![plugin(clippy(conf_file="../ui/conf_bad_type.toml"))]

View File

@@ -1,4 +1,4 @@
error: compiler plugins are experimental and possibly buggy (see issue #29597) error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597)
--> $DIR/conf_french_blacklisted_name.rs:2:1 --> $DIR/conf_french_blacklisted_name.rs:2:1
| |
2 | #![plugin(clippy(conf_file="../auxiliary/conf_french_blacklisted_name.toml"))] 2 | #![plugin(clippy(conf_file="../auxiliary/conf_french_blacklisted_name.toml"))]

View File

@@ -1,4 +1,4 @@
error: compiler plugins are experimental and possibly buggy (see issue #29597) error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597)
--> $DIR/conf_path_non_string.rs:3:1 --> $DIR/conf_path_non_string.rs:3:1
| |
3 | #![plugin(clippy(conf_file=42))] 3 | #![plugin(clippy(conf_file=42))]

View File

@@ -1,4 +1,4 @@
error: compiler plugins are experimental and possibly buggy (see issue #29597) error[E0658]: compiler plugins are experimental and possibly buggy (see issue #29597)
--> $DIR/conf_unknown_key.rs:4:1 --> $DIR/conf_unknown_key.rs:4:1
| |
4 | #![plugin(clippy(conf_file="../auxiliary/conf_unknown_key.toml"))] 4 | #![plugin(clippy(conf_file="../auxiliary/conf_unknown_key.toml"))]

View File

@@ -2,7 +2,7 @@ error: Constants have by default a `'static` lifetime
--> $DIR/const_static_lifetime.rs:4:17 --> $DIR/const_static_lifetime.rs:4:17
| |
4 | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static. 4 | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static.
| ^^^^^^^ help: consider removing `'static` | -^^^^^^^---- help: consider removing `'static`: `&str`
| |
= note: `-D const-static-lifetime` implied by `-D warnings` = note: `-D const-static-lifetime` implied by `-D warnings`
@@ -10,71 +10,71 @@ error: Constants have by default a `'static` lifetime
--> $DIR/const_static_lifetime.rs:8:21 --> $DIR/const_static_lifetime.rs:8:21
| |
8 | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static 8 | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static
| ^^^^^^^ help: consider removing `'static` | -^^^^^^^---- help: consider removing `'static`: `&str`
error: Constants have by default a `'static` lifetime error: Constants have by default a `'static` lifetime
--> $DIR/const_static_lifetime.rs:10:32 --> $DIR/const_static_lifetime.rs:10:32
| |
10 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static 10 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static
| ^^^^^^^ help: consider removing `'static` | -^^^^^^^---- help: consider removing `'static`: `&str`
error: Constants have by default a `'static` lifetime error: Constants have by default a `'static` lifetime
--> $DIR/const_static_lifetime.rs:10:47 --> $DIR/const_static_lifetime.rs:10:47
| |
10 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static 10 | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static
| ^^^^^^^ help: consider removing `'static` | -^^^^^^^---- help: consider removing `'static`: `&str`
error: Constants have by default a `'static` lifetime error: Constants have by default a `'static` lifetime
--> $DIR/const_static_lifetime.rs:12:18 --> $DIR/const_static_lifetime.rs:12:18
| |
12 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static 12 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static
| ^^^^^^^ help: consider removing `'static` | -^^^^^^^------------------ help: consider removing `'static`: `&[&[&'static str]]`
error: Constants have by default a `'static` lifetime error: Constants have by default a `'static` lifetime
--> $DIR/const_static_lifetime.rs:12:30 --> $DIR/const_static_lifetime.rs:12:30
| |
12 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static 12 | const VAR_FIVE: &'static [&[&'static str]] = &[&["test"], &["other one"]]; // ERROR Consider removing 'static
| ^^^^^^^ help: consider removing `'static` | -^^^^^^^---- help: consider removing `'static`: `&str`
error: Constants have by default a `'static` lifetime error: Constants have by default a `'static` lifetime
--> $DIR/const_static_lifetime.rs:14:17 --> $DIR/const_static_lifetime.rs:14:17
| |
14 | const VAR_SIX: &'static u8 = &5; 14 | const VAR_SIX: &'static u8 = &5;
| ^^^^^^^ help: consider removing `'static` | -^^^^^^^--- help: consider removing `'static`: `&u8`
error: Constants have by default a `'static` lifetime error: Constants have by default a `'static` lifetime
--> $DIR/const_static_lifetime.rs:16:29 --> $DIR/const_static_lifetime.rs:16:29
| |
16 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; 16 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])];
| ^^^^^^^ help: consider removing `'static` | -^^^^^^^--------------- help: consider removing `'static`: `&[&'static str]`
error: Constants have by default a `'static` lifetime error: Constants have by default a `'static` lifetime
--> $DIR/const_static_lifetime.rs:16:39 --> $DIR/const_static_lifetime.rs:16:39
| |
16 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])]; 16 | const VAR_SEVEN: &[&(&str, &'static [&'static str])] = &[&("one", &["other one"])];
| ^^^^^^^ help: consider removing `'static` | -^^^^^^^---- help: consider removing `'static`: `&str`
error: Constants have by default a `'static` lifetime error: Constants have by default a `'static` lifetime
--> $DIR/const_static_lifetime.rs:18:20 --> $DIR/const_static_lifetime.rs:18:20
| |
18 | const VAR_HEIGHT: &'static Foo = &Foo {}; 18 | const VAR_HEIGHT: &'static Foo = &Foo {};
| ^^^^^^^ help: consider removing `'static` | -^^^^^^^---- help: consider removing `'static`: `&Foo`
error: Constants have by default a `'static` lifetime error: Constants have by default a `'static` lifetime
--> $DIR/const_static_lifetime.rs:20:19 --> $DIR/const_static_lifetime.rs:20:19
| |
20 | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static. 20 | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static.
| ^^^^^^^ help: consider removing `'static` | -^^^^^^^----- help: consider removing `'static`: `&[u8]`
error: Constants have by default a `'static` lifetime error: Constants have by default a `'static` lifetime
--> $DIR/const_static_lifetime.rs:22:19 --> $DIR/const_static_lifetime.rs:22:19
| |
22 | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static. 22 | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static.
| ^^^^^^^ help: consider removing `'static` | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)`
error: Constants have by default a `'static` lifetime error: Constants have by default a `'static` lifetime
--> $DIR/const_static_lifetime.rs:24:19 --> $DIR/const_static_lifetime.rs:24:19
| |
24 | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static. 24 | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static.
| ^^^^^^^ help: consider removing `'static` | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]`

View File

@@ -264,9 +264,3 @@ error: missing documentation for a function
191 | fn also_undocumented2() {} 191 | fn also_undocumented2() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
--> $DIR/missing-doc.rs:202:1
|
202 | fn main() {}
| ^^^^^^^^^^^^

View File

@@ -1,8 +1,8 @@
error: using `println!("")`, consider using `println!()` instead error: using `println!("")`
--> $DIR/println_empty_string.rs:3:5 --> $DIR/println_empty_string.rs:3:5
| |
3 | println!(""); 3 | println!("");
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^ help: replace it with: `println!()`
| |
= note: `-D print-with-newline` implied by `-D warnings` = note: `-D print-with-newline` implied by `-D warnings`

View File

@@ -0,0 +1,96 @@
#![feature(integer_atomics, i128, i128_type)]
#![allow(blacklisted_name)]
#![deny(replace_consts)]
use std::sync::atomic::*;
use std::sync::{ONCE_INIT, Once};
fn bad() {
// Once
{ let foo = ONCE_INIT; };
// Atomic
{ let foo = ATOMIC_BOOL_INIT; };
{ let foo = ATOMIC_ISIZE_INIT; };
{ let foo = ATOMIC_I8_INIT; };
{ let foo = ATOMIC_I16_INIT; };
{ let foo = ATOMIC_I32_INIT; };
{ let foo = ATOMIC_I64_INIT; };
{ let foo = ATOMIC_USIZE_INIT; };
{ let foo = ATOMIC_U8_INIT; };
{ let foo = ATOMIC_U16_INIT; };
{ let foo = ATOMIC_U32_INIT; };
{ let foo = ATOMIC_U64_INIT; };
// Min
{ let foo = std::isize::MIN; };
{ let foo = std::i8::MIN; };
{ let foo = std::i16::MIN; };
{ let foo = std::i32::MIN; };
{ let foo = std::i64::MIN; };
{ let foo = std::i128::MIN; };
{ let foo = std::usize::MIN; };
{ let foo = std::u8::MIN; };
{ let foo = std::u16::MIN; };
{ let foo = std::u32::MIN; };
{ let foo = std::u64::MIN; };
{ let foo = std::u128::MIN; };
// Max
{ let foo = std::isize::MAX; };
{ let foo = std::i8::MAX; };
{ let foo = std::i16::MAX; };
{ let foo = std::i32::MAX; };
{ let foo = std::i64::MAX; };
{ let foo = std::i128::MAX; };
{ let foo = std::usize::MAX; };
{ let foo = std::u8::MAX; };
{ let foo = std::u16::MAX; };
{ let foo = std::u32::MAX; };
{ let foo = std::u64::MAX; };
{ let foo = std::u128::MAX; };
}
fn good() {
// Once
{ let foo = Once::new(); };
// Atomic
{ let foo = AtomicBool::new(false); };
{ let foo = AtomicIsize::new(0); };
{ let foo = AtomicI8::new(0); };
{ let foo = AtomicI16::new(0); };
{ let foo = AtomicI32::new(0); };
{ let foo = AtomicI64::new(0); };
{ let foo = AtomicUsize::new(0); };
{ let foo = AtomicU8::new(0); };
{ let foo = AtomicU16::new(0); };
{ let foo = AtomicU32::new(0); };
{ let foo = AtomicU64::new(0); };
// Min
{ let foo = isize::min_value(); };
{ let foo = i8::min_value(); };
{ let foo = i16::min_value(); };
{ let foo = i32::min_value(); };
{ let foo = i64::min_value(); };
{ let foo = i128::min_value(); };
{ let foo = usize::min_value(); };
{ let foo = u8::min_value(); };
{ let foo = u16::min_value(); };
{ let foo = u32::min_value(); };
{ let foo = u64::min_value(); };
{ let foo = u128::min_value(); };
// Max
{ let foo = isize::max_value(); };
{ let foo = i8::max_value(); };
{ let foo = i16::max_value(); };
{ let foo = i32::max_value(); };
{ let foo = i64::max_value(); };
{ let foo = i128::max_value(); };
{ let foo = usize::max_value(); };
{ let foo = u8::max_value(); };
{ let foo = u16::max_value(); };
{ let foo = u32::max_value(); };
{ let foo = u64::max_value(); };
{ let foo = u128::max_value(); };
}
fn main() {
bad();
good();
}

View File

@@ -0,0 +1,216 @@
error: using `ATOMIC_BOOL_INIT`
--> $DIR/replace_consts.rs:11:17
|
11 | { let foo = ATOMIC_BOOL_INIT; };
| ^^^^^^^^^^^^^^^^ help: try this: `AtomicBool::new(false)`
|
note: lint level defined here
--> $DIR/replace_consts.rs:3:9
|
3 | #![deny(replace_consts)]
| ^^^^^^^^^^^^^^
error: using `ATOMIC_ISIZE_INIT`
--> $DIR/replace_consts.rs:12:17
|
12 | { let foo = ATOMIC_ISIZE_INIT; };
| ^^^^^^^^^^^^^^^^^ help: try this: `AtomicIsize::new(0)`
error: using `ATOMIC_I8_INIT`
--> $DIR/replace_consts.rs:13:17
|
13 | { let foo = ATOMIC_I8_INIT; };
| ^^^^^^^^^^^^^^ help: try this: `AtomicI8::new(0)`
error: using `ATOMIC_I16_INIT`
--> $DIR/replace_consts.rs:14:17
|
14 | { let foo = ATOMIC_I16_INIT; };
| ^^^^^^^^^^^^^^^ help: try this: `AtomicI16::new(0)`
error: using `ATOMIC_I32_INIT`
--> $DIR/replace_consts.rs:15:17
|
15 | { let foo = ATOMIC_I32_INIT; };
| ^^^^^^^^^^^^^^^ help: try this: `AtomicI32::new(0)`
error: using `ATOMIC_I64_INIT`
--> $DIR/replace_consts.rs:16:17
|
16 | { let foo = ATOMIC_I64_INIT; };
| ^^^^^^^^^^^^^^^ help: try this: `AtomicI64::new(0)`
error: using `ATOMIC_USIZE_INIT`
--> $DIR/replace_consts.rs:17:17
|
17 | { let foo = ATOMIC_USIZE_INIT; };
| ^^^^^^^^^^^^^^^^^ help: try this: `AtomicUsize::new(0)`
error: using `ATOMIC_U8_INIT`
--> $DIR/replace_consts.rs:18:17
|
18 | { let foo = ATOMIC_U8_INIT; };
| ^^^^^^^^^^^^^^ help: try this: `AtomicU8::new(0)`
error: using `ATOMIC_U16_INIT`
--> $DIR/replace_consts.rs:19:17
|
19 | { let foo = ATOMIC_U16_INIT; };
| ^^^^^^^^^^^^^^^ help: try this: `AtomicU16::new(0)`
error: using `ATOMIC_U32_INIT`
--> $DIR/replace_consts.rs:20:17
|
20 | { let foo = ATOMIC_U32_INIT; };
| ^^^^^^^^^^^^^^^ help: try this: `AtomicU32::new(0)`
error: using `ATOMIC_U64_INIT`
--> $DIR/replace_consts.rs:21:17
|
21 | { let foo = ATOMIC_U64_INIT; };
| ^^^^^^^^^^^^^^^ help: try this: `AtomicU64::new(0)`
error: using `MIN`
--> $DIR/replace_consts.rs:23:17
|
23 | { let foo = std::isize::MIN; };
| ^^^^^^^^^^^^^^^ help: try this: `isize::min_value()`
error: using `MIN`
--> $DIR/replace_consts.rs:24:17
|
24 | { let foo = std::i8::MIN; };
| ^^^^^^^^^^^^ help: try this: `i8::min_value()`
error: using `MIN`
--> $DIR/replace_consts.rs:25:17
|
25 | { let foo = std::i16::MIN; };
| ^^^^^^^^^^^^^ help: try this: `i16::min_value()`
error: using `MIN`
--> $DIR/replace_consts.rs:26:17
|
26 | { let foo = std::i32::MIN; };
| ^^^^^^^^^^^^^ help: try this: `i32::min_value()`
error: using `MIN`
--> $DIR/replace_consts.rs:27:17
|
27 | { let foo = std::i64::MIN; };
| ^^^^^^^^^^^^^ help: try this: `i64::min_value()`
error: using `MIN`
--> $DIR/replace_consts.rs:28:17
|
28 | { let foo = std::i128::MIN; };
| ^^^^^^^^^^^^^^ help: try this: `i128::min_value()`
error: using `MIN`
--> $DIR/replace_consts.rs:29:17
|
29 | { let foo = std::usize::MIN; };
| ^^^^^^^^^^^^^^^ help: try this: `usize::min_value()`
error: using `MIN`
--> $DIR/replace_consts.rs:30:17
|
30 | { let foo = std::u8::MIN; };
| ^^^^^^^^^^^^ help: try this: `u8::min_value()`
error: using `MIN`
--> $DIR/replace_consts.rs:31:17
|
31 | { let foo = std::u16::MIN; };
| ^^^^^^^^^^^^^ help: try this: `u16::min_value()`
error: using `MIN`
--> $DIR/replace_consts.rs:32:17
|
32 | { let foo = std::u32::MIN; };
| ^^^^^^^^^^^^^ help: try this: `u32::min_value()`
error: using `MIN`
--> $DIR/replace_consts.rs:33:17
|
33 | { let foo = std::u64::MIN; };
| ^^^^^^^^^^^^^ help: try this: `u64::min_value()`
error: using `MIN`
--> $DIR/replace_consts.rs:34:17
|
34 | { let foo = std::u128::MIN; };
| ^^^^^^^^^^^^^^ help: try this: `u128::min_value()`
error: using `MAX`
--> $DIR/replace_consts.rs:36:17
|
36 | { let foo = std::isize::MAX; };
| ^^^^^^^^^^^^^^^ help: try this: `isize::max_value()`
error: using `MAX`
--> $DIR/replace_consts.rs:37:17
|
37 | { let foo = std::i8::MAX; };
| ^^^^^^^^^^^^ help: try this: `i8::max_value()`
error: using `MAX`
--> $DIR/replace_consts.rs:38:17
|
38 | { let foo = std::i16::MAX; };
| ^^^^^^^^^^^^^ help: try this: `i16::max_value()`
error: using `MAX`
--> $DIR/replace_consts.rs:39:17
|
39 | { let foo = std::i32::MAX; };
| ^^^^^^^^^^^^^ help: try this: `i32::max_value()`
error: using `MAX`
--> $DIR/replace_consts.rs:40:17
|
40 | { let foo = std::i64::MAX; };
| ^^^^^^^^^^^^^ help: try this: `i64::max_value()`
error: using `MAX`
--> $DIR/replace_consts.rs:41:17
|
41 | { let foo = std::i128::MAX; };
| ^^^^^^^^^^^^^^ help: try this: `i128::max_value()`
error: using `MAX`
--> $DIR/replace_consts.rs:42:17
|
42 | { let foo = std::usize::MAX; };
| ^^^^^^^^^^^^^^^ help: try this: `usize::max_value()`
error: using `MAX`
--> $DIR/replace_consts.rs:43:17
|
43 | { let foo = std::u8::MAX; };
| ^^^^^^^^^^^^ help: try this: `u8::max_value()`
error: using `MAX`
--> $DIR/replace_consts.rs:44:17
|
44 | { let foo = std::u16::MAX; };
| ^^^^^^^^^^^^^ help: try this: `u16::max_value()`
error: using `MAX`
--> $DIR/replace_consts.rs:45:17
|
45 | { let foo = std::u32::MAX; };
| ^^^^^^^^^^^^^ help: try this: `u32::max_value()`
error: using `MAX`
--> $DIR/replace_consts.rs:46:17
|
46 | { let foo = std::u64::MAX; };
| ^^^^^^^^^^^^^ help: try this: `u64::max_value()`
error: using `MAX`
--> $DIR/replace_consts.rs:47:17
|
47 | { let foo = std::u128::MAX; };
| ^^^^^^^^^^^^^^ help: try this: `u128::max_value()`

10
tests/ui/types.rs Normal file
View File

@@ -0,0 +1,10 @@
// should not warn on lossy casting in constant types
// because not supported yet
const C : i32 = 42;
const C_I64 : i64 = C as i64;
fn main() {
// should suggest i64::from(c)
let c : i32 = 42;
let c_i64 : i64 = c as i64;
}

8
tests/ui/types.stderr Normal file
View File

@@ -0,0 +1,8 @@
error: casting i32 to i64 may become silently lossy if types change
--> $DIR/types.rs:9:23
|
9 | let c_i64 : i64 = c as i64;
| ^^^^^^^^ help: try: `i64::from(c)`
|
= note: `-D cast-lossless` implied by `-D warnings`

View File

@@ -1,3 +1,4 @@
#![warn(clone_on_ref_ptr)]
#![allow(unused)] #![allow(unused)]
use std::collections::HashSet; use std::collections::HashSet;
@@ -5,6 +6,10 @@ use std::collections::VecDeque;
use std::rc::{self, Rc}; use std::rc::{self, Rc};
use std::sync::{self, Arc}; use std::sync::{self, Arc};
trait SomeTrait {}
struct SomeImpl;
impl SomeTrait for SomeImpl {}
fn main() {} fn main() {}
fn clone_on_copy() { fn clone_on_copy() {
@@ -34,7 +39,8 @@ fn clone_on_ref_ptr() {
arc_weak.clone(); arc_weak.clone();
sync::Weak::clone(&arc_weak); sync::Weak::clone(&arc_weak);
let x = Arc::new(SomeImpl);
let _: Arc<SomeTrait> = x.clone();
} }
fn clone_on_copy_generic<T: Copy>(t: T) { fn clone_on_copy_generic<T: Copy>(t: T) {

View File

@@ -1,75 +1,81 @@
error: using `clone` on a `Copy` type error: using `clone` on a `Copy` type
--> $DIR/unnecessary_clone.rs:11:5 --> $DIR/unnecessary_clone.rs:16:5
| |
11 | 42.clone(); 16 | 42.clone();
| ^^^^^^^^^^ help: try removing the `clone` call: `42` | ^^^^^^^^^^ help: try removing the `clone` call: `42`
| |
= note: `-D clone-on-copy` implied by `-D warnings` = note: `-D clone-on-copy` implied by `-D warnings`
error: using `clone` on a `Copy` type error: using `clone` on a `Copy` type
--> $DIR/unnecessary_clone.rs:15:5 --> $DIR/unnecessary_clone.rs:20:5
| |
15 | (&42).clone(); 20 | (&42).clone();
| ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)`
error: using '.clone()' on a ref-counted pointer error: using '.clone()' on a ref-counted pointer
--> $DIR/unnecessary_clone.rs:25:5 --> $DIR/unnecessary_clone.rs:30:5
| |
25 | rc.clone(); 30 | rc.clone();
| ^^^^^^^^^^ help: try this: `Rc::clone(&rc)` | ^^^^^^^^^^ help: try this: `Rc::<bool>::clone(&rc)`
| |
= note: `-D clone-on-ref-ptr` implied by `-D warnings` = note: `-D clone-on-ref-ptr` implied by `-D warnings`
error: using '.clone()' on a ref-counted pointer error: using '.clone()' on a ref-counted pointer
--> $DIR/unnecessary_clone.rs:28:5 --> $DIR/unnecessary_clone.rs:33:5
| |
28 | arc.clone(); 33 | arc.clone();
| ^^^^^^^^^^^ help: try this: `Arc::clone(&arc)` | ^^^^^^^^^^^ help: try this: `Arc::<bool>::clone(&arc)`
error: using '.clone()' on a ref-counted pointer error: using '.clone()' on a ref-counted pointer
--> $DIR/unnecessary_clone.rs:31:5 --> $DIR/unnecessary_clone.rs:36:5
| |
31 | rcweak.clone(); 36 | rcweak.clone();
| ^^^^^^^^^^^^^^ help: try this: `Weak::clone(&rcweak)` | ^^^^^^^^^^^^^^ help: try this: `Weak::<bool>::clone(&rcweak)`
error: using '.clone()' on a ref-counted pointer error: using '.clone()' on a ref-counted pointer
--> $DIR/unnecessary_clone.rs:34:5 --> $DIR/unnecessary_clone.rs:39:5
| |
34 | arc_weak.clone(); 39 | arc_weak.clone();
| ^^^^^^^^^^^^^^^^ help: try this: `Weak::clone(&arc_weak)` | ^^^^^^^^^^^^^^^^ help: try this: `Weak::<bool>::clone(&arc_weak)`
error: using '.clone()' on a ref-counted pointer
--> $DIR/unnecessary_clone.rs:43:29
|
43 | let _: Arc<SomeTrait> = x.clone();
| ^^^^^^^^^ help: try this: `Arc::<SomeImpl>::clone(&x)`
error: using `clone` on a `Copy` type error: using `clone` on a `Copy` type
--> $DIR/unnecessary_clone.rs:41:5 --> $DIR/unnecessary_clone.rs:47:5
| |
41 | t.clone(); 47 | t.clone();
| ^^^^^^^^^ help: try removing the `clone` call: `t` | ^^^^^^^^^ help: try removing the `clone` call: `t`
error: using `clone` on a `Copy` type error: using `clone` on a `Copy` type
--> $DIR/unnecessary_clone.rs:43:5 --> $DIR/unnecessary_clone.rs:49:5
| |
43 | Some(t).clone(); 49 | Some(t).clone();
| ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)`
error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type
--> $DIR/unnecessary_clone.rs:49:22 --> $DIR/unnecessary_clone.rs:55:22
| |
49 | let z: &Vec<_> = y.clone(); 55 | let z: &Vec<_> = y.clone();
| ^^^^^^^^^ | ^^^^^^^^^
| |
= note: `-D clone-double-ref` implied by `-D warnings` = note: `-D clone-double-ref` implied by `-D warnings`
help: try dereferencing it help: try dereferencing it
| |
49 | let z: &Vec<_> = &(*y).clone(); 55 | let z: &Vec<_> = &(*y).clone();
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
help: or try being explicit about what type to clone help: or try being explicit about what type to clone
| |
49 | let z: &Vec<_> = &std::vec::Vec<i32>::clone(y); 55 | let z: &Vec<_> = &std::vec::Vec<i32>::clone(y);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable error: called `cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable
--> $DIR/unnecessary_clone.rs:56:27 --> $DIR/unnecessary_clone.rs:62:27
| |
56 | let v2 : Vec<isize> = v.iter().cloned().collect(); 62 | let v2 : Vec<isize> = v.iter().cloned().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: `-D iter-cloned-collect` implied by `-D warnings` = note: `-D iter-cloned-collect` implied by `-D warnings`