Merge branch 'master' into typos

This commit is contained in:
Matthias Krüger 2018-07-25 19:54:45 +02:00
commit cfc9b33f17
168 changed files with 2659 additions and 2140 deletions

View File

@ -48,8 +48,6 @@ matrix:
- env: INTEGRATION=serde-rs/serde
- env: INTEGRATION=Geal/nom
- env: INTEGRATION=hyperium/hyper
- env: INTEGRATION=rust-lang/cargo
- env: INTEGRATION=rust-lang-nursery/rls
script:
- |

View File

@ -1,6 +1,9 @@
# Change Log
All notable changes to this project will be documented in this file.
## 0.0.212
* Rustup to *rustc 1.29.0-nightly (e06c87544 2018-07-06)*
## 0.0.211
* Rustup to *rustc 1.28.0-nightly (e3bf634e0 2018-06-28)*
@ -504,7 +507,7 @@ All notable changes to this project will be documented in this file.
## 0.0.74 — 2016-06-07
* Fix bug with `cargo-clippy` JSON parsing
* Add the `CLIPPY_DISABLE_DOCS_LINKS` environment variable to deactivate the
“for further information visit *wiki-link*” message.
“for further information visit *lint-link*” message.
## 0.0.73 — 2016-06-05
* Fix false positives in [`useless_let_if_seq`]
@ -609,7 +612,7 @@ All notable changes to this project will be documented in this file.
[`AsRef`]: https://doc.rust-lang.org/std/convert/trait.AsRef.html
[configuration file]: ./rust-clippy#configuration
<!-- begin autogenerated links to wiki -->
<!-- begin autogenerated links to lint list -->
[`absurd_extreme_comparisons`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#absurd_extreme_comparisons
[`almost_swapped`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#almost_swapped
[`approx_constant`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#approx_constant
@ -744,6 +747,7 @@ All notable changes to this project will be documented in this file.
[`misaligned_transmute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#misaligned_transmute
[`misrefactored_assign_op`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#misrefactored_assign_op
[`missing_docs_in_private_items`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#missing_docs_in_private_items
[`missing_inline_in_public_items`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#missing_inline_in_public_items
[`mixed_case_hex_literals`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#mixed_case_hex_literals
[`module_inception`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#module_inception
[`modulo_one`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#modulo_one
@ -890,4 +894,4 @@ All notable changes to this project will be documented in this file.
[`zero_prefixed_literal`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#zero_prefixed_literal
[`zero_ptr`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#zero_ptr
[`zero_width_space`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#zero_width_space
<!-- end autogenerated links to wiki -->
<!-- end autogenerated links to lint list -->

View File

@ -1,4 +1,4 @@
# Contributing to rust-clippy
# Contributing to Clippy
Hello fellow Rustacean! Great to see your interest in compiler internals and lints!
@ -63,7 +63,7 @@ an AST expression). `match_def_path()` in Clippy's `utils` module can also be us
## Writing code
Compiling clippy from scratch can take almost a minute or more depending on your machine.
Compiling Clippy from scratch can take almost a minute or more depending on your machine.
However, since Rust 1.24.0 incremental compilation is enabled by default and compile times for small changes should be quick.
[Llogiq's blog post on lints](https://llogiq.github.io/2015/06/04/workflows.html) is a nice primer
@ -74,7 +74,7 @@ of this.
### Author lint
There is also the internal `author` lint to generate clippy code that detects the offending pattern. It does not work for all of the Rust syntax, but can give a good starting point.
There is also the internal `author` lint to generate Clippy code that detects the offending pattern. It does not work for all of the Rust syntax, but can give a good starting point.
First, create a new UI test file in the `tests/ui/` directory with the pattern you want to match:
@ -93,9 +93,9 @@ a `.stdout` file with the generated code:
// ./tests/ui/my_lint.stdout
if_chain! {
if let Expr_::ExprArray(ref elements) = stmt.node;
if let ExprKind::Array(ref elements) = stmt.node;
if elements.len() == 1;
if let Expr_::ExprLit(ref lit) = elements[0].node;
if let ExprKind::Lit(ref lit) = elements[0].node;
if let LitKind::Int(7, _) = lit.node;
then {
// report your lint here
@ -148,7 +148,7 @@ Therefore you should use `tests/ui/update-all-references.sh` (after running
### Testing manually
Manually testing against an example file is useful if you have added some
`println!`s and test suite output becomes unreadable. To try clippy with your
`println!`s and test suite output becomes unreadable. To try Clippy with your
local modifications, run `cargo run --bin clippy-driver -- -L ./target/debug input.rs` from the
working copy root.
@ -179,7 +179,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
```
The [`rustc_plugin::PluginRegistry`][plugin_registry] provides two methods to register lints: [register_early_lint_pass][reg_early_lint_pass] and [register_late_lint_pass][reg_late_lint_pass].
Both take an object that implements an [`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass] respectively. This is done in every single lint.
Both take an object that implements an [`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass] respectively. This is done in every single lint.
It's worth noting that the majority of `clippy_lints/src/lib.rs` is autogenerated by `util/update_lints.py` and you don't have to add anything by hand. When you are writing your own lint, you can use that script to save you some time.
```rust

View File

@ -2,7 +2,7 @@ cargo-features = ["edition"]
[package]
name = "clippy"
version = "0.0.211"
version = "0.0.212"
authors = [
"Manish Goregaokar <manishsmail@gmail.com>",
"Andre Bogus <bogusandre@gmail.com>",
@ -40,11 +40,51 @@ path = "src/driver.rs"
[dependencies]
# begin automatic update
clippy_lints = { version = "0.0.211", path = "clippy_lints" }
clippy_lints = { version = "0.0.212", path = "clippy_lints" }
# end automatic update
regex = "1"
semver = "0.9"
# Not actually needed right now but required to make sure that clippy/ and cargo build
# with the same set of features in rust-lang/rust
num-traits = "0.2" # enable the default feature
backtrace = "0.3"
# keep in sync with `cargo`'s `Cargo.toml'
[target.'cfg(windows)'.dependencies.winapi]
version = "0.3"
features = [
# keep in sync with `cargo`'s `Cargo.toml'
"handleapi",
"jobapi",
"jobapi2",
"minwindef",
"ntdef",
"ntstatus",
"processenv",
"processthreadsapi",
"psapi",
"synchapi",
"winerror",
"winbase",
"wincon",
"winnt",
# no idea where these come from
"basetsd",
"lmcons",
"memoryapi",
"minschannel",
"minwinbase",
"ntsecapi",
"profileapi",
"schannel",
"securitybaseapi",
"synchapi",
"sysinfoapi",
"timezoneapi",
"wincrypt",
]
[dev-dependencies]
cargo_metadata = "0.5"
compiletest_rs = "0.3.7"

View File

@ -1,7 +1,8 @@
Steps to publish a new clippy version
Steps to publish a new Clippy version
- Bump `package.version` in `./Cargo.toml` (no need to manually bump `dependencies.clippy_lints.version`).
- Write a changelog entry.
- If a nightly update is needed, update `min_version.txt` using `rustc -vV > min_version.txt`
- Run `./pre_publish.sh`
- Review and commit all changed files
- `git push`

View File

@ -1,6 +1,6 @@
We are currently in the process of discussing Clippy 1.0 via the RFC process in https://github.com/rust-lang/rfcs/pull/2476 . The RFC's goal is to clarify policies around lint categorizations and the policy around which lints should be in the compiler and which lints should be in clippy. Please leave your thoughts on the RFC PR.
We are currently in the process of discussing Clippy 1.0 via the RFC process in https://github.com/rust-lang/rfcs/pull/2476 . The RFC's goal is to clarify policies around lint categorizations and the policy around which lints should be in the compiler and which lints should be in Clippy. Please leave your thoughts on the RFC PR.
# rust-clippy
# Clippy
[![Build Status](https://travis-ci.org/rust-lang-nursery/rust-clippy.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rust-clippy)
[![Windows Build status](https://ci.appveyor.com/api/projects/status/id677xpw1dguo7iw?svg=true)](https://ci.appveyor.com/project/rust-lang-libs/rust-clippy)
@ -9,9 +9,9 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
[There are 272 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html)
[There are 273 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html)
We have a bunch of lint categories to allow you to choose how much clippy is supposed to ~~annoy~~ help you:
We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
* `clippy` (everything that has no false positives)
* `clippy_pedantic` (everything)
@ -33,49 +33,51 @@ Table of contents:
## Usage
Since this is a tool for helping the developer of a library or application
write better code, it is recommended not to include clippy as a hard dependency.
write better code, it is recommended not to include Clippy as a hard dependency.
Options include using it as an optional dependency, as a cargo subcommand, or
as an included feature during build. All of these options are detailed below.
as an included feature during build. These options are detailed below.
As a general rule clippy will only work with the *latest* Rust nightly for now.
### As a cargo subcommand (`cargo clippy`)
To install Rust nightly, the recommended way is to use [rustup](https://rustup.rs/):
One way to use Clippy is by installing Clippy through rustup as a cargo
subcommand.
#### Step 1: Install rustup
You can install [rustup](http://rustup.rs/) on supported platforms. This will help
us install clippy and its dependencies.
If you already have rustup installed, update to ensure you have the latest
rustup and compiler:
```terminal
rustup update
```
#### Step 2: Install nightly toolchain
Rustup integration is still new, you will need a relatively new nightly (2018-07-15 or later).
To install Rust nightly with [rustup](https://rustup.rs/):
```terminal
rustup install nightly
```
### As a cargo subcommand (`cargo clippy`)
#### Step 3: Install clippy
One way to use clippy is by installing clippy through cargo as a cargo
subcommand.
Once you have rustup and the nightly toolchain installed, run the following command:
```terminal
cargo +nightly install clippy
rustup component add clippy-preview --toolchain=nightly
```
(The `+nightly` is not necessary if your default `rustup` install is nightly)
Now you can run Clippy by invoking `cargo +nightly clippy`. If nightly is your
default toolchain in rustup, `cargo clippy` will work fine.
Now you can run clippy by invoking `cargo +nightly clippy`.
### Running Clippy from the command line without installing it
To update the subcommand together with the latest nightly use the [rust-update](rust-update) script or run:
```terminal
rustup update nightly
cargo +nightly install --force 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
```
### Running clippy from the command line without installing it
To have cargo compile your crate with clippy without clippy installation
To have cargo compile your crate with Clippy without Clippy installation
in your code, you can use:
```terminal
@ -83,7 +85,7 @@ cargo run --bin cargo-clippy --manifest-path=path_to_clippys_Cargo.toml
```
*[Note](https://github.com/rust-lang-nursery/rust-clippy/wiki#a-word-of-warning):*
Be sure that clippy was compiled with the same version of rustc that cargo invokes here!
Be sure that Clippy was compiled with the same version of rustc that cargo invokes here!
## Configuration
@ -117,7 +119,7 @@ You can add options to `allow`/`warn`/`deny`:
Note: `deny` produces errors instead of warnings.
For convenience, `cargo clippy` automatically defines a `cargo-clippy`
feature. This lets you set lint levels and compile with or without clippy
feature. This lets you set lint levels and compile with or without Clippy
transparently:
```rust
@ -126,12 +128,12 @@ transparently:
## Updating rustc
Sometimes, rustc moves forward without clippy catching up. Therefore updating
rustc may leave clippy a non-functional state until we fix the resulting
Sometimes, rustc moves forward without Clippy catching up. Therefore updating
rustc may leave Clippy a non-functional state until we fix the resulting
breakage.
You can use the [rust-update](rust-update) script to update rustc only if
clippy would also update correctly.
Clippy would also update correctly.
## License

View File

@ -1,8 +1,8 @@
//! This build script ensures that clippy is not compiled with an
//! This build script ensures that Clippy is not compiled with an
//! incompatible version of rust. It will panic with a descriptive
//! error message instead.
//!
//! We specifially want to ensure that clippy is only built with a
//! We specifially want to ensure that Clippy is only built with a
//! rustc version that is newer or equal to the one specified in the
//! `min_version.txt` file.
//!
@ -63,7 +63,7 @@ fn check_rustc_version() {
eprintln!(
"\n{} {}",
Red.bold().paint("error:"),
"clippy requires a nightly version of Rust."
"Clippy requires a nightly version of Rust."
);
print_version_err(&current_version, &*current_date_str);
eprintln!(
@ -80,7 +80,7 @@ fn check_rustc_version() {
eprintln!(
"\n{} {}",
Red.bold().paint("error:"),
"clippy does not support this version of rustc nightly."
"Clippy does not support this version of rustc nightly."
);
eprintln!(
"> {}{}{}",

View File

@ -6,6 +6,7 @@ cargo test --features debugging
mkdir -p ~/rust/cargo/bin
cp target/debug/cargo-clippy ~/rust/cargo/bin/cargo-clippy
cp target/debug/clippy-driver ~/rust/cargo/bin/clippy-driver
rm ~/.cargo/bin/cargo-clippy
PATH=$PATH:~/rust/cargo/bin cargo clippy --all -- -D clippy
cd clippy_workspace_tests && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ..
cd clippy_workspace_tests/src && PATH=$PATH:~/rust/cargo/bin cargo clippy -- -D clippy && cd ../..

View File

@ -1,4 +1,5 @@
set -x
rm ~/.cargo/bin/cargo-clippy
cargo install --force --path .
echo "Running integration test for crate ${INTEGRATION}"

View File

@ -3,7 +3,7 @@ cargo-features = ["edition"]
[package]
name = "clippy_lints"
# begin automatic update
version = "0.0.211"
version = "0.0.212"
# end automatic update
authors = [
"Manish Goregaokar <manishsmail@gmail.com>",
@ -21,8 +21,8 @@ edition = "2018"
[dependencies]
cargo_metadata = "0.5"
itertools = "0.7"
lazy_static = "1.0"
matches = "0.1.2"
lazy_static = "1.0.2"
matches = "0.1.7"
quine-mc_cluskey = "0.2.2"
regex-syntax = "0.6"
semver = "0.9.0"
@ -32,7 +32,7 @@ toml = "0.4"
unicode-normalization = "0.1"
pulldown-cmark = "0.1"
url = "1.7.0"
if_chain = "0.1"
if_chain = "0.1.3"
[features]
debugging = []

View File

@ -1,6 +1,7 @@
use crate::utils::span_lint;
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use std::f64::consts as f64;
use syntax::ast::{FloatTy, Lit, LitKind};
use syntax::symbol;
@ -63,13 +64,13 @@ impl LintPass for Pass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
if let ExprLit(ref lit) = e.node {
if let ExprKind::Lit(ref lit) = e.node {
check_lit(cx, lit, e);
}
}
}
fn check_lit(cx: &LateContext, lit: &Lit, e: &Expr) {
fn check_lit(cx: &LateContext<'_, '_>, lit: &Lit, e: &Expr) {
match lit.node {
LitKind::Float(s, FloatTy::F32) => check_known_consts(cx, e, s, "f32"),
LitKind::Float(s, FloatTy::F64) => check_known_consts(cx, e, s, "f64"),
@ -78,7 +79,7 @@ fn check_lit(cx: &LateContext, lit: &Lit, e: &Expr) {
}
}
fn check_known_consts(cx: &LateContext, e: &Expr, s: symbol::Symbol, module: &str) {
fn check_known_consts(cx: &LateContext<'_, '_>, e: &Expr, s: symbol::Symbol, module: &str) {
let s = s.as_str();
if s.parse::<f64>().is_ok() {
for &(constant, name, min_digits) in KNOWN_CONSTS {

View File

@ -1,6 +1,7 @@
use crate::utils::span_lint;
use rustc::hir;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use syntax::codemap::Span;
/// **What it does:** Checks for plain integer arithmetic.
@ -55,21 +56,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic {
return;
}
match expr.node {
hir::ExprBinary(ref op, ref l, ref r) => {
hir::ExprKind::Binary(ref op, ref l, ref r) => {
match op.node {
hir::BiAnd
| hir::BiOr
| hir::BiBitAnd
| hir::BiBitOr
| hir::BiBitXor
| hir::BiShl
| hir::BiShr
| hir::BiEq
| hir::BiLt
| hir::BiLe
| hir::BiNe
| hir::BiGe
| hir::BiGt => return,
hir::BinOpKind::And
| hir::BinOpKind::Or
| hir::BinOpKind::BitAnd
| hir::BinOpKind::BitOr
| hir::BinOpKind::BitXor
| hir::BinOpKind::Shl
| hir::BinOpKind::Shr
| hir::BinOpKind::Eq
| hir::BinOpKind::Lt
| hir::BinOpKind::Le
| hir::BinOpKind::Ne
| hir::BinOpKind::Ge
| hir::BinOpKind::Gt => return,
_ => (),
}
let (l_ty, r_ty) = (cx.tables.expr_ty(l), cx.tables.expr_ty(r));
@ -81,7 +82,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic {
self.span = Some(expr.span);
}
},
hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => {
hir::ExprKind::Unary(hir::UnOp::UnNeg, ref arg) => {
let ty = cx.tables.expr_ty(arg);
if ty.is_integral() {
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");

View File

@ -3,6 +3,8 @@ use crate::utils::{higher, sugg};
use rustc::hir;
use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use syntax::ast;
/// **What it does:** Checks for compound assignment operations (`+=` and
@ -49,8 +51,10 @@ declare_clippy_lint! {
/// **Why is this bad?** Most likely these are bugs where one meant to write `a
/// op= b`.
///
/// **Known problems:** Someone might actually mean `a op= a op b`, but that
/// should rather be written as `a = (2 * a) op b` where applicable.
/// **Known problems:** Clippy cannot know for sure if `a op= a op b` should have
/// been `a = a op a op b` or `a = a op b`/`a op= b`. Therefore it suggests both.
/// If `a op= a op b` is really the correct behaviour it should be
/// written as `a = a op a op b` as it's less confusing.
///
/// **Example:**
/// ```rust
@ -76,7 +80,7 @@ impl LintPass for AssignOps {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
match expr.node {
hir::ExprAssignOp(op, ref lhs, ref rhs) => {
hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => {
span_lint_and_then(cx, ASSIGN_OPS, expr.span, "assign operation detected", |db| {
let lhs = &sugg::Sugg::hir(cx, lhs, "..");
let rhs = &sugg::Sugg::hir(cx, rhs, "..");
@ -87,7 +91,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
format!("{} = {}", lhs, sugg::make_binop(higher::binop(op.node), lhs, rhs)),
);
});
if let hir::ExprBinary(binop, ref l, ref r) = rhs.node {
if let hir::ExprKind::Binary(binop, ref l, ref r) = rhs.node {
if op.node == binop.node {
let lint = |assignee: &hir::Expr, rhs_other: &hir::Expr| {
span_lint_and_then(
@ -131,8 +135,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
}
}
},
hir::ExprAssign(ref assignee, ref e) => {
if let hir::ExprBinary(op, ref l, ref r) = e.node {
hir::ExprKind::Assign(ref assignee, ref e) => {
if let hir::ExprKind::Binary(op, ref l, ref r) = e.node {
#[allow(cyclomatic_complexity)]
let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
let ty = cx.tables.expr_ty(assignee);
@ -142,9 +146,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
$cx:expr,
$ty:expr,
$rty:expr,
$($trait_name:ident:$full_trait_name:ident),+) => {
$($trait_name:ident),+) => {
match $op {
$(hir::$full_trait_name => {
$(hir::BinOpKind::$trait_name => {
let [krate, module] = crate::utils::paths::OPS_MODULE;
let path = [krate, module, concat!(stringify!($trait_name), "Assign")];
let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) {
@ -159,7 +163,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
if_chain! {
if parent_impl != ast::CRATE_NODE_ID;
if let hir::map::Node::NodeItem(item) = cx.tcx.hir.get(parent_impl);
if let hir::Item_::ItemImpl(_, _, _, _, Some(ref trait_ref), _, _) =
if let hir::ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, _) =
item.node;
if trait_ref.path.def.def_id() == trait_id;
then { return; }
@ -175,18 +179,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
cx,
ty,
rty.into(),
Add: BiAdd,
Sub: BiSub,
Mul: BiMul,
Div: BiDiv,
Rem: BiRem,
And: BiAnd,
Or: BiOr,
BitAnd: BiBitAnd,
BitOr: BiBitOr,
BitXor: BiBitXor,
Shr: BiShr,
Shl: BiShl
Add,
Sub,
Mul,
Div,
Rem,
And,
Or,
BitAnd,
BitOr,
BitXor,
Shr,
Shl
) {
span_lint_and_then(
cx,
@ -224,13 +228,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
// a = b commutative_op a
if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) {
match op.node {
hir::BiAdd
| hir::BiMul
| hir::BiAnd
| hir::BiOr
| hir::BiBitXor
| hir::BiBitAnd
| hir::BiBitOr => {
hir::BinOpKind::Add
| hir::BinOpKind::Mul
| hir::BinOpKind::And
| hir::BinOpKind::Or
| hir::BinOpKind::BitXor
| hir::BinOpKind::BitAnd
| hir::BinOpKind::BitOr => {
lint(assignee, l);
},
_ => {},
@ -244,11 +248,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
}
}
fn is_commutative(op: hir::BinOp_) -> bool {
use rustc::hir::BinOp_::*;
fn is_commutative(op: hir::BinOpKind) -> bool {
use rustc::hir::BinOpKind::*;
match op {
BiAdd | BiMul | BiAnd | BiOr | BiBitXor | BiBitAnd | BiBitOr | BiEq | BiNe => true,
BiSub | BiDiv | BiRem | BiShl | BiShr | BiLt | BiLe | BiGe | BiGt => false,
Add | Mul | And | Or | BitXor | BitAnd | BitOr | Eq | Ne => true,
Sub | Div | Rem | Shl | Shr | Lt | Le | Ge | Gt => false,
}
}

View File

@ -7,6 +7,8 @@ use crate::utils::{
};
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::ty::{self, TyCtxt};
use semver::Version;
use syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
@ -39,22 +41,31 @@ declare_clippy_lint! {
}
/// **What it does:** Checks for `extern crate` and `use` items annotated with
/// lint attributes
/// lint attributes.
///
/// This lint whitelists `#[allow(unused_imports)]` and `#[allow(deprecated)]` on
/// `use` items and `#[allow(unused_imports)]` on `extern crate` items with a
/// `#[macro_use]` attribute.
///
/// **Why is this bad?** Lint attributes have no effect on crate imports. Most
/// likely a `!` was
/// forgotten
/// likely a `!` was forgotten.
///
/// **Known problems:** Technically one might allow `unused_import` on a `use`
/// item,
/// but it's easier to remove the unused item.
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// // Bad
/// #[deny(dead_code)]
/// extern crate foo;
/// #[allow(unused_import)]
/// #[forbid(dead_code)]
/// use foo::bar;
///
/// // Ok
/// #[allow(unused_imports)]
/// use foo::baz;
/// #[allow(unused_imports)]
/// #[macro_use]
/// extern crate baz;
/// ```
declare_clippy_lint! {
pub USELESS_ATTRIBUTE,
@ -154,17 +165,26 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass {
check_attrs(cx, item.span, item.name, &item.attrs)
}
match item.node {
ItemExternCrate(_) | ItemUse(_, _) => {
ItemKind::ExternCrate(..) | ItemKind::Use(..) => {
let skip_unused_imports = item.attrs.iter().any(|attr| attr.name() == "macro_use");
for attr in &item.attrs {
if let Some(ref lint_list) = attr.meta_item_list() {
match &*attr.name().as_str() {
"allow" | "warn" | "deny" | "forbid" => {
// whitelist `unused_imports` and `deprecated`
// whitelist `unused_imports` and `deprecated` for `use` items
// and `unused_imports` for `extern crate` items with `macro_use`
for lint in lint_list {
if is_word(lint, "unused_imports") || is_word(lint, "deprecated") {
if let ItemUse(_, _) = item.node {
return;
}
match item.node {
ItemKind::Use(..) => if is_word(lint, "unused_imports")
|| is_word(lint, "deprecated") {
return
},
ItemKind::ExternCrate(..) => if is_word(lint, "unused_imports")
&& skip_unused_imports {
return
},
_ => {},
}
}
let line_span = last_line_of_span(cx, attr.span);
@ -206,22 +226,22 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass {
}
}
fn is_relevant_item(tcx: TyCtxt, item: &Item) -> bool {
if let ItemFn(_, _, _, eid) = item.node {
fn is_relevant_item(tcx: TyCtxt<'_, '_, '_>, item: &Item) -> bool {
if let ItemKind::Fn(_, _, _, eid) = item.node {
is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value)
} else {
true
}
}
fn is_relevant_impl(tcx: TyCtxt, item: &ImplItem) -> bool {
fn is_relevant_impl(tcx: TyCtxt<'_, '_, '_>, item: &ImplItem) -> bool {
match item.node {
ImplItemKind::Method(_, eid) => is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value),
_ => false,
}
}
fn is_relevant_trait(tcx: TyCtxt, item: &TraitItem) -> bool {
fn is_relevant_trait(tcx: TyCtxt<'_, '_, '_>, item: &TraitItem) -> bool {
match item.node {
TraitItemKind::Method(_, TraitMethod::Required(_)) => true,
TraitItemKind::Method(_, TraitMethod::Provided(eid)) => {
@ -231,23 +251,23 @@ fn is_relevant_trait(tcx: TyCtxt, item: &TraitItem) -> bool {
}
}
fn is_relevant_block(tcx: TyCtxt, tables: &ty::TypeckTables, block: &Block) -> bool {
fn is_relevant_block(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, block: &Block) -> bool {
if let Some(stmt) = block.stmts.first() {
match stmt.node {
StmtDecl(_, _) => true,
StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => is_relevant_expr(tcx, tables, expr),
StmtKind::Decl(_, _) => true,
StmtKind::Expr(ref expr, _) | StmtKind::Semi(ref expr, _) => is_relevant_expr(tcx, tables, expr),
}
} else {
block.expr.as_ref().map_or(false, |e| is_relevant_expr(tcx, tables, e))
}
}
fn is_relevant_expr(tcx: TyCtxt, tables: &ty::TypeckTables, expr: &Expr) -> bool {
fn is_relevant_expr(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, expr: &Expr) -> bool {
match expr.node {
ExprBlock(ref block, _) => is_relevant_block(tcx, tables, block),
ExprRet(Some(ref e)) => is_relevant_expr(tcx, tables, e),
ExprRet(None) | ExprBreak(_, None) => false,
ExprCall(ref path_expr, _) => if let ExprPath(ref qpath) = path_expr.node {
ExprKind::Block(ref block, _) => is_relevant_block(tcx, tables, block),
ExprKind::Ret(Some(ref e)) => is_relevant_expr(tcx, tables, e),
ExprKind::Ret(None) | ExprKind::Break(_, None) => false,
ExprKind::Call(ref path_expr, _) => if let ExprKind::Path(ref qpath) = path_expr.node {
if let Some(fun_id) = opt_def_id(tables.qpath_def(qpath, path_expr.hir_id)) {
!match_def_path(tcx, fun_id, &paths::BEGIN_PANIC)
} else {
@ -260,7 +280,7 @@ fn is_relevant_expr(tcx: TyCtxt, tables: &ty::TypeckTables, expr: &Expr) -> bool
}
}
fn check_attrs(cx: &LateContext, span: Span, name: Name, attrs: &[Attribute]) {
fn check_attrs(cx: &LateContext<'_, '_>, span: Span, name: Name, attrs: &[Attribute]) {
if in_macro(span) {
return;
}
@ -311,7 +331,7 @@ fn check_attrs(cx: &LateContext, span: Span, name: Name, attrs: &[Attribute]) {
}
}
fn check_semver(cx: &LateContext, span: Span, lit: &Lit) {
fn check_semver(cx: &LateContext<'_, '_>, span: Span, lit: &Lit) {
if let LitKind::Str(ref is, _) = lit.node {
if Version::parse(&is.as_str()).is_ok() {
return;
@ -338,7 +358,7 @@ fn is_word(nmi: &NestedMetaItem, expected: &str) -> bool {
// sources that the user has no control over.
// For some reason these attributes don't have any expansion info on them, so
// we have to check it this way until there is a better way.
fn is_present_in_source(cx: &LateContext, span: Span) -> bool {
fn is_present_in_source(cx: &LateContext<'_, '_>, span: Span) -> bool {
if let Some(snippet) = snippet_opt(cx, span) {
if snippet.is_empty() {
return false;

View File

@ -1,5 +1,7 @@
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use syntax::ast::LitKind;
use syntax::codemap::Span;
use crate::utils::{span_lint, span_lint_and_then};
@ -109,7 +111,7 @@ impl LintPass for BitMask {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
if let ExprBinary(ref cmp, ref left, ref right) = e.node {
if let ExprKind::Binary(ref cmp, ref left, ref right) = e.node {
if cmp.node.is_comparison() {
if let Some(cmp_opt) = fetch_int_literal(cx, right) {
check_compare(cx, left, cmp.node, cmp_opt, e.span)
@ -119,13 +121,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask {
}
}
if_chain! {
if let Expr_::ExprBinary(ref op, ref left, ref right) = e.node;
if BinOp_::BiEq == op.node;
if let Expr_::ExprBinary(ref op1, ref left1, ref right1) = left.node;
if BinOp_::BiBitAnd == op1.node;
if let Expr_::ExprLit(ref lit) = right1.node;
if let ExprKind::Binary(ref op, ref left, ref right) = e.node;
if BinOpKind::Eq == op.node;
if let ExprKind::Binary(ref op1, ref left1, ref right1) = left.node;
if BinOpKind::BitAnd == op1.node;
if let ExprKind::Lit(ref lit) = right1.node;
if let LitKind::Int(n, _) = lit.node;
if let Expr_::ExprLit(ref lit1) = right.node;
if let ExprKind::Lit(ref lit1) = right.node;
if let LitKind::Int(0, _) = lit1.node;
if n.leading_zeros() == n.count_zeros();
if n > u128::from(self.verbose_bit_mask_threshold);
@ -143,22 +145,22 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask {
}
}
fn invert_cmp(cmp: BinOp_) -> BinOp_ {
fn invert_cmp(cmp: BinOpKind) -> BinOpKind {
match cmp {
BiEq => BiEq,
BiNe => BiNe,
BiLt => BiGt,
BiGt => BiLt,
BiLe => BiGe,
BiGe => BiLe,
_ => BiOr, // Dummy
BinOpKind::Eq => BinOpKind::Eq,
BinOpKind::Ne => BinOpKind::Ne,
BinOpKind::Lt => BinOpKind::Gt,
BinOpKind::Gt => BinOpKind::Lt,
BinOpKind::Le => BinOpKind::Ge,
BinOpKind::Ge => BinOpKind::Le,
_ => BinOpKind::Or, // Dummy
}
}
fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u128, span: Span) {
if let ExprBinary(ref op, ref left, ref right) = bit_op.node {
if op.node != BiBitAnd && op.node != BiBitOr {
fn check_compare(cx: &LateContext<'_, '_>, bit_op: &Expr, cmp_op: BinOpKind, cmp_value: u128, span: Span) {
if let ExprKind::Binary(ref op, ref left, ref right) = bit_op.node {
if op.node != BinOpKind::BitAnd && op.node != BinOpKind::BitOr {
return;
}
fetch_int_literal(cx, right)
@ -167,10 +169,10 @@ fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u12
}
}
fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u128, cmp_value: u128, span: Span) {
fn check_bit_mask(cx: &LateContext<'_, '_>, bit_op: BinOpKind, cmp_op: BinOpKind, mask_value: u128, cmp_value: u128, span: Span) {
match cmp_op {
BiEq | BiNe => match bit_op {
BiBitAnd => if mask_value & cmp_value != cmp_value {
BinOpKind::Eq | BinOpKind::Ne => match bit_op {
BinOpKind::BitAnd => if mask_value & cmp_value != cmp_value {
if cmp_value != 0 {
span_lint(
cx,
@ -186,7 +188,7 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value:
} else if mask_value == 0 {
span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero");
},
BiBitOr => if mask_value | cmp_value != cmp_value {
BinOpKind::BitOr => if mask_value | cmp_value != cmp_value {
span_lint(
cx,
BAD_BIT_MASK,
@ -200,8 +202,8 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value:
},
_ => (),
},
BiLt | BiGe => match bit_op {
BiBitAnd => if mask_value < cmp_value {
BinOpKind::Lt | BinOpKind::Ge => match bit_op {
BinOpKind::BitAnd => if mask_value < cmp_value {
span_lint(
cx,
BAD_BIT_MASK,
@ -215,7 +217,7 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value:
} else if mask_value == 0 {
span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero");
},
BiBitOr => if mask_value >= cmp_value {
BinOpKind::BitOr => if mask_value >= cmp_value {
span_lint(
cx,
BAD_BIT_MASK,
@ -229,11 +231,11 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value:
} else {
check_ineffective_lt(cx, span, mask_value, cmp_value, "|");
},
BiBitXor => check_ineffective_lt(cx, span, mask_value, cmp_value, "^"),
BinOpKind::BitXor => check_ineffective_lt(cx, span, mask_value, cmp_value, "^"),
_ => (),
},
BiLe | BiGt => match bit_op {
BiBitAnd => if mask_value <= cmp_value {
BinOpKind::Le | BinOpKind::Gt => match bit_op {
BinOpKind::BitAnd => if mask_value <= cmp_value {
span_lint(
cx,
BAD_BIT_MASK,
@ -247,7 +249,7 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value:
} else if mask_value == 0 {
span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero");
},
BiBitOr => if mask_value > cmp_value {
BinOpKind::BitOr => if mask_value > cmp_value {
span_lint(
cx,
BAD_BIT_MASK,
@ -261,14 +263,14 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value:
} else {
check_ineffective_gt(cx, span, mask_value, cmp_value, "|");
},
BiBitXor => check_ineffective_gt(cx, span, mask_value, cmp_value, "^"),
BinOpKind::BitXor => check_ineffective_gt(cx, span, mask_value, cmp_value, "^"),
_ => (),
},
_ => (),
}
}
fn check_ineffective_lt(cx: &LateContext, span: Span, m: u128, c: u128, op: &str) {
fn check_ineffective_lt(cx: &LateContext<'_, '_>, span: Span, m: u128, c: u128, op: &str) {
if c.is_power_of_two() && m < c {
span_lint(
cx,
@ -284,7 +286,7 @@ fn check_ineffective_lt(cx: &LateContext, span: Span, m: u128, c: u128, op: &str
}
}
fn check_ineffective_gt(cx: &LateContext, span: Span, m: u128, c: u128, op: &str) {
fn check_ineffective_gt(cx: &LateContext<'_, '_>, span: Span, m: u128, c: u128, op: &str) {
if (c + 1).is_power_of_two() && m <= c {
span_lint(
cx,
@ -300,7 +302,7 @@ fn check_ineffective_gt(cx: &LateContext, span: Span, m: u128, c: u128, op: &str
}
}
fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u128> {
fn fetch_int_literal(cx: &LateContext<'_, '_>, lit: &Expr) -> Option<u128> {
match constant(cx, cx.tables, lit)?.0 {
Constant::Int(n) => Some(n),
_ => None,

View File

@ -1,4 +1,5 @@
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::hir::*;
use crate::utils::span_lint;

View File

@ -1,4 +1,6 @@
use matches::matches;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint, lint_array};
use rustc::hir::*;
use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use crate::utils::*;
@ -56,10 +58,10 @@ struct ExVisitor<'a, 'tcx: 'a> {
impl<'a, 'tcx: 'a> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr) {
if let ExprClosure(_, _, eid, _, _) = expr.node {
if let ExprKind::Closure(_, _, eid, _, _) = expr.node {
let body = self.cx.tcx.hir.body(eid);
let ex = &body.value;
if matches!(ex.node, ExprBlock(_, _)) {
if matches!(ex.node, ExprKind::Block(_, _)) {
self.found_block = Some(ex);
return;
}
@ -77,8 +79,8 @@ const COMPLEX_BLOCK_MESSAGE: &str = "in an 'if' condition, avoid complex blocks
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let ExprIf(ref check, ref then, _) = expr.node {
if let ExprBlock(ref block, _) = check.node {
if let ExprKind::If(ref check, ref then, _) = expr.node {
if let ExprKind::Block(ref block, _) = check.node {
if block.rules == DefaultBlock {
if block.stmts.is_empty() {
if let Some(ref ex) = block.expr {

View File

@ -1,4 +1,5 @@
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint, lint_array};
use rustc::hir::*;
use rustc::hir::intravisit::*;
use syntax::ast::{LitKind, NodeId, DUMMY_NODE_ID};
@ -84,9 +85,9 @@ struct Hir2Qmm<'a, 'tcx: 'a, 'v> {
}
impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> {
fn extract(&mut self, op: BinOp_, a: &[&'v Expr], mut v: Vec<Bool>) -> Result<Vec<Bool>, String> {
fn extract(&mut self, op: BinOpKind, a: &[&'v Expr], mut v: Vec<Bool>) -> Result<Vec<Bool>, String> {
for a in a {
if let ExprBinary(binop, ref lhs, ref rhs) = a.node {
if let ExprKind::Binary(binop, ref lhs, ref rhs) = a.node {
if binop.node == op {
v = self.extract(op, &[lhs, rhs], v)?;
continue;
@ -101,13 +102,13 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> {
// prevent folding of `cfg!` macros and the like
if !in_macro(e.span) {
match e.node {
ExprUnary(UnNot, ref inner) => return Ok(Bool::Not(box self.run(inner)?)),
ExprBinary(binop, ref lhs, ref rhs) => match binop.node {
BiOr => return Ok(Bool::Or(self.extract(BiOr, &[lhs, rhs], Vec::new())?)),
BiAnd => return Ok(Bool::And(self.extract(BiAnd, &[lhs, rhs], Vec::new())?)),
ExprKind::Unary(UnNot, ref inner) => return Ok(Bool::Not(box self.run(inner)?)),
ExprKind::Binary(binop, ref lhs, ref rhs) => match binop.node {
BinOpKind::Or => return Ok(Bool::Or(self.extract(BinOpKind::Or, &[lhs, rhs], Vec::new())?)),
BinOpKind::And => return Ok(Bool::And(self.extract(BinOpKind::And, &[lhs, rhs], Vec::new())?)),
_ => (),
},
ExprLit(ref lit) => match lit.node {
ExprKind::Lit(ref lit) => match lit.node {
LitKind::Bool(true) => return Ok(Bool::True),
LitKind::Bool(false) => return Ok(Bool::False),
_ => (),
@ -121,8 +122,8 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> {
return Ok(Bool::Term(n as u8));
}
let negated = match e.node {
ExprBinary(binop, ref lhs, ref rhs) => {
ExprKind::Binary(binop, ref lhs, ref rhs) => {
if !implements_ord(self.cx, lhs) {
continue;
}
@ -133,16 +134,16 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> {
hir_id: DUMMY_HIR_ID,
span: DUMMY_SP,
attrs: ThinVec::new(),
node: ExprBinary(dummy_spanned(op), lhs.clone(), rhs.clone()),
node: ExprKind::Binary(dummy_spanned(op), lhs.clone(), rhs.clone()),
}
};
match binop.node {
BiEq => mk_expr(BiNe),
BiNe => mk_expr(BiEq),
BiGt => mk_expr(BiLe),
BiGe => mk_expr(BiLt),
BiLt => mk_expr(BiGe),
BiLe => mk_expr(BiGt),
BinOpKind::Eq => mk_expr(BinOpKind::Ne),
BinOpKind::Ne => mk_expr(BinOpKind::Eq),
BinOpKind::Gt => mk_expr(BinOpKind::Le),
BinOpKind::Ge => mk_expr(BinOpKind::Lt),
BinOpKind::Lt => mk_expr(BinOpKind::Ge),
BinOpKind::Le => mk_expr(BinOpKind::Gt),
_ => continue,
}
},
@ -178,23 +179,23 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> {
fn simplify_not(&self, expr: &Expr) -> Option<String> {
match expr.node {
ExprBinary(binop, ref lhs, ref rhs) => {
ExprKind::Binary(binop, ref lhs, ref rhs) => {
if !implements_ord(self.cx, lhs) {
return None;
}
match binop.node {
BiEq => Some(" != "),
BiNe => Some(" == "),
BiLt => Some(" >= "),
BiGt => Some(" <= "),
BiLe => Some(" > "),
BiGe => Some(" < "),
BinOpKind::Eq => Some(" != "),
BinOpKind::Ne => Some(" == "),
BinOpKind::Lt => Some(" >= "),
BinOpKind::Gt => Some(" <= "),
BinOpKind::Le => Some(" > "),
BinOpKind::Ge => Some(" < "),
_ => None,
}.and_then(|op| Some(format!("{}{}{}", self.snip(lhs)?, op, self.snip(rhs)?)))
},
ExprMethodCall(ref path, _, ref args) if args.len() == 1 => {
ExprKind::MethodCall(ref path, _, ref args) if args.len() == 1 => {
let type_of_receiver = self.cx.tables.expr_ty(&args[0]);
if !match_type(self.cx, type_of_receiver, &paths::OPTION) &&
!match_type(self.cx, type_of_receiver, &paths::RESULT) {
@ -274,7 +275,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> {
}
// The boolean part of the return indicates whether some simplifications have been applied.
fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> (String, bool) {
fn suggest(cx: &LateContext<'_, '_>, suggestion: &Bool, terminals: &[&Expr]) -> (String, bool) {
let mut suggest_context = SuggestContext {
terminals,
cx,
@ -441,8 +442,8 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
return;
}
match e.node {
ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e),
ExprUnary(UnNot, ref inner) => if self.cx.tables.node_types()[inner.hir_id].is_bool() {
ExprKind::Binary(binop, _, _) if binop.node == BinOpKind::Or || binop.node == BinOpKind::And => self.bool_expr(e),
ExprKind::Unary(UnNot, ref inner) => if self.cx.tables.node_types()[inner.hir_id].is_bool() {
self.bool_expr(e);
} else {
walk_expr(self, e);

View File

@ -1,5 +1,7 @@
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::ty;
use syntax::ast::{Name, UintTy};
use crate::utils::{contains_name, get_pat_name, match_type, paths, single_segment_path, snippet, span_lint_and_sugg,
@ -36,22 +38,22 @@ impl LintPass for ByteCount {
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr) {
if_chain! {
if let ExprMethodCall(ref count, _, ref count_args) = expr.node;
if let ExprKind::MethodCall(ref count, _, ref count_args) = expr.node;
if count.ident.name == "count";
if count_args.len() == 1;
if let ExprMethodCall(ref filter, _, ref filter_args) = count_args[0].node;
if let ExprKind::MethodCall(ref filter, _, ref filter_args) = count_args[0].node;
if filter.ident.name == "filter";
if filter_args.len() == 2;
if let ExprClosure(_, _, body_id, _, _) = filter_args[1].node;
if let ExprKind::Closure(_, _, body_id, _, _) = filter_args[1].node;
then {
let body = cx.tcx.hir.body(body_id);
if_chain! {
if body.arguments.len() == 1;
if let Some(argname) = get_pat_name(&body.arguments[0].pat);
if let ExprBinary(ref op, ref l, ref r) = body.value.node;
if op.node == BiEq;
if let ExprKind::Binary(ref op, ref l, ref r) = body.value.node;
if op.node == BinOpKind::Eq;
if match_type(cx,
walk_ptrs_ty(cx.tables.expr_ty(&filter_args[0])),
&paths::SLICE_ITER);
@ -66,7 +68,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount {
if ty::TyUint(UintTy::U8) != walk_ptrs_ty(cx.tables.expr_ty(needle)).sty {
return;
}
let haystack = if let ExprMethodCall(ref path, _, ref args) =
let haystack = if let ExprKind::MethodCall(ref path, _, ref args) =
filter_args[0].node {
let p = path.ident.name;
if (p == "iter" || p == "iter_mut") && args.len() == 1 {
@ -98,13 +100,13 @@ fn check_arg(name: Name, arg: Name, needle: &Expr) -> bool {
fn get_path_name(expr: &Expr) -> Option<Name> {
match expr.node {
ExprBox(ref e) | ExprAddrOf(_, ref e) | ExprUnary(UnOp::UnDeref, ref e) => get_path_name(e),
ExprBlock(ref b, _) => if b.stmts.is_empty() {
ExprKind::Box(ref e) | ExprKind::AddrOf(_, ref e) | ExprKind::Unary(UnOp::UnDeref, ref e) => get_path_name(e),
ExprKind::Block(ref b, _) => if b.stmts.is_empty() {
b.expr.as_ref().and_then(|p| get_path_name(p))
} else {
None
},
ExprPath(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name),
ExprKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name),
_ => None,
}
}

View File

@ -13,6 +13,8 @@
//! This lint is **warn** by default
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use syntax::ast;
use crate::utils::{in_macro, snippet_block, span_lint_and_sugg, span_lint_and_then};
@ -78,14 +80,14 @@ impl LintPass for CollapsibleIf {
}
impl EarlyLintPass for CollapsibleIf {
fn check_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr) {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
if !in_macro(expr.span) {
check_if(cx, expr)
}
}
}
fn check_if(cx: &EarlyContext, expr: &ast::Expr) {
fn check_if(cx: &EarlyContext<'_>, expr: &ast::Expr) {
match expr.node {
ast::ExprKind::If(ref check, ref then, ref else_) => if let Some(ref else_) = *else_ {
check_collapsible_maybe_if_let(cx, else_);
@ -99,7 +101,7 @@ fn check_if(cx: &EarlyContext, expr: &ast::Expr) {
}
}
fn check_collapsible_maybe_if_let(cx: &EarlyContext, else_: &ast::Expr) {
fn check_collapsible_maybe_if_let(cx: &EarlyContext<'_>, else_: &ast::Expr) {
if_chain! {
if let ast::ExprKind::Block(ref block, _) = else_.node;
if let Some(else_) = expr_block(block);
@ -120,7 +122,7 @@ fn check_collapsible_maybe_if_let(cx: &EarlyContext, else_: &ast::Expr) {
}
}
fn check_collapsible_no_if_let(cx: &EarlyContext, expr: &ast::Expr, check: &ast::Expr, then: &ast::Block) {
fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: &ast::Expr, then: &ast::Block) {
if_chain! {
if let Some(inner) = expr_block(then);
if let ast::ExprKind::If(ref check_inner, ref content, None) = inner.node;

View File

@ -1,5 +1,6 @@
use syntax::ast::*;
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use rustc::{declare_lint, lint_array};
use crate::utils::{in_macro, snippet, span_lint_and_then};
/// **What it does:** Checks for constants with an explicit `'static` lifetime.
@ -34,7 +35,7 @@ impl LintPass for StaticConst {
impl StaticConst {
// Recursively visit types
fn visit_type(&mut self, ty: &Ty, cx: &EarlyContext) {
fn visit_type(&mut self, ty: &Ty, cx: &EarlyContext<'_>) {
match ty.node {
// Be careful of nested structures (arrays and tuples)
TyKind::Array(ref ty, _) => {
@ -78,7 +79,7 @@ impl StaticConst {
}
impl EarlyLintPass for StaticConst {
fn check_item(&mut self, cx: &EarlyContext, item: &Item) {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
if !in_macro(item.span) {
// Match only constants...
if let ItemKind::Const(ref var_type, _) = item.node {

View File

@ -2,6 +2,7 @@
#![allow(float_cmp)]
use rustc::lint::LateContext;
use rustc::{span_bug, bug};
use rustc::hir::def::Def;
use rustc::hir::*;
use rustc::ty::{self, Ty, TyCtxt, Instance};
@ -13,7 +14,6 @@ use std::mem;
use std::rc::Rc;
use syntax::ast::{FloatTy, LitKind};
use syntax::ptr::P;
use rustc::middle::const_val::ConstVal;
use crate::utils::{sext, unsext, clip};
#[derive(Debug, Copy, Clone)]
@ -123,7 +123,7 @@ impl Hash for Constant {
}
impl Constant {
pub fn partial_cmp(tcx: TyCtxt, cmp_type: &ty::TypeVariants, left: &Self, right: &Self) -> Option<Ordering> {
pub fn partial_cmp(tcx: TyCtxt<'_, '_, '_>, cmp_type: &ty::TypeVariants<'_>, left: &Self, right: &Self) -> Option<Ordering> {
match (left, right) {
(&Constant::Str(ref ls), &Constant::Str(ref rs)) => Some(ls.cmp(rs)),
(&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)),
@ -212,31 +212,31 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
/// simple constant folding: Insert an expression, get a constant or none.
pub fn expr(&mut self, e: &Expr) -> Option<Constant> {
match e.node {
ExprPath(ref qpath) => self.fetch_path(qpath, e.hir_id),
ExprBlock(ref block, _) => self.block(block),
ExprIf(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, otherwise),
ExprLit(ref lit) => Some(lit_to_constant(&lit.node, self.tables.expr_ty(e))),
ExprArray(ref vec) => self.multi(vec).map(Constant::Vec),
ExprTup(ref tup) => self.multi(tup).map(Constant::Tuple),
ExprRepeat(ref value, _) => {
ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id),
ExprKind::Block(ref block, _) => self.block(block),
ExprKind::If(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, otherwise),
ExprKind::Lit(ref lit) => Some(lit_to_constant(&lit.node, self.tables.expr_ty(e))),
ExprKind::Array(ref vec) => self.multi(vec).map(Constant::Vec),
ExprKind::Tup(ref tup) => self.multi(tup).map(Constant::Tuple),
ExprKind::Repeat(ref value, _) => {
let n = match self.tables.expr_ty(e).sty {
ty::TyArray(_, n) => n.assert_usize(self.tcx).expect("array length"),
_ => span_bug!(e.span, "typeck error"),
};
self.expr(value).map(|v| Constant::Repeat(Box::new(v), n as u64))
},
ExprUnary(op, ref operand) => self.expr(operand).and_then(|o| match op {
ExprKind::Unary(op, ref operand) => self.expr(operand).and_then(|o| match op {
UnNot => self.constant_not(&o, self.tables.expr_ty(e)),
UnNeg => self.constant_negate(&o, self.tables.expr_ty(e)),
UnDeref => Some(o),
}),
ExprBinary(op, ref left, ref right) => self.binop(op, left, right),
ExprKind::Binary(op, ref left, ref right) => self.binop(op, left, right),
// TODO: add other expressions
_ => None,
}
}
fn constant_not(&self, o: &Constant, ty: ty::Ty) -> Option<Constant> {
fn constant_not(&self, o: &Constant, ty: ty::Ty<'_>) -> Option<Constant> {
use self::Constant::*;
match *o {
Bool(b) => Some(Bool(!b)),
@ -252,7 +252,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
}
}
fn constant_negate(&self, o: &Constant, ty: ty::Ty) -> Option<Constant> {
fn constant_negate(&self, o: &Constant, ty: ty::Ty<'_>) -> Option<Constant> {
use self::Constant::*;
match *o {
Int(value) => {
@ -280,7 +280,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
.collect::<Option<_>>()
}
/// lookup a possibly constant expression from a ExprPath
/// lookup a possibly constant expression from a ExprKind::Path
fn fetch_path(&mut self, qpath: &QPath, id: HirId) -> Option<Constant> {
let def = self.tables.qpath_def(qpath, id);
match def {
@ -341,43 +341,43 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
let r = sext(self.tcx, r, ity);
let zext = |n: i128| Constant::Int(unsext(self.tcx, n, ity));
match op.node {
BiAdd => l.checked_add(r).map(zext),
BiSub => l.checked_sub(r).map(zext),
BiMul => l.checked_mul(r).map(zext),
BiDiv if r != 0 => l.checked_div(r).map(zext),
BiRem if r != 0 => l.checked_rem(r).map(zext),
BiShr => l.checked_shr(r as u128 as u32).map(zext),
BiShl => l.checked_shl(r as u128 as u32).map(zext),
BiBitXor => Some(zext(l ^ r)),
BiBitOr => Some(zext(l | r)),
BiBitAnd => Some(zext(l & r)),
BiEq => Some(Constant::Bool(l == r)),
BiNe => Some(Constant::Bool(l != r)),
BiLt => Some(Constant::Bool(l < r)),
BiLe => Some(Constant::Bool(l <= r)),
BiGe => Some(Constant::Bool(l >= r)),
BiGt => Some(Constant::Bool(l > r)),
BinOpKind::Add => l.checked_add(r).map(zext),
BinOpKind::Sub => l.checked_sub(r).map(zext),
BinOpKind::Mul => l.checked_mul(r).map(zext),
BinOpKind::Div if r != 0 => l.checked_div(r).map(zext),
BinOpKind::Rem if r != 0 => l.checked_rem(r).map(zext),
BinOpKind::Shr => l.checked_shr(r as u128 as u32).map(zext),
BinOpKind::Shl => l.checked_shl(r as u128 as u32).map(zext),
BinOpKind::BitXor => Some(zext(l ^ r)),
BinOpKind::BitOr => Some(zext(l | r)),
BinOpKind::BitAnd => Some(zext(l & r)),
BinOpKind::Eq => Some(Constant::Bool(l == r)),
BinOpKind::Ne => Some(Constant::Bool(l != r)),
BinOpKind::Lt => Some(Constant::Bool(l < r)),
BinOpKind::Le => Some(Constant::Bool(l <= r)),
BinOpKind::Ge => Some(Constant::Bool(l >= r)),
BinOpKind::Gt => Some(Constant::Bool(l > r)),
_ => None,
}
}
ty::TyUint(_) => {
match op.node {
BiAdd => l.checked_add(r).map(Constant::Int),
BiSub => l.checked_sub(r).map(Constant::Int),
BiMul => l.checked_mul(r).map(Constant::Int),
BiDiv => l.checked_div(r).map(Constant::Int),
BiRem => l.checked_rem(r).map(Constant::Int),
BiShr => l.checked_shr(r as u32).map(Constant::Int),
BiShl => l.checked_shl(r as u32).map(Constant::Int),
BiBitXor => Some(Constant::Int(l ^ r)),
BiBitOr => Some(Constant::Int(l | r)),
BiBitAnd => Some(Constant::Int(l & r)),
BiEq => Some(Constant::Bool(l == r)),
BiNe => Some(Constant::Bool(l != r)),
BiLt => Some(Constant::Bool(l < r)),
BiLe => Some(Constant::Bool(l <= r)),
BiGe => Some(Constant::Bool(l >= r)),
BiGt => Some(Constant::Bool(l > r)),
BinOpKind::Add => l.checked_add(r).map(Constant::Int),
BinOpKind::Sub => l.checked_sub(r).map(Constant::Int),
BinOpKind::Mul => l.checked_mul(r).map(Constant::Int),
BinOpKind::Div => l.checked_div(r).map(Constant::Int),
BinOpKind::Rem => l.checked_rem(r).map(Constant::Int),
BinOpKind::Shr => l.checked_shr(r as u32).map(Constant::Int),
BinOpKind::Shl => l.checked_shl(r as u32).map(Constant::Int),
BinOpKind::BitXor => Some(Constant::Int(l ^ r)),
BinOpKind::BitOr => Some(Constant::Int(l | r)),
BinOpKind::BitAnd => Some(Constant::Int(l & r)),
BinOpKind::Eq => Some(Constant::Bool(l == r)),
BinOpKind::Ne => Some(Constant::Bool(l != r)),
BinOpKind::Lt => Some(Constant::Bool(l < r)),
BinOpKind::Le => Some(Constant::Bool(l <= r)),
BinOpKind::Ge => Some(Constant::Bool(l >= r)),
BinOpKind::Gt => Some(Constant::Bool(l > r)),
_ => None,
}
},
@ -385,40 +385,40 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
}
},
(Constant::F32(l), Some(Constant::F32(r))) => match op.node {
BiAdd => Some(Constant::F32(l + r)),
BiSub => Some(Constant::F32(l - r)),
BiMul => Some(Constant::F32(l * r)),
BiDiv => Some(Constant::F32(l / r)),
BiRem => Some(Constant::F32(l % r)),
BiEq => Some(Constant::Bool(l == r)),
BiNe => Some(Constant::Bool(l != r)),
BiLt => Some(Constant::Bool(l < r)),
BiLe => Some(Constant::Bool(l <= r)),
BiGe => Some(Constant::Bool(l >= r)),
BiGt => Some(Constant::Bool(l > r)),
BinOpKind::Add => Some(Constant::F32(l + r)),
BinOpKind::Sub => Some(Constant::F32(l - r)),
BinOpKind::Mul => Some(Constant::F32(l * r)),
BinOpKind::Div => Some(Constant::F32(l / r)),
BinOpKind::Rem => Some(Constant::F32(l % r)),
BinOpKind::Eq => Some(Constant::Bool(l == r)),
BinOpKind::Ne => Some(Constant::Bool(l != r)),
BinOpKind::Lt => Some(Constant::Bool(l < r)),
BinOpKind::Le => Some(Constant::Bool(l <= r)),
BinOpKind::Ge => Some(Constant::Bool(l >= r)),
BinOpKind::Gt => Some(Constant::Bool(l > r)),
_ => None,
},
(Constant::F64(l), Some(Constant::F64(r))) => match op.node {
BiAdd => Some(Constant::F64(l + r)),
BiSub => Some(Constant::F64(l - r)),
BiMul => Some(Constant::F64(l * r)),
BiDiv => Some(Constant::F64(l / r)),
BiRem => Some(Constant::F64(l % r)),
BiEq => Some(Constant::Bool(l == r)),
BiNe => Some(Constant::Bool(l != r)),
BiLt => Some(Constant::Bool(l < r)),
BiLe => Some(Constant::Bool(l <= r)),
BiGe => Some(Constant::Bool(l >= r)),
BiGt => Some(Constant::Bool(l > r)),
BinOpKind::Add => Some(Constant::F64(l + r)),
BinOpKind::Sub => Some(Constant::F64(l - r)),
BinOpKind::Mul => Some(Constant::F64(l * r)),
BinOpKind::Div => Some(Constant::F64(l / r)),
BinOpKind::Rem => Some(Constant::F64(l % r)),
BinOpKind::Eq => Some(Constant::Bool(l == r)),
BinOpKind::Ne => Some(Constant::Bool(l != r)),
BinOpKind::Lt => Some(Constant::Bool(l < r)),
BinOpKind::Le => Some(Constant::Bool(l <= r)),
BinOpKind::Ge => Some(Constant::Bool(l >= r)),
BinOpKind::Gt => Some(Constant::Bool(l > r)),
_ => None,
},
(l, r) => match (op.node, l, r) {
(BiAnd, Constant::Bool(false), _) => Some(Constant::Bool(false)),
(BiOr, Constant::Bool(true), _) => Some(Constant::Bool(true)),
(BiAnd, Constant::Bool(true), Some(r)) | (BiOr, Constant::Bool(false), Some(r)) => Some(r),
(BiBitXor, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l ^ r)),
(BiBitAnd, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l & r)),
(BiBitOr, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l | r)),
(BinOpKind::And, Constant::Bool(false), _) => Some(Constant::Bool(false)),
(BinOpKind::Or, Constant::Bool(true), _) => Some(Constant::Bool(true)),
(BinOpKind::And, Constant::Bool(true), Some(r)) | (BinOpKind::Or, Constant::Bool(false), Some(r)) => Some(r),
(BinOpKind::BitXor, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l ^ r)),
(BinOpKind::BitAnd, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l & r)),
(BinOpKind::BitOr, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l | r)),
_ => None,
},
}
@ -428,7 +428,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<'tcx>) -> Option<Constant> {
use rustc::mir::interpret::{Scalar, ConstValue};
match result.val {
ConstVal::Value(ConstValue::Scalar(Scalar::Bits{ bits: b, ..})) => match result.ty.sty {
ConstValue::Scalar(Scalar::Bits{ bits: b, ..}) => match result.ty.sty {
ty::TyBool => Some(Constant::Bool(b == 1)),
ty::TyUint(_) | ty::TyInt(_) => Some(Constant::Int(b)),
ty::TyFloat(FloatTy::F32) => Some(Constant::F32(f32::from_bits(b as u32))),
@ -436,7 +436,7 @@ pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<'
// FIXME: implement other conversion
_ => None,
},
ConstVal::Value(ConstValue::ScalarPair(Scalar::Ptr(ptr), Scalar::Bits { bits: n, .. })) => match result.ty.sty {
ConstValue::ScalarPair(Scalar::Ptr(ptr), Scalar::Bits { bits: n, .. }) => match result.ty.sty {
ty::TyRef(_, tam, _) => match tam.sty {
ty::TyStr => {
let alloc = tcx

View File

@ -1,4 +1,5 @@
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::ty::Ty;
use rustc::hir::*;
use std::collections::HashMap;
@ -115,7 +116,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyAndPaste {
if !in_macro(expr.span) {
// skip ifs directly in else, it will be checked in the parent if
if let Some(&Expr {
node: ExprIf(_, _, Some(ref else_expr)),
node: ExprKind::If(_, _, Some(ref else_expr)),
..
}) = get_parent_expr(cx, expr)
{
@ -133,7 +134,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyAndPaste {
}
/// Implementation of `IF_SAME_THEN_ELSE`.
fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) {
fn lint_same_then_else(cx: &LateContext<'_, '_>, blocks: &[&Block]) {
let eq: &dyn Fn(&&Block, &&Block) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).eq_block(lhs, rhs) };
if let Some((i, j)) = search_same_sequenced(blocks, eq) {
@ -149,7 +150,7 @@ fn lint_same_then_else(cx: &LateContext, blocks: &[&Block]) {
}
/// Implementation of `IFS_SAME_COND`.
fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) {
fn lint_same_cond(cx: &LateContext<'_, '_>, conds: &[&Expr]) {
let hash: &dyn Fn(&&Expr) -> u64 = &|expr| -> u64 {
let mut h = SpanlessHash::new(cx, cx.tables);
h.hash_expr(expr);
@ -171,8 +172,8 @@ fn lint_same_cond(cx: &LateContext, conds: &[&Expr]) {
}
/// Implementation of `MATCH_SAME_ARMS`.
fn lint_match_arms(cx: &LateContext, expr: &Expr) {
if let ExprMatch(_, ref arms, MatchSource::Normal) = expr.node {
fn lint_match_arms(cx: &LateContext<'_, '_>, expr: &Expr) {
if let ExprKind::Match(_, ref arms, MatchSource::Normal) = expr.node {
let hash = |&(_, arm): &(usize, &Arm)| -> u64 {
let mut h = SpanlessHash::new(cx, cx.tables);
h.hash_expr(&arm.body);
@ -236,12 +237,12 @@ fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) {
let mut conds = SmallVector::new();
let mut blocks: SmallVector<&Block> = SmallVector::new();
while let ExprIf(ref cond, ref then_expr, ref else_expr) = expr.node {
while let ExprKind::If(ref cond, ref then_expr, ref else_expr) = expr.node {
conds.push(&**cond);
if let ExprBlock(ref block, _) = then_expr.node {
if let ExprKind::Block(ref block, _) = then_expr.node {
blocks.push(block);
} else {
panic!("ExprIf node is not an ExprBlock");
panic!("ExprKind::If node is not an ExprKind::Block");
}
if let Some(ref else_expr) = *else_expr {
@ -253,7 +254,7 @@ fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) {
// final `else {..}`
if !blocks.is_empty() {
if let ExprBlock(ref block, _) = expr.node {
if let ExprKind::Block(ref block, _) = expr.node {
blocks.push(&**block);
}
}

View File

@ -2,6 +2,7 @@
use rustc::cfg::CFG;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::hir::*;
use rustc::ty;
use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
@ -147,14 +148,14 @@ struct CCHelper<'a, 'tcx: 'a> {
impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> {
fn visit_expr(&mut self, e: &'tcx Expr) {
match e.node {
ExprMatch(_, ref arms, _) => {
ExprKind::Match(_, ref arms, _) => {
walk_expr(self, e);
let arms_n: u64 = arms.iter().map(|arm| arm.pats.len() as u64).sum();
if arms_n > 1 {
self.match_arms += arms_n - 2;
}
},
ExprCall(ref callee, _) => {
ExprKind::Call(ref callee, _) => {
walk_expr(self, e);
let ty = self.cx.tables.node_id_to_type(callee.hir_id);
match ty.sty {
@ -167,15 +168,15 @@ impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> {
_ => (),
}
},
ExprClosure(.., _) => (),
ExprBinary(op, _, _) => {
ExprKind::Closure(.., _) => (),
ExprKind::Binary(op, _, _) => {
walk_expr(self, e);
match op.node {
BiAnd | BiOr => self.short_circuits += 1,
BinOpKind::And | BinOpKind::Or => self.short_circuits += 1,
_ => (),
}
},
ExprRet(_) => self.returns += 1,
ExprKind::Ret(_) => self.returns += 1,
_ => walk_expr(self, e),
}
}
@ -186,7 +187,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> {
#[cfg(feature = "debugging")]
#[allow(too_many_arguments)]
fn report_cc_bug(_: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span, _: NodeId) {
fn report_cc_bug(_: &LateContext<'_, '_>, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span, _: NodeId) {
span_bug!(
span,
"Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \
@ -200,7 +201,7 @@ fn report_cc_bug(_: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, re
}
#[cfg(not(feature = "debugging"))]
#[allow(too_many_arguments)]
fn report_cc_bug(cx: &LateContext, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span, id: NodeId) {
fn report_cc_bug(cx: &LateContext<'_, '_>, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span, id: NodeId) {
if !is_allowed(cx, CYCLOMATIC_COMPLEXITY, id) {
cx.sess().span_note_without_error(
span,

View File

@ -1,5 +1,7 @@
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::ty::TypeVariants;
use crate::utils::{any_parent_is_automatically_derived, match_def_path, opt_def_id, paths, span_lint_and_sugg};
@ -38,9 +40,9 @@ impl LintPass for DefaultTraitAccess {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if_chain! {
if let ExprCall(ref path, ..) = expr.node;
if let ExprKind::Call(ref path, ..) = expr.node;
if !any_parent_is_automatically_derived(cx.tcx, expr.id);
if let ExprPath(ref qpath) = path.node;
if let ExprKind::Path(ref qpath) = path.node;
if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id));
if match_def_path(cx.tcx, def_id, &paths::DEFAULT_TRAIT_METHOD);
then {

View File

@ -1,4 +1,6 @@
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::ty::{self, Ty};
use rustc::hir::*;
use syntax::codemap::Span;
@ -70,7 +72,7 @@ impl LintPass for Derive {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Derive {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if let ItemImpl(_, _, _, _, Some(ref trait_ref), _, _) = item.node {
if let ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, _) = item.node {
let ty = cx.tcx.type_of(cx.tcx.hir.local_def_id(item.id));
let is_automatically_derived = is_automatically_derived(&*item.attrs);

View File

@ -1,6 +1,7 @@
use itertools::Itertools;
use pulldown_cmark;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use syntax::ast;
use syntax::codemap::{BytePos, Span};
use syntax_pos::Pos;
@ -51,11 +52,11 @@ impl LintPass for Doc {
}
impl EarlyLintPass for Doc {
fn check_crate(&mut self, cx: &EarlyContext, krate: &ast::Crate) {
fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) {
check_attrs(cx, &self.valid_idents, &krate.attrs);
}
fn check_item(&mut self, cx: &EarlyContext, item: &ast::Item) {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
check_attrs(cx, &self.valid_idents, &item.attrs);
}
}
@ -138,7 +139,7 @@ pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<(
panic!("not a doc-comment: {}", comment);
}
pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [ast::Attribute]) {
pub fn check_attrs<'a>(cx: &EarlyContext<'_>, valid_idents: &[String], attrs: &'a [ast::Attribute]) {
let mut doc = String::new();
let mut spans = vec![];
@ -185,7 +186,7 @@ pub fn check_attrs<'a>(cx: &EarlyContext, valid_idents: &[String], attrs: &'a [a
}
fn check_doc<'a, Events: Iterator<Item = (usize, pulldown_cmark::Event<'a>)>>(
cx: &EarlyContext,
cx: &EarlyContext<'_>,
valid_idents: &[String],
docs: Events,
spans: &[(usize, Span)],
@ -231,7 +232,7 @@ fn check_doc<'a, Events: Iterator<Item = (usize, pulldown_cmark::Event<'a>)>>(
}
}
fn check_text(cx: &EarlyContext, valid_idents: &[String], text: &str, span: Span) {
fn check_text(cx: &EarlyContext<'_>, valid_idents: &[String], text: &str, span: Span) {
for word in text.split_whitespace() {
// Trim punctuation as in `some comment (see foo::bar).`
// ^^
@ -254,7 +255,7 @@ fn check_text(cx: &EarlyContext, valid_idents: &[String], text: &str, span: Span
}
}
fn check_word(cx: &EarlyContext, word: &str, span: Span) {
fn check_word(cx: &EarlyContext<'_>, word: &str, span: Span) {
/// Checks if a string is camel-case, ie. contains at least two uppercase
/// letter (`Clippy` is
/// ok) and one lower-case letter (`NASA` is ok). Plural are also excluded

View File

@ -2,6 +2,7 @@
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use syntax::codemap::Span;
use crate::utils::{snippet, span_lint_and_sugg, SpanlessEq};
@ -41,13 +42,13 @@ impl<'a, 'tcx> DoubleComparisonPass {
fn check_binop(
&self,
cx: &LateContext<'a, 'tcx>,
op: BinOp_,
op: BinOpKind,
lhs: &'tcx Expr,
rhs: &'tcx Expr,
span: Span,
) {
let (lkind, llhs, lrhs, rkind, rlhs, rrhs) = match (lhs.node.clone(), rhs.node.clone()) {
(ExprBinary(lb, llhs, lrhs), ExprBinary(rb, rlhs, rrhs)) => {
(ExprKind::Binary(lb, llhs, lrhs), ExprKind::Binary(rb, rlhs, rrhs)) => {
(lb.node, llhs, lrhs, rb.node, rlhs, rrhs)
}
_ => return,
@ -67,10 +68,10 @@ impl<'a, 'tcx> DoubleComparisonPass {
}}
}
match (op, lkind, rkind) {
(BiOr, BiEq, BiLt) | (BiOr, BiLt, BiEq) => lint_double_comparison!(<=),
(BiOr, BiEq, BiGt) | (BiOr, BiGt, BiEq) => lint_double_comparison!(>=),
(BiOr, BiLt, BiGt) | (BiOr, BiGt, BiLt) => lint_double_comparison!(!=),
(BiAnd, BiLe, BiGe) | (BiAnd, BiGe, BiLe) => lint_double_comparison!(==),
(BinOpKind::Or, BinOpKind::Eq, BinOpKind::Lt) | (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Eq) => lint_double_comparison!(<=),
(BinOpKind::Or, BinOpKind::Eq, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Eq) => lint_double_comparison!(>=),
(BinOpKind::Or, BinOpKind::Lt, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Lt) => lint_double_comparison!(!=),
(BinOpKind::And, BinOpKind::Le, BinOpKind::Ge) | (BinOpKind::And, BinOpKind::Ge, BinOpKind::Le) => lint_double_comparison!(==),
_ => (),
};
}
@ -78,7 +79,7 @@ impl<'a, 'tcx> DoubleComparisonPass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DoubleComparisonPass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let ExprBinary(ref kind, ref lhs, ref rhs) = expr.node {
if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = expr.node {
self.check_binop(cx, kind.node, lhs, rhs, expr.span);
}
}

View File

@ -1,5 +1,6 @@
use syntax::ast::*;
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
use rustc::{declare_lint, lint_array};
/// **What it does:** Checks for unnecessary double parentheses.
///
@ -30,7 +31,7 @@ impl LintPass for DoubleParens {
}
impl EarlyLintPass for DoubleParens {
fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
match expr.node {
ExprKind::Paren(ref in_paren) => match in_paren.node {
ExprKind::Paren(_) | ExprKind::Tup(_) => {

View File

@ -1,4 +1,6 @@
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::ty;
use rustc::hir::*;
use crate::utils::{is_copy, match_def_path, opt_def_id, paths, span_note_and_lint};
@ -116,8 +118,8 @@ impl LintPass for Pass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if_chain! {
if let ExprCall(ref path, ref args) = expr.node;
if let ExprPath(ref qpath) = path.node;
if let ExprKind::Call(ref path, ref args) = expr.node;
if let ExprKind::Path(ref qpath) = path.node;
if args.len() == 1;
if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id));
then {

View File

@ -1,5 +1,7 @@
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use syntax::codemap::Spanned;
use crate::consts::{constant, Constant};
@ -38,8 +40,8 @@ impl LintPass for DurationSubsec {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DurationSubsec {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if_chain! {
if let ExprBinary(Spanned { node: BiDiv, .. }, ref left, ref right) = expr.node;
if let ExprMethodCall(ref method_path, _ , ref args) = left.node;
if let ExprKind::Binary(Spanned { node: BinOpKind::Div, .. }, ref left, ref right) = expr.node;
if let ExprKind::MethodCall(ref method_path, _ , ref args) = left.node;
if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &paths::DURATION);
if let Some((Constant::Int(divisor), _)) = constant(cx, cx.tables, right);
then {

View File

@ -1,9 +1,10 @@
//! lint on if expressions with an else if, but without a final else branch
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use syntax::ast::*;
use crate::utils::{in_external_macro, span_lint_and_sugg};
use crate::utils::span_lint_and_sugg;
/// **What it does:** Checks for usage of if expressions with an `else if` branch,
/// but without a final `else` branch.
@ -48,8 +49,8 @@ impl LintPass for ElseIfWithoutElse {
}
impl EarlyLintPass for ElseIfWithoutElse {
fn check_expr(&mut self, cx: &EarlyContext, mut item: &Expr) {
if in_external_macro(cx, item.span) {
fn check_expr(&mut self, cx: &EarlyContext<'_>, mut item: &Expr) {
if in_external_macro(cx.sess(), item.span) {
return;
}

View File

@ -1,6 +1,7 @@
//! lint when there is an enum with no variants
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::hir::*;
use crate::utils::span_lint_and_then;
@ -32,9 +33,9 @@ impl LintPass for EmptyEnum {
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EmptyEnum {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item) {
let did = cx.tcx.hir.local_def_id(item.id);
if let ItemEnum(..) = item.node {
if let ItemKind::Enum(..) = item.node {
let ty = cx.tcx.type_of(did);
let adt = ty.ty_adt_def()
.expect("already checked whether this is an enum");

View File

@ -1,6 +1,8 @@
use rustc::hir::*;
use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use syntax::codemap::Span;
use crate::utils::SpanlessEq;
use crate::utils::{get_item_name, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty};
@ -41,13 +43,13 @@ impl LintPass for HashMapLint {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HashMapLint {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let ExprIf(ref check, ref then_block, ref else_block) = expr.node {
if let ExprUnary(UnOp::UnNot, ref check) = check.node {
if let ExprKind::If(ref check, ref then_block, ref else_block) = expr.node {
if let ExprKind::Unary(UnOp::UnNot, ref check) = check.node {
if let Some((ty, map, key)) = check_cond(cx, check) {
// in case of `if !m.contains_key(&k) { m.insert(k, v); }`
// we can give a better error message
let sole_expr = {
else_block.is_none() && if let ExprBlock(ref then_block, _) = then_block.node {
else_block.is_none() && if let ExprKind::Block(ref then_block, _) = then_block.node {
(then_block.expr.is_some() as usize) + then_block.stmts.len() == 1
} else {
true
@ -88,10 +90,10 @@ fn check_cond<'a, 'tcx, 'b>(
check: &'b Expr,
) -> Option<(&'static str, &'b Expr, &'b Expr)> {
if_chain! {
if let ExprMethodCall(ref path, _, ref params) = check.node;
if let ExprKind::MethodCall(ref path, _, ref params) = check.node;
if params.len() >= 2;
if path.ident.name == "contains_key";
if let ExprAddrOf(_, ref key) = params[1].node;
if let ExprKind::AddrOf(_, ref key) = params[1].node;
then {
let map = &params[0];
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(map));
@ -123,7 +125,7 @@ struct InsertVisitor<'a, 'tcx: 'a, 'b> {
impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> {
fn visit_expr(&mut self, expr: &'tcx Expr) {
if_chain! {
if let ExprMethodCall(ref path, _, ref params) = expr.node;
if let ExprKind::MethodCall(ref path, _, ref params) = expr.node;
if params.len() == 3;
if path.ident.name == "insert";
if get_item_name(self.cx, self.map) == get_item_name(self.cx, &params[0]);

View File

@ -2,6 +2,7 @@
//! don't fit into an `i32`
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::hir::*;
use rustc::ty;
use rustc::ty::subst::Substs;
@ -47,7 +48,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant {
if cx.tcx.data_layout.pointer_size.bits() != 64 {
return;
}
if let ItemEnum(ref def, _) = item.node {
if let ItemKind::Enum(ref def, _) = item.node {
for var in &def.variants {
let variant = &var.node;
if let Some(ref anon_const) = variant.disr_expr {

View File

@ -3,6 +3,7 @@
use rustc::hir::*;
use rustc::hir::def::Def;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint, lint_array};
use syntax::ast::NodeId;
use syntax::codemap::Span;
use crate::utils::span_lint;
@ -43,11 +44,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EnumGlobUse {
}
impl EnumGlobUse {
fn lint_item(&self, cx: &LateContext, item: &Item) {
if item.vis == Visibility::Public {
fn lint_item(&self, cx: &LateContext<'_, '_>, item: &Item) {
if item.vis.node.is_pub() {
return; // re-exports are fine
}
if let ItemUse(ref path, UseKind::Glob) = item.node {
if let ItemKind::Use(ref path, UseKind::Glob) = item.node {
if let Def::Enum(_) = path.def {
span_lint(
cx,

View File

@ -1,6 +1,7 @@
//! lint on enum variants that are prefixed or suffixed by the same characters
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use syntax::ast::*;
use syntax::codemap::Span;
use syntax::symbol::LocalInternedString;
@ -148,7 +149,7 @@ fn partial_rmatch(post: &str, name: &str) -> usize {
// FIXME: #600
#[allow(while_let_on_iterator)]
fn check_variant(
cx: &EarlyContext,
cx: &EarlyContext<'_>,
threshold: u64,
def: &EnumDef,
item_name: &str,
@ -239,12 +240,12 @@ fn to_camel_case(item_name: &str) -> String {
}
impl EarlyLintPass for EnumVariantNames {
fn check_item_post(&mut self, _cx: &EarlyContext, _item: &Item) {
fn check_item_post(&mut self, _cx: &EarlyContext<'_>, _item: &Item) {
let last = self.modules.pop();
assert!(last.is_some());
}
fn check_item(&mut self, cx: &EarlyContext, item: &Item) {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
let item_name = item.ident.as_str();
let item_name_chars = item_name.chars().count();
let item_camel = to_camel_case(&item_name);
@ -262,7 +263,7 @@ impl EarlyLintPass for EnumVariantNames {
);
}
}
if item.vis.node == VisibilityKind::Public {
if item.vis.node.is_pub() {
let matching = partial_match(mod_camel, &item_camel);
let rmatching = partial_rmatch(mod_camel, &item_camel);
let nchars = mod_camel.chars().count();

View File

@ -1,5 +1,6 @@
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use crate::utils::{in_macro, implements_trait, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq};
/// **What it does:** Checks for equal operands to comparison, logical and
@ -52,7 +53,7 @@ impl LintPass for EqOp {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
if let ExprBinary(op, ref left, ref right) = e.node {
if let ExprKind::Binary(op, ref left, ref right) = e.node {
if in_macro(e.span) {
return;
}
@ -66,28 +67,28 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
return;
}
let (trait_id, requires_ref) = match op.node {
BiAdd => (cx.tcx.lang_items().add_trait(), false),
BiSub => (cx.tcx.lang_items().sub_trait(), false),
BiMul => (cx.tcx.lang_items().mul_trait(), false),
BiDiv => (cx.tcx.lang_items().div_trait(), false),
BiRem => (cx.tcx.lang_items().rem_trait(), false),
BinOpKind::Add => (cx.tcx.lang_items().add_trait(), false),
BinOpKind::Sub => (cx.tcx.lang_items().sub_trait(), false),
BinOpKind::Mul => (cx.tcx.lang_items().mul_trait(), false),
BinOpKind::Div => (cx.tcx.lang_items().div_trait(), false),
BinOpKind::Rem => (cx.tcx.lang_items().rem_trait(), false),
// don't lint short circuiting ops
BiAnd | BiOr => return,
BiBitXor => (cx.tcx.lang_items().bitxor_trait(), false),
BiBitAnd => (cx.tcx.lang_items().bitand_trait(), false),
BiBitOr => (cx.tcx.lang_items().bitor_trait(), false),
BiShl => (cx.tcx.lang_items().shl_trait(), false),
BiShr => (cx.tcx.lang_items().shr_trait(), false),
BiNe | BiEq => (cx.tcx.lang_items().eq_trait(), true),
BiLt | BiLe | BiGe | BiGt => (cx.tcx.lang_items().ord_trait(), true),
BinOpKind::And | BinOpKind::Or => return,
BinOpKind::BitXor => (cx.tcx.lang_items().bitxor_trait(), false),
BinOpKind::BitAnd => (cx.tcx.lang_items().bitand_trait(), false),
BinOpKind::BitOr => (cx.tcx.lang_items().bitor_trait(), false),
BinOpKind::Shl => (cx.tcx.lang_items().shl_trait(), false),
BinOpKind::Shr => (cx.tcx.lang_items().shr_trait(), false),
BinOpKind::Ne | BinOpKind::Eq => (cx.tcx.lang_items().eq_trait(), true),
BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ge | BinOpKind::Gt => (cx.tcx.lang_items().ord_trait(), true),
};
if let Some(trait_id) = trait_id {
#[allow(match_same_arms)]
match (&left.node, &right.node) {
// do not suggest to dereference literals
(&ExprLit(..), _) | (_, &ExprLit(..)) => {},
(&ExprKind::Lit(..), _) | (_, &ExprKind::Lit(..)) => {},
// &foo == &bar
(&ExprAddrOf(_, ref l), &ExprAddrOf(_, ref r)) => {
(&ExprKind::AddrOf(_, ref l), &ExprKind::AddrOf(_, ref r)) => {
let lty = cx.tables.expr_ty(l);
let rty = cx.tables.expr_ty(r);
let lcpy = is_copy(cx, lty);
@ -128,7 +129,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
}
},
// &foo == bar
(&ExprAddrOf(_, ref l), _) => {
(&ExprKind::AddrOf(_, ref l), _) => {
let lty = cx.tables.expr_ty(l);
let lcpy = is_copy(cx, lty);
if (requires_ref || lcpy) && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()]) {
@ -139,7 +140,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
}
},
// foo == &bar
(_, &ExprAddrOf(_, ref r)) => {
(_, &ExprKind::AddrOf(_, ref r)) => {
let rty = cx.tables.expr_ty(r);
let rcpy = is_copy(cx, rty);
if (requires_ref || rcpy) && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()]) {
@ -159,7 +160,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
fn is_valid_operator(op: BinOp) -> bool {
match op.node {
BiSub | BiDiv | BiEq | BiLt | BiLe | BiGt | BiGe | BiNe | BiAnd | BiOr | BiBitXor | BiBitAnd | BiBitOr => true,
BinOpKind::Sub | BinOpKind::Div | BinOpKind::Eq | BinOpKind::Lt | BinOpKind::Le | BinOpKind::Gt | BinOpKind::Ge | BinOpKind::Ne | BinOpKind::And | BinOpKind::Or | BinOpKind::BitXor | BinOpKind::BitAnd | BinOpKind::BitOr => true,
_ => false,
}
}

View File

@ -1,6 +1,7 @@
use crate::consts::{constant_simple, Constant};
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use syntax::codemap::Span;
use crate::utils::{in_macro, span_lint};
@ -36,20 +37,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ErasingOp {
if in_macro(e.span) {
return;
}
if let ExprBinary(ref cmp, ref left, ref right) = e.node {
if let ExprKind::Binary(ref cmp, ref left, ref right) = e.node {
match cmp.node {
BiMul | BiBitAnd => {
BinOpKind::Mul | BinOpKind::BitAnd => {
check(cx, left, e.span);
check(cx, right, e.span);
},
BiDiv => check(cx, left, e.span),
BinOpKind::Div => check(cx, left, e.span),
_ => (),
}
}
}
}
fn check(cx: &LateContext, e: &Expr, span: Span) {
fn check(cx: &LateContext<'_, '_>, e: &Expr, span: Span) {
if let Some(Constant::Int(v)) = constant_simple(cx, cx.tables, e) {
if v == 0 {
span_lint(

View File

@ -2,6 +2,7 @@ use rustc::hir::*;
use rustc::hir::intravisit as visit;
use rustc::hir::map::Node::{NodeExpr, NodeStmt};
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::middle::expr_use_visitor::*;
use rustc::middle::mem_categorization::{cmt_, Categorization};
use rustc::ty::{self, Ty};
@ -38,7 +39,7 @@ declare_clippy_lint! {
"using `Box<T>` where unnecessary"
}
fn is_non_trait_box(ty: Ty) -> bool {
fn is_non_trait_box(ty: Ty<'_>) -> bool {
ty.is_box() && !ty.boxed_ty().is_trait()
}
@ -108,11 +109,12 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
return;
}
if let Categorization::Rvalue(..) = cmt.cat {
if let Some(NodeStmt(st)) = map.find(map.get_parent_node(cmt.id)) {
if let StmtDecl(ref decl, _) = st.node {
if let DeclLocal(ref loc) = decl.node {
let id = map.hir_to_node_id(cmt.hir_id);
if let Some(NodeStmt(st)) = map.find(map.get_parent_node(id)) {
if let StmtKind::Decl(ref decl, _) = st.node {
if let DeclKind::Local(ref loc) = decl.node {
if let Some(ref ex) = loc.init {
if let ExprBox(..) = ex.node {
if let ExprKind::Box(..) = ex.node {
if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) {
// let x = box (...)
self.set.insert(consume_pat.id);
@ -135,7 +137,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
}
}
}
fn borrow(&mut self, _: NodeId, _: Span, cmt: &cmt_<'tcx>, _: ty::Region, _: ty::BorrowKind, loan_cause: LoanCause) {
fn borrow(&mut self, _: NodeId, _: Span, cmt: &cmt_<'tcx>, _: ty::Region<'_>, _: ty::BorrowKind, loan_cause: LoanCause) {
if let Categorization::Local(lid) = cmt.cat {
match loan_cause {
// x.foo()

View File

@ -1,4 +1,5 @@
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::ty;
use rustc::hir::*;
use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then};
@ -37,7 +38,7 @@ impl LintPass for EtaPass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaPass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
match expr.node {
ExprCall(_, ref args) | ExprMethodCall(_, _, ref args) => for arg in args {
ExprKind::Call(_, ref args) | ExprKind::MethodCall(_, _, ref args) => for arg in args {
check_closure(cx, arg)
},
_ => (),
@ -45,11 +46,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaPass {
}
}
fn check_closure(cx: &LateContext, expr: &Expr) {
if let ExprClosure(_, ref decl, eid, _, _) = expr.node {
fn check_closure(cx: &LateContext<'_, '_>, expr: &Expr) {
if let ExprKind::Closure(_, ref decl, eid, _, _) = expr.node {
let body = cx.tcx.hir.body(eid);
let ex = &body.value;
if let ExprCall(ref caller, ref args) = ex.node {
if let ExprKind::Call(ref caller, ref args) = ex.node {
if args.len() != decl.inputs.len() {
// Not the same number of arguments, there
// is no way the closure is the same as the function
@ -73,7 +74,7 @@ fn check_closure(cx: &LateContext, expr: &Expr) {
for (a1, a2) in iter_input_pats(decl, body).zip(args) {
if let PatKind::Binding(_, _, ident, _) = a1.pat.node {
// XXXManishearth Should I be checking the binding mode here?
if let ExprPath(QPath::Resolved(None, ref p)) = a2.node {
if let ExprKind::Path(QPath::Resolved(None, ref p)) = a2.node {
if p.segments.len() != 1 {
// If it's a proper path, it can't be a local variable
return;

View File

@ -2,6 +2,8 @@ use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc::hir::*;
use rustc::ty;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use syntax::ast;
use crate::utils::{get_parent_expr, span_lint, span_note_and_lint};
@ -62,7 +64,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
// Find a write to a local variable.
match expr.node {
ExprAssign(ref lhs, _) | ExprAssignOp(_, ref lhs, _) => if let ExprPath(ref qpath) = lhs.node {
ExprKind::Assign(ref lhs, _) | ExprKind::AssignOp(_, ref lhs, _) => if let ExprKind::Path(ref qpath) = lhs.node {
if let QPath::Resolved(_, ref path) = *qpath {
if path.segments.len() == 1 {
if let def::Def::Local(var) = cx.tables.qpath_def(qpath, lhs.hir_id) {
@ -82,8 +84,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence {
}
fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) {
match stmt.node {
StmtExpr(ref e, _) | StmtSemi(ref e, _) => DivergenceVisitor { cx }.maybe_walk_expr(e),
StmtDecl(ref d, _) => if let DeclLocal(ref local) = d.node {
StmtKind::Expr(ref e, _) | StmtKind::Semi(ref e, _) => DivergenceVisitor { cx }.maybe_walk_expr(e),
StmtKind::Decl(ref d, _) => if let DeclKind::Local(ref local) = d.node {
if let Local {
init: Some(ref e), ..
} = **local
@ -102,8 +104,8 @@ struct DivergenceVisitor<'a, 'tcx: 'a> {
impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
fn maybe_walk_expr(&mut self, e: &'tcx Expr) {
match e.node {
ExprClosure(.., _) => {},
ExprMatch(ref e, ref arms, _) => {
ExprKind::Closure(.., _) => {},
ExprKind::Match(ref e, ref arms, _) => {
self.visit_expr(e);
for arm in arms {
if let Some(ref guard) = arm.guard {
@ -124,8 +126,8 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
fn visit_expr(&mut self, e: &'tcx Expr) {
match e.node {
ExprContinue(_) | ExprBreak(_, _) | ExprRet(_) => self.report_diverging_sub_expr(e),
ExprCall(ref func, _) => {
ExprKind::Continue(_) | ExprKind::Break(_, _) | ExprKind::Ret(_) => self.report_diverging_sub_expr(e),
ExprKind::Call(ref func, _) => {
let typ = self.cx.tables.expr_ty(func);
match typ.sty {
ty::TyFnDef(..) | ty::TyFnPtr(_) => {
@ -137,7 +139,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
_ => {},
}
},
ExprMethodCall(..) => {
ExprKind::MethodCall(..) => {
let borrowed_table = self.cx.tables;
if borrowed_table.expr_ty(e).is_never() {
self.report_diverging_sub_expr(e);
@ -173,7 +175,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
/// logical operators are considered to have a defined evaluation order.
///
/// When such a read is found, the lint is triggered.
fn check_for_unsequenced_reads(vis: &mut ReadVisitor) {
fn check_for_unsequenced_reads(vis: &mut ReadVisitor<'_, '_>) {
let map = &vis.cx.tcx.hir;
let mut cur_id = vis.write_expr.id;
loop {
@ -218,25 +220,25 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr) -> St
}
match expr.node {
ExprArray(_) |
ExprTup(_) |
ExprMethodCall(..) |
ExprCall(_, _) |
ExprAssign(_, _) |
ExprIndex(_, _) |
ExprRepeat(_, _) |
ExprStruct(_, _, _) => {
ExprKind::Array(_) |
ExprKind::Tup(_) |
ExprKind::MethodCall(..) |
ExprKind::Call(_, _) |
ExprKind::Assign(_, _) |
ExprKind::Index(_, _) |
ExprKind::Repeat(_, _) |
ExprKind::Struct(_, _, _) => {
walk_expr(vis, expr);
},
ExprBinary(op, _, _) | ExprAssignOp(op, _, _) => {
if op.node == BiAnd || op.node == BiOr {
ExprKind::Binary(op, _, _) | ExprKind::AssignOp(op, _, _) => {
if op.node == BinOpKind::And || op.node == BinOpKind::Or {
// x && y and x || y always evaluate x first, so these are
// strictly sequenced.
} else {
walk_expr(vis, expr);
}
},
ExprClosure(_, _, _, _, _) => {
ExprKind::Closure(_, _, _, _, _) => {
// Either
//
// * `var` is defined in the closure body, in which case we've
@ -262,12 +264,12 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr) -> St
fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt) -> StopEarly {
match stmt.node {
StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => check_expr(vis, expr),
StmtDecl(ref decl, _) => {
StmtKind::Expr(ref expr, _) | StmtKind::Semi(ref expr, _) => check_expr(vis, expr),
StmtKind::Decl(ref decl, _) => {
// If the declaration is of a local variable, check its initializer
// expression if it has one. Otherwise, keep going.
let local = match decl.node {
DeclLocal(ref local) => Some(local),
DeclKind::Local(ref local) => Some(local),
_ => None,
};
local
@ -297,7 +299,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> {
}
match expr.node {
ExprPath(ref qpath) => {
ExprKind::Path(ref qpath) => {
if_chain! {
if let QPath::Resolved(None, ref path) = *qpath;
if path.segments.len() == 1;
@ -320,7 +322,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> {
// We're about to descend a closure. Since we don't know when (or
// if) the closure will be evaluated, any reads in it might not
// occur here (or ever). Like above, bail to avoid false positives.
ExprClosure(_, _, _, _, _) |
ExprKind::Closure(_, _, _, _, _) |
// We want to avoid a false positive when a variable name occurs
// only to have its address taken, so we stop here. Technically,
@ -332,7 +334,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> {
// ```
//
// TODO: fix this
ExprAddrOf(_, _) => {
ExprKind::AddrOf(_, _) => {
return;
}
_ => {}
@ -346,9 +348,9 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> {
}
/// Returns true if `expr` is the LHS of an assignment, like `expr = ...`.
fn is_in_assignment_position(cx: &LateContext, expr: &Expr) -> bool {
fn is_in_assignment_position(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
if let Some(parent) = get_parent_expr(cx, expr) {
if let ExprAssign(ref lhs, _) = parent.node {
if let ExprKind::Assign(ref lhs, _) = parent.node {
return lhs.id == expr.id;
}
}

View File

@ -1,5 +1,7 @@
use rustc::hir;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::ty::TypeVariants;
use std::f32;
use std::f64;
@ -45,7 +47,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExcessivePrecision {
if_chain! {
let ty = cx.tables.expr_ty(expr);
if let TypeVariants::TyFloat(fty) = ty.sty;
if let hir::ExprLit(ref lit) = expr.node;
if let hir::ExprKind::Lit(ref lit) = expr.node;
if let LitKind::Float(sym, _) | LitKind::FloatUnsuffixed(sym) = lit.node;
if let Some(sugg) = self.check(sym, fty);
then {

View File

@ -1,5 +1,7 @@
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use crate::utils::{is_expn_of, match_def_path, resolve_node, span_lint};
use crate::utils::opt_def_id;
@ -35,17 +37,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if_chain! {
// match call to unwrap
if let ExprMethodCall(ref unwrap_fun, _, ref unwrap_args) = expr.node;
if let ExprKind::MethodCall(ref unwrap_fun, _, ref unwrap_args) = expr.node;
if unwrap_fun.ident.name == "unwrap";
// match call to write_fmt
if unwrap_args.len() > 0;
if let ExprMethodCall(ref write_fun, _, ref write_args) =
if let ExprKind::MethodCall(ref write_fun, _, ref write_args) =
unwrap_args[0].node;
if write_fun.ident.name == "write_fmt";
// match calls to std::io::stdout() / std::io::stderr ()
if write_args.len() > 0;
if let ExprCall(ref dest_fun, _) = write_args[0].node;
if let ExprPath(ref qpath) = dest_fun.node;
if let ExprKind::Call(ref dest_fun, _) = write_args[0].node;
if let ExprKind::Path(ref qpath) = dest_fun.node;
if let Some(dest_fun_id) =
opt_def_id(resolve_node(cx, qpath, dest_fun.hir_id));
if let Some(dest_name) = if match_def_path(cx.tcx, dest_fun_id, &["std", "io", "stdio", "stdout"]) {

View File

@ -1,4 +1,6 @@
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::hir;
use rustc::ty;
use syntax_pos::Span;
@ -39,7 +41,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FallibleImplFrom {
// check for `impl From<???> for ..`
let impl_def_id = cx.tcx.hir.local_def_id(item.id);
if_chain! {
if let hir::ItemImpl(.., ref impl_items) = item.node;
if let hir::ItemKind::Impl(.., ref impl_items) = item.node;
if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_def_id);
if match_def_path(cx.tcx, impl_trait_ref.def_id, &FROM_TRAIT);
then {
@ -63,8 +65,8 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it
fn visit_expr(&mut self, expr: &'tcx Expr) {
// check for `begin_panic`
if_chain! {
if let ExprCall(ref func_expr, _) = expr.node;
if let ExprPath(QPath::Resolved(_, ref path)) = func_expr.node;
if let ExprKind::Call(ref func_expr, _) = expr.node;
if let ExprKind::Path(QPath::Resolved(_, ref path)) = func_expr.node;
if let Some(path_def_id) = opt_def_id(path.def);
if match_def_path(self.tcx, path_def_id, &BEGIN_PANIC) ||
match_def_path(self.tcx, path_def_id, &BEGIN_PANIC_FMT);
@ -126,7 +128,7 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it
}
}
fn match_type(tcx: ty::TyCtxt, ty: ty::Ty, path: &[&str]) -> bool {
fn match_type(tcx: ty::TyCtxt<'_, '_, '_>, ty: ty::Ty<'_>, path: &[&str]) -> bool {
match ty.sty {
ty::TyAdt(adt, _) => match_def_path(tcx, adt.did, path),
_ => false,

View File

@ -1,5 +1,7 @@
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::ty;
use syntax::ast::LitKind;
use syntax_pos::Span;
@ -46,9 +48,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
match expr.node {
// `format!("{}", foo)` expansion
ExprCall(ref fun, ref args) => {
ExprKind::Call(ref fun, ref args) => {
if_chain! {
if let ExprPath(ref qpath) = fun.node;
if let ExprKind::Path(ref qpath) = fun.node;
if args.len() == 3;
if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id));
if match_def_path(cx.tcx, fun_def_id, &paths::FMT_ARGUMENTS_NEWV1FORMATTED);
@ -64,7 +66,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
}
},
// `format!("foo")` expansion contains `match () { () => [], }`
ExprMatch(ref matchee, _, _) => if let ExprTup(ref tup) = matchee.node {
ExprKind::Match(ref matchee, _, _) => if let ExprKind::Tup(ref tup) = matchee.node {
if tup.is_empty() {
let sugg = format!("{}.to_string()", snippet(cx, expr.span, "<expr>").into_owned());
span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| {
@ -81,10 +83,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
/// Checks if the expressions matches `&[""]`
fn check_single_piece(expr: &Expr) -> bool {
if_chain! {
if let ExprAddrOf(_, ref expr) = expr.node; // &[""]
if let ExprArray(ref exprs) = expr.node; // [""]
if let ExprKind::AddrOf(_, ref expr) = expr.node; // &[""]
if let ExprKind::Array(ref exprs) = expr.node; // [""]
if exprs.len() == 1;
if let ExprLit(ref lit) = exprs[0].node;
if let ExprKind::Lit(ref lit) = exprs[0].node;
if let LitKind::Str(ref lit, _) = lit.node;
then {
return lit.as_str().is_empty();
@ -103,25 +105,25 @@ fn check_single_piece(expr: &Expr) -> bool {
/// ```
/// and that type of `__arg0` is `&str` or `String`
/// then returns the span of first element of the matched tuple
fn get_single_string_arg(cx: &LateContext, expr: &Expr) -> Option<Span> {
fn get_single_string_arg(cx: &LateContext<'_, '_>, expr: &Expr) -> Option<Span> {
if_chain! {
if let ExprAddrOf(_, ref expr) = expr.node;
if let ExprMatch(ref match_expr, ref arms, _) = expr.node;
if let ExprKind::AddrOf(_, ref expr) = expr.node;
if let ExprKind::Match(ref match_expr, ref arms, _) = expr.node;
if arms.len() == 1;
if arms[0].pats.len() == 1;
if let PatKind::Tuple(ref pat, None) = arms[0].pats[0].node;
if pat.len() == 1;
if let ExprArray(ref exprs) = arms[0].body.node;
if let ExprKind::Array(ref exprs) = arms[0].body.node;
if exprs.len() == 1;
if let ExprCall(_, ref args) = exprs[0].node;
if let ExprKind::Call(_, ref args) = exprs[0].node;
if args.len() == 2;
if let ExprPath(ref qpath) = args[1].node;
if let ExprKind::Path(ref qpath) = args[1].node;
if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, args[1].hir_id));
if match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD);
then {
let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0]));
if ty.sty == ty::TyStr || match_type(cx, ty, &paths::STRING) {
if let ExprTup(ref values) = match_expr.node {
if let ExprKind::Tup(ref values) = match_expr.node {
return Some(values[0].span);
}
}
@ -143,14 +145,14 @@ fn get_single_string_arg(cx: &LateContext, expr: &Expr) -> Option<Span> {
/// ```
fn check_unformatted(expr: &Expr) -> bool {
if_chain! {
if let ExprAddrOf(_, ref expr) = expr.node;
if let ExprArray(ref exprs) = expr.node;
if let ExprKind::AddrOf(_, ref expr) = expr.node;
if let ExprKind::Array(ref exprs) = expr.node;
if exprs.len() == 1;
if let ExprStruct(_, ref fields, _) = exprs[0].node;
if let ExprKind::Struct(_, ref fields, _) = exprs[0].node;
if let Some(format_field) = fields.iter().find(|f| f.ident.name == "format");
if let ExprStruct(_, ref fields, _) = format_field.expr.node;
if let ExprKind::Struct(_, ref fields, _) = format_field.expr.node;
if let Some(align_field) = fields.iter().find(|f| f.ident.name == "width");
if let ExprPath(ref qpath) = align_field.expr.node;
if let ExprKind::Path(ref qpath) = align_field.expr.node;
if last_path_segment(qpath).ident.name == "Implied";
then {
return true;

View File

@ -1,4 +1,5 @@
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use syntax::ast;
use crate::utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint};
use syntax::ptr::P;
@ -82,7 +83,7 @@ impl LintPass for Formatting {
}
impl EarlyLintPass for Formatting {
fn check_block(&mut self, cx: &EarlyContext, block: &ast::Block) {
fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) {
for w in block.stmts.windows(2) {
match (&w[0].node, &w[1].node) {
(&ast::StmtKind::Expr(ref first), &ast::StmtKind::Expr(ref second)) |
@ -94,7 +95,7 @@ impl EarlyLintPass for Formatting {
}
}
fn check_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr) {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
check_assign(cx, expr);
check_else_if(cx, expr);
check_array(cx, expr);
@ -102,7 +103,7 @@ impl EarlyLintPass for Formatting {
}
/// Implementation of the `SUSPICIOUS_ASSIGNMENT_FORMATTING` lint.
fn check_assign(cx: &EarlyContext, expr: &ast::Expr) {
fn check_assign(cx: &EarlyContext<'_>, expr: &ast::Expr) {
if let ast::ExprKind::Assign(ref lhs, ref rhs) = expr.node {
if !differing_macro_contexts(lhs.span, rhs.span) && !in_macro(lhs.span) {
let eq_span = lhs.span.between(rhs.span);
@ -131,7 +132,7 @@ fn check_assign(cx: &EarlyContext, expr: &ast::Expr) {
}
/// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for weird `else if`.
fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) {
fn check_else_if(cx: &EarlyContext<'_>, expr: &ast::Expr) {
if let Some((then, &Some(ref else_))) = unsugar_if(expr) {
if unsugar_if(else_).is_some() && !differing_macro_contexts(then.span, else_.span) && !in_macro(then.span) {
// this will be a span from the closing } of the “then” block (excluding) to
@ -163,7 +164,7 @@ fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) {
}
/// Implementation of the `POSSIBLE_MISSING_COMMA` lint for array
fn check_array(cx: &EarlyContext, expr: &ast::Expr) {
fn check_array(cx: &EarlyContext<'_>, expr: &ast::Expr) {
if let ast::ExprKind::Array(ref array) = expr.node {
for element in array {
if let ast::ExprKind::Binary(ref op, ref lhs, _) = element.node {
@ -189,7 +190,7 @@ fn check_array(cx: &EarlyContext, expr: &ast::Expr) {
}
/// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for consecutive ifs.
fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Expr) {
fn check_consecutive_ifs(cx: &EarlyContext<'_>, first: &ast::Expr, second: &ast::Expr) {
if !differing_macro_contexts(first.span, second.span) && !in_macro(first.span) && unsugar_if(first).is_some()
&& unsugar_if(second).is_some()
{

View File

@ -1,6 +1,8 @@
use matches::matches;
use rustc::hir::intravisit;
use rustc::hir;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::ty;
use rustc::hir::def::Def;
use std::collections::HashSet;
@ -86,7 +88,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions {
use rustc::hir::map::Node::*;
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(_), _, _))
matches!(item.node, hir::ItemKind::Impl(_, _, _, _, Some(_), _, _))
} else {
false
};
@ -126,7 +128,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions {
}
impl<'a, 'tcx> Functions {
fn check_arg_number(self, cx: &LateContext, decl: &hir::FnDecl, span: Span) {
fn check_arg_number(self, cx: &LateContext<'_, '_>, decl: &hir::FnDecl, span: Span) {
let args = decl.inputs.len() as u64;
if args > self.threshold {
span_lint(
@ -168,7 +170,7 @@ impl<'a, 'tcx> Functions {
}
fn raw_ptr_arg(arg: &hir::Arg, ty: &hir::Ty) -> Option<ast::NodeId> {
if let (&hir::PatKind::Binding(_, id, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &ty.node) {
if let (&hir::PatKind::Binding(_, id, _, _), &hir::TyKind::Ptr(_)) = (&arg.pat.node, &ty.node) {
Some(id)
} else {
None
@ -184,7 +186,7 @@ struct DerefVisitor<'a, 'tcx: 'a> {
impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
match expr.node {
hir::ExprCall(ref f, ref args) => {
hir::ExprKind::Call(ref f, ref args) => {
let ty = self.tables.expr_ty(f);
if type_is_unsafe_function(self.cx, ty) {
@ -193,7 +195,7 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
}
}
},
hir::ExprMethodCall(_, _, ref args) => {
hir::ExprKind::MethodCall(_, _, ref args) => {
let def_id = self.tables.type_dependent_defs()[expr.hir_id].def_id();
let base_type = self.cx.tcx.type_of(def_id);
@ -203,7 +205,7 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
}
}
},
hir::ExprUnary(hir::UnDeref, ref ptr) => self.check_arg(ptr),
hir::ExprKind::Unary(hir::UnDeref, ref ptr) => self.check_arg(ptr),
_ => (),
}
@ -216,7 +218,7 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
impl<'a, 'tcx: 'a> DerefVisitor<'a, 'tcx> {
fn check_arg(&self, ptr: &hir::Expr) {
if let hir::ExprPath(ref qpath) = ptr.node {
if let hir::ExprKind::Path(ref qpath) = ptr.node {
if let Def::Local(id) = self.cx.tables.qpath_def(qpath, ptr.hir_id) {
if self.ptrs.contains(&id) {
span_lint(

View File

@ -1,4 +1,5 @@
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::hir::*;
use syntax::ast::NodeId;
use crate::utils::{in_macro, match_def_path, match_trait_method, same_tys, snippet, span_lint_and_then};
@ -43,19 +44,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion {
}
match e.node {
ExprMatch(_, ref arms, MatchSource::TryDesugar) => {
ExprKind::Match(_, ref arms, MatchSource::TryDesugar) => {
let e = match arms[0].body.node {
ExprRet(Some(ref e)) | ExprBreak(_, Some(ref e)) => e,
ExprKind::Ret(Some(ref e)) | ExprKind::Break(_, Some(ref e)) => e,
_ => return,
};
if let ExprCall(_, ref args) = e.node {
if let ExprKind::Call(_, ref args) = e.node {
self.try_desugar_arm.push(args[0].id);
} else {
return;
}
},
ExprMethodCall(ref name, .., ref args) => {
ExprKind::MethodCall(ref name, .., ref args) => {
if match_trait_method(cx, e, &paths::INTO[..]) && &*name.ident.as_str() == "into" {
let a = cx.tables.expr_ty(e);
let b = cx.tables.expr_ty(&args[0]);
@ -68,7 +69,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion {
}
},
ExprCall(ref path, ref args) => if let ExprPath(ref qpath) = path.node {
ExprKind::Call(ref path, ref args) => if let ExprKind::Path(ref qpath) = path.node {
if let Some(def_id) = opt_def_id(resolve_node(cx, qpath, path.hir_id)) {
if match_def_path(cx.tcx, def_id, &paths::FROM_FROM[..]) {
let a = cx.tables.expr_ty(e);

View File

@ -1,6 +1,7 @@
use crate::consts::{constant_simple, Constant};
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use syntax::codemap::Span;
use crate::utils::{in_macro, snippet, span_lint, unsext, clip};
use rustc::ty;
@ -36,19 +37,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp {
if in_macro(e.span) {
return;
}
if let ExprBinary(ref cmp, ref left, ref right) = e.node {
if let ExprKind::Binary(ref cmp, ref left, ref right) = e.node {
match cmp.node {
BiAdd | BiBitOr | BiBitXor => {
BinOpKind::Add | BinOpKind::BitOr | BinOpKind::BitXor => {
check(cx, left, 0, e.span, right.span);
check(cx, right, 0, e.span, left.span);
},
BiShl | BiShr | BiSub => check(cx, right, 0, e.span, left.span),
BiMul => {
BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Sub => check(cx, right, 0, e.span, left.span),
BinOpKind::Mul => {
check(cx, left, 1, e.span, right.span);
check(cx, right, 1, e.span, left.span);
},
BiDiv => check(cx, right, 1, e.span, left.span),
BiBitAnd => {
BinOpKind::Div => check(cx, right, 1, e.span, left.span),
BinOpKind::BitAnd => {
check(cx, left, -1, e.span, right.span);
check(cx, right, -1, e.span, left.span);
},
@ -59,7 +60,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp {
}
#[allow(cast_possible_wrap)]
fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) {
fn check(cx: &LateContext<'_, '_>, e: &Expr, m: i8, span: Span, arg: Span) {
if let Some(Constant::Int(v)) = constant_simple(cx, cx.tables, e) {
let check = match cx.tables.expr_ty(e).sty {
ty::TyInt(ity) => unsext(cx.tcx, -1i128, ity),

View File

@ -1,4 +1,5 @@
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::hir::*;
use crate::utils::{match_qpath, paths, snippet, span_lint_and_then};
@ -45,16 +46,20 @@ impl LintPass for Pass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let ExprMatch(ref op, ref arms, MatchSource::IfLetDesugar { .. }) = expr.node {
if let ExprKind::Match(ref op, ref arms, MatchSource::IfLetDesugar { .. }) = expr.node {
if arms[0].pats.len() == 1 {
let good_method = match arms[0].pats[0].node {
PatKind::TupleStruct(ref path, ref pats, _) if pats.len() == 1 && pats[0].node == PatKind::Wild => {
if match_qpath(path, &paths::RESULT_OK) {
"is_ok()"
} else if match_qpath(path, &paths::RESULT_ERR) {
"is_err()"
} else if match_qpath(path, &paths::OPTION_SOME) {
"is_some()"
PatKind::TupleStruct(ref path, ref pats, _) if pats.len() == 1 => {
if let PatKind::Wild = pats[0].node {
if match_qpath(path, &paths::RESULT_OK) {
"is_ok()"
} else if match_qpath(path, &paths::RESULT_ERR) {
"is_err()"
} else if match_qpath(path, &paths::OPTION_SOME) {
"is_some()"
} else {
return;
}
} else {
return;
}

View File

@ -2,9 +2,10 @@
//! on the condition
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use syntax::ast::*;
use crate::utils::{in_external_macro, span_help_and_lint};
use crate::utils::span_help_and_lint;
/// **What it does:** Checks for usage of `!` or `!=` in an if condition with an
/// else branch.
@ -46,8 +47,8 @@ impl LintPass for IfNotElse {
}
impl EarlyLintPass for IfNotElse {
fn check_expr(&mut self, cx: &EarlyContext, item: &Expr) {
if in_external_macro(cx, item.span) {
fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) {
if in_external_macro(cx.sess(), item.span) {
return;
}
if let ExprKind::If(ref cond, _, Some(ref els)) = item.node {

View File

@ -6,6 +6,7 @@ use crate::utils::higher;
use crate::utils::higher::Range;
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::ty;
use syntax::ast::RangeLimits;
@ -94,7 +95,7 @@ impl LintPass for IndexingSlicing {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let ExprIndex(ref array, ref index) = &expr.node {
if let ExprKind::Index(ref array, ref index) = &expr.node {
let ty = cx.tables.expr_ty(array);
if let Some(range) = higher::range(cx, index) {
// Ranged indexes, i.e. &x[n..m], &x[n..], &x[..n] and &x[..]
@ -154,7 +155,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing {
/// the range.
fn to_const_range<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>,
range: Range,
range: Range<'_>,
array_size: u128,
) -> Option<(u128, u128)> {
let s = range

View File

@ -1,6 +1,8 @@
use super::utils::{get_arg_name, match_var, remove_blocks, snippet, span_lint_and_sugg};
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
/// **What it does:** Checks for matches being used to destructure a single-variant enum
/// or tuple struct where a `let` will suffice.
@ -50,7 +52,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_local(&mut self, cx: &LateContext<'a, 'tcx>, local: &'tcx Local) {
if_chain! {
if let Some(ref expr) = local.init;
if let Expr_::ExprMatch(ref target, ref arms, MatchSource::Normal) = expr.node;
if let ExprKind::Match(ref target, ref arms, MatchSource::Normal) = expr.node;
if arms.len() == 1 && arms[0].pats.len() == 1 && arms[0].guard.is_none();
if let PatKind::TupleStruct(QPath::Resolved(None, ref variant_name), ref args, _) = arms[0].pats[0].node;
if args.len() == 1;

View File

@ -1,5 +1,6 @@
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, paths, span_lint};
/// **What it does:** Checks for iteration that is guaranteed to be infinite.
@ -139,9 +140,9 @@ static HEURISTICS: &[(&str, usize, Heuristic, Finiteness)] = &[
("scan", 3, First, MaybeInfinite),
];
fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness {
fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
match expr.node {
ExprMethodCall(ref method, _, ref args) => {
ExprKind::MethodCall(ref method, _, ref args) => {
for &(name, len, heuristic, cap) in HEURISTICS.iter() {
if method.ident.name == name && args.len() == len {
return (match heuristic {
@ -153,21 +154,21 @@ fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness {
}
}
if method.ident.name == "flat_map" && args.len() == 2 {
if let ExprClosure(_, _, body_id, _, _) = args[1].node {
if let ExprKind::Closure(_, _, body_id, _, _) = args[1].node {
let body = cx.tcx.hir.body(body_id);
return is_infinite(cx, &body.value);
}
}
Finite
},
ExprBlock(ref block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)),
ExprBox(ref e) | ExprAddrOf(_, ref e) => is_infinite(cx, e),
ExprCall(ref path, _) => if let ExprPath(ref qpath) = path.node {
ExprKind::Block(ref block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)),
ExprKind::Box(ref e) | ExprKind::AddrOf(_, ref e) => is_infinite(cx, e),
ExprKind::Call(ref path, _) => if let ExprKind::Path(ref qpath) = path.node {
match_qpath(qpath, &paths::REPEAT).into()
} else {
Finite
},
ExprStruct(..) => higher::range(cx, expr)
ExprKind::Struct(..) => higher::range(cx, expr)
.map_or(false, |r| r.end.is_none())
.into(),
_ => Finite,
@ -203,9 +204,9 @@ static COMPLETING_METHODS: &[(&str, usize)] = &[
("product", 1),
];
fn complete_infinite_iter(cx: &LateContext, expr: &Expr) -> Finiteness {
fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
match expr.node {
ExprMethodCall(ref method, _, ref args) => {
ExprKind::MethodCall(ref method, _, ref args) => {
for &(name, len) in COMPLETING_METHODS.iter() {
if method.ident.name == name && args.len() == len {
return is_infinite(cx, &args[0]);
@ -224,11 +225,11 @@ fn complete_infinite_iter(cx: &LateContext, expr: &Expr) -> Finiteness {
}
}
},
ExprBinary(op, ref l, ref r) => if op.node.is_comparison() {
ExprKind::Binary(op, ref l, ref r) => if op.node.is_comparison() {
return is_infinite(cx, l)
.and(is_infinite(cx, r))
.and(MaybeInfinite);
}, // TODO: ExprLoop + Match
}, // TODO: ExprKind::Loop + Match
_ => (),
}
Finite

View File

@ -2,6 +2,7 @@
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use std::collections::HashMap;
use std::default::Default;
use syntax_pos::Span;
@ -56,7 +57,7 @@ impl LintPass for Pass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_item(&mut self, _: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if let Item_::ItemImpl(_, _, _, ref generics, None, _, _) = item.node {
if let ItemKind::Impl(_, _, _, ref generics, None, _, _) = item.node {
// Remember for each inherent implementation encoutered its span and generics
self.impls
.insert(item.hir_id.owner_def_id(), (item.span, generics.clone()));

View File

@ -1,6 +1,7 @@
//! checks for `#[inline]` on trait methods without bodies
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::hir::*;
use syntax::ast::{Attribute, Name};
use crate::utils::span_lint_and_then;
@ -43,7 +44,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
}
}
fn check_attrs(cx: &LateContext, name: Name, attrs: &[Attribute]) {
fn check_attrs(cx: &LateContext<'_, '_>, name: Name, attrs: &[Attribute]) {
for attr in attrs {
if attr.name() != "inline" {
continue;

View File

@ -1,6 +1,7 @@
//! lint on blocks unnecessarily using >= with a + 1 or - 1
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use syntax::ast::*;
use crate::utils::{snippet_opt, span_lint_and_then};
@ -60,7 +61,7 @@ impl IntPlusOne {
false
}
fn check_binop(&self, cx: &EarlyContext, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option<String> {
fn check_binop(&self, cx: &EarlyContext<'_>, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option<String> {
match (binop, &lhs.node, &rhs.node) {
// case where `x - 1 >= ...` or `-1 + x >= ...`
(BinOpKind::Ge, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) => {
@ -126,7 +127,7 @@ impl IntPlusOne {
fn generate_recommendation(
&self,
cx: &EarlyContext,
cx: &EarlyContext<'_>,
binop: BinOpKind,
node: &Expr,
other_side: &Expr,
@ -149,7 +150,7 @@ impl IntPlusOne {
None
}
fn emit_warning(&self, cx: &EarlyContext, block: &Expr, recommendation: String) {
fn emit_warning(&self, cx: &EarlyContext<'_>, block: &Expr, recommendation: String) {
span_lint_and_then(cx, INT_PLUS_ONE, block.span, "Unnecessary `>= y + 1` or `x - 1 >=`", |db| {
db.span_suggestion(block.span, "change `>= y + 1` to `> y` as shown", recommendation);
});
@ -157,7 +158,7 @@ impl IntPlusOne {
}
impl EarlyLintPass for IntPlusOne {
fn check_expr(&mut self, cx: &EarlyContext, item: &Expr) {
fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) {
if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = item.node {
if let Some(ref rec) = self.check_binop(cx, kind.node, lhs, rhs) {
self.emit_warning(cx, item, rec.clone());

View File

@ -1,4 +1,6 @@
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::ty;
use rustc::hir::*;
use crate::utils::{match_def_path, opt_def_id, paths, span_help_and_lint};
@ -35,8 +37,8 @@ impl LintPass for InvalidRef {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidRef {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if_chain! {
if let ExprCall(ref path, ref args) = expr.node;
if let ExprPath(ref qpath) = path.node;
if let ExprKind::Call(ref path, ref args) = expr.node;
if let ExprKind::Path(ref qpath) = path.node;
if args.len() == 0;
if let ty::TyRef(..) = cx.tables.expr_ty(expr).sty;
if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id));

View File

@ -1,6 +1,8 @@
//! lint when items are used after statements
use matches::matches;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use syntax::ast::*;
use crate::utils::{in_macro, span_lint};
@ -41,7 +43,7 @@ impl LintPass for ItemsAfterStatements {
}
impl EarlyLintPass for ItemsAfterStatements {
fn check_block(&mut self, cx: &EarlyContext, item: &Block) {
fn check_block(&mut self, cx: &EarlyContext<'_>, item: &Block) {
if in_macro(item.span) {
return;
}

View File

@ -1,6 +1,7 @@
//! lint when there is a large size difference between variants on an enum
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::hir::*;
use crate::utils::{snippet_opt, span_lint_and_then};
use rustc::ty::layout::LayoutOf;
@ -47,9 +48,9 @@ impl LintPass for LargeEnumVariant {
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item) {
let did = cx.tcx.hir.local_def_id(item.id);
if let ItemEnum(ref def, _) = item.node {
if let ItemKind::Enum(ref def, _) = item.node {
let ty = cx.tcx.type_of(did);
let adt = ty.ty_adt_def()
.expect("already checked whether this is an enum");

View File

@ -1,6 +1,7 @@
use rustc::hir::def_id::DefId;
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::ty;
use std::collections::HashSet;
use syntax::ast::{Lit, LitKind, Name};
@ -68,8 +69,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero {
}
match item.node {
ItemTrait(_, _, _, _, ref trait_items) => check_trait_items(cx, item, trait_items),
ItemImpl(_, _, _, _, None, _, ref impl_items) => check_impl_items(cx, item, impl_items),
ItemKind::Trait(_, _, _, _, ref trait_items) => check_trait_items(cx, item, trait_items),
ItemKind::Impl(_, _, _, _, None, _, ref impl_items) => check_impl_items(cx, item, impl_items),
_ => (),
}
}
@ -79,34 +80,34 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero {
return;
}
if let ExprBinary(Spanned { node: cmp, .. }, ref left, ref right) = expr.node {
if let ExprKind::Binary(Spanned { node: cmp, .. }, ref left, ref right) = expr.node {
match cmp {
BiEq => {
BinOpKind::Eq => {
check_cmp(cx, expr.span, left, right, "", 0); // len == 0
check_cmp(cx, expr.span, right, left, "", 0); // 0 == len
},
BiNe => {
BinOpKind::Ne => {
check_cmp(cx, expr.span, left, right, "!", 0); // len != 0
check_cmp(cx, expr.span, right, left, "!", 0); // 0 != len
},
BiGt => {
BinOpKind::Gt => {
check_cmp(cx, expr.span, left, right, "!", 0); // len > 0
check_cmp(cx, expr.span, right, left, "", 1); // 1 > len
},
BiLt => {
BinOpKind::Lt => {
check_cmp(cx, expr.span, left, right, "", 1); // len < 1
check_cmp(cx, expr.span, right, left, "!", 0); // 0 < len
},
BiGe => check_cmp(cx, expr.span, left, right, "!", 1), // len <= 1
BiLe => check_cmp(cx, expr.span, right, left, "!", 1), // 1 >= len
BinOpKind::Ge => check_cmp(cx, expr.span, left, right, "!", 1), // len <= 1
BinOpKind::Le => check_cmp(cx, expr.span, right, left, "!", 1), // 1 >= len
_ => (),
}
}
}
}
fn check_trait_items(cx: &LateContext, visited_trait: &Item, trait_items: &[TraitItemRef]) {
fn is_named_self(cx: &LateContext, item: &TraitItemRef, name: &str) -> bool {
fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items: &[TraitItemRef]) {
fn is_named_self(cx: &LateContext<'_, '_>, item: &TraitItemRef, name: &str) -> bool {
item.ident.name == name && if let AssociatedItemKind::Method { has_self } = item.kind {
has_self && {
let did = cx.tcx.hir.local_def_id(item.id.node_id);
@ -118,7 +119,7 @@ fn check_trait_items(cx: &LateContext, visited_trait: &Item, trait_items: &[Trai
}
// fill the set with current and super traits
fn fill_trait_set(traitt: DefId, set: &mut HashSet<DefId>, cx: &LateContext) {
fn fill_trait_set(traitt: DefId, set: &mut HashSet<DefId>, cx: &LateContext<'_, '_>) {
if set.insert(traitt) {
for supertrait in ::rustc::traits::supertrait_def_ids(cx.tcx, traitt) {
fill_trait_set(supertrait, set, cx);
@ -153,8 +154,8 @@ fn check_trait_items(cx: &LateContext, visited_trait: &Item, trait_items: &[Trai
}
}
fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItemRef]) {
fn is_named_self(cx: &LateContext, item: &ImplItemRef, name: &str) -> bool {
fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item, impl_items: &[ImplItemRef]) {
fn is_named_self(cx: &LateContext<'_, '_>, item: &ImplItemRef, name: &str) -> bool {
item.ident.name == name && if let AssociatedItemKind::Method { has_self } = item.kind {
has_self && {
let did = cx.tcx.hir.local_def_id(item.id.node_id);
@ -193,8 +194,8 @@ fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItemRef]) {
}
}
fn check_cmp(cx: &LateContext, span: Span, method: &Expr, lit: &Expr, op: &str, compare_to: u32) {
if let (&ExprMethodCall(ref method_path, _, ref args), &ExprLit(ref lit)) = (&method.node, &lit.node) {
fn check_cmp(cx: &LateContext<'_, '_>, span: Span, method: &Expr, lit: &Expr, op: &str, compare_to: u32) {
if let (&ExprKind::MethodCall(ref method_path, _, ref args), &ExprKind::Lit(ref lit)) = (&method.node, &lit.node) {
// check if we are in an is_empty() method
if let Some(name) = get_item_name(cx, method) {
if name == "is_empty" {
@ -206,7 +207,7 @@ fn check_cmp(cx: &LateContext, span: Span, method: &Expr, lit: &Expr, op: &str,
}
}
fn check_len(cx: &LateContext, span: Span, method_name: Name, args: &[Expr], lit: &Lit, op: &str, compare_to: u32) {
fn check_len(cx: &LateContext<'_, '_>, span: Span, method_name: Name, args: &[Expr], lit: &Lit, op: &str, compare_to: u32) {
if let Spanned {
node: LitKind::Int(lit, _),
..
@ -231,9 +232,9 @@ fn check_len(cx: &LateContext, span: Span, method_name: Name, args: &[Expr], lit
}
/// Check if this type has an `is_empty` method.
fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool {
fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
/// Get an `AssociatedItem` and return true if it matches `is_empty(self)`.
fn is_is_empty(cx: &LateContext, item: &ty::AssociatedItem) -> bool {
fn is_is_empty(cx: &LateContext<'_, '_>, item: &ty::AssociatedItem) -> bool {
if let ty::AssociatedKind::Method = item.kind {
if item.ident.name == "is_empty" {
let sig = cx.tcx.fn_sig(item.def_id);
@ -248,7 +249,7 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool {
}
/// Check the inherent impl's items for an `is_empty(self)` method.
fn has_is_empty_impl(cx: &LateContext, id: DefId) -> bool {
fn has_is_empty_impl(cx: &LateContext<'_, '_>, id: DefId) -> bool {
cx.tcx.inherent_impls(id).iter().any(|imp| {
cx.tcx
.associated_items(*imp)
@ -258,11 +259,10 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool {
let ty = &walk_ptrs_ty(cx.tables.expr_ty(expr));
match ty.sty {
ty::TyDynamic(..) => cx.tcx
.associated_items(ty.ty_to_def_id().expect("trait impl not found"))
ty::TyDynamic(ref tt, ..) => cx.tcx
.associated_items(tt.principal().expect("trait impl not found").def_id())
.any(|item| is_is_empty(cx, &item)),
ty::TyProjection(_) => ty.ty_to_def_id()
.map_or(false, |id| has_is_empty_impl(cx, id)),
ty::TyProjection(ref proj) => has_is_empty_impl(cx, proj.item_def_id),
ty::TyAdt(id, _) => has_is_empty_impl(cx, id.did),
ty::TyArray(..) | ty::TySlice(..) | ty::TyStr => true,
_ => false,

View File

@ -1,4 +1,6 @@
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::hir;
use rustc::hir::BindingAnnotation;
use rustc::hir::def::Def;
@ -65,20 +67,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq {
while let Some(stmt) = it.next() {
if_chain! {
if let Some(expr) = it.peek();
if let hir::StmtDecl(ref decl, _) = stmt.node;
if let hir::DeclLocal(ref decl) = decl.node;
if let hir::StmtKind::Decl(ref decl, _) = stmt.node;
if let hir::DeclKind::Local(ref decl) = decl.node;
if let hir::PatKind::Binding(mode, canonical_id, ident, None) = decl.pat.node;
if let hir::StmtExpr(ref if_, _) = expr.node;
if let hir::ExprIf(ref cond, ref then, ref else_) = if_.node;
if let hir::StmtKind::Expr(ref if_, _) = expr.node;
if let hir::ExprKind::If(ref cond, ref then, ref else_) = if_.node;
if !used_in_expr(cx, canonical_id, cond);
if let hir::ExprBlock(ref then, _) = then.node;
if let hir::ExprKind::Block(ref then, _) = then.node;
if let Some(value) = check_assign(cx, canonical_id, &*then);
if !used_in_expr(cx, canonical_id, value);
then {
let span = stmt.span.to(if_.span);
let (default_multi_stmts, default) = if let Some(ref else_) = *else_ {
if let hir::ExprBlock(ref else_, _) = else_.node {
if let hir::ExprKind::Block(ref else_, _) = else_.node {
if let Some(default) = check_assign(cx, canonical_id, else_) {
(else_.stmts.len() > 1, default)
} else if let Some(ref default) = decl.init {
@ -140,7 +142,7 @@ struct UsedVisitor<'a, 'tcx: 'a> {
impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UsedVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
if_chain! {
if let hir::ExprPath(ref qpath) = expr.node;
if let hir::ExprKind::Path(ref qpath) = expr.node;
if let Def::Local(local_id) = self.cx.tables.qpath_def(qpath, expr.hir_id);
if self.id == local_id;
then {
@ -163,9 +165,9 @@ fn check_assign<'a, 'tcx>(
if_chain! {
if block.expr.is_none();
if let Some(expr) = block.stmts.iter().last();
if let hir::StmtSemi(ref expr, _) = expr.node;
if let hir::ExprAssign(ref var, ref value) = expr.node;
if let hir::ExprPath(ref qpath) = var.node;
if let hir::StmtKind::Semi(ref expr, _) = expr.node;
if let hir::ExprKind::Assign(ref var, ref value) = expr.node;
if let hir::ExprKind::Path(ref qpath) = var.node;
if let Def::Local(local_id) = cx.tables.qpath_def(qpath, var.hir_id);
if decl == local_id;
then {

View File

@ -14,54 +14,41 @@
#![feature(rust_2018_preview)]
#![warn(rust_2018_idioms)]
#[macro_use]
extern crate rustc;
use toml;
use rustc_plugin;
use rustc;
#[macro_use]
extern crate matches as matches_macro;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate if_chain;
macro_rules! declare_clippy_lint {
{ pub $name:tt, style, $description:tt } => {
declare_lint! { pub $name, Warn, $description }
declare_lint! { pub $name, Warn, $description, report_in_external_macro: true }
};
{ pub $name:tt, correctness, $description:tt } => {
declare_lint! { pub $name, Deny, $description }
declare_lint! { pub $name, Deny, $description, report_in_external_macro: true }
};
{ pub $name:tt, complexity, $description:tt } => {
declare_lint! { pub $name, Warn, $description }
declare_lint! { pub $name, Warn, $description, report_in_external_macro: true }
};
{ pub $name:tt, perf, $description:tt } => {
declare_lint! { pub $name, Warn, $description }
declare_lint! { pub $name, Warn, $description, report_in_external_macro: true }
};
{ pub $name:tt, pedantic, $description:tt } => {
declare_lint! { pub $name, Allow, $description }
declare_lint! { pub $name, Allow, $description, report_in_external_macro: true }
};
{ pub $name:tt, restriction, $description:tt } => {
declare_lint! { pub $name, Allow, $description }
declare_lint! { pub $name, Allow, $description, report_in_external_macro: true }
};
{ pub $name:tt, cargo, $description:tt } => {
declare_lint! { pub $name, Allow, $description }
declare_lint! { pub $name, Allow, $description, report_in_external_macro: true }
};
{ pub $name:tt, nursery, $description:tt } => {
declare_lint! { pub $name, Allow, $description }
declare_lint! { pub $name, Allow, $description, report_in_external_macro: true }
};
{ pub $name:tt, internal, $description:tt } => {
declare_lint! { pub $name, Allow, $description }
declare_lint! { pub $name, Allow, $description, report_in_external_macro: true }
};
{ pub $name:tt, internal_warn, $description:tt } => {
declare_lint! { pub $name, Warn, $description }
declare_lint! { pub $name, Warn, $description, report_in_external_macro: true }
};
}
@ -134,6 +121,7 @@ pub mod minmax;
pub mod misc;
pub mod misc_early;
pub mod missing_doc;
pub mod missing_inline;
pub mod multiple_crate_versions;
pub mod mut_mut;
pub mod mut_reference;
@ -188,8 +176,12 @@ mod reexport {
crate use syntax::ast::{Name, NodeId};
}
pub fn register_pre_expansion_lints(session: &rustc::session::Session, store: &mut rustc::lint::LintStore) {
store.register_pre_expansion_pass(Some(session), box write::Pass);
}
#[cfg_attr(rustfmt, rustfmt_skip)]
pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>) {
let conf = match utils::conf::file_from_args(reg.args()) {
Ok(file_name) => {
// if the user specified a file, it must exist, otherwise default to `clippy.toml` but
@ -333,7 +325,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
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_late_lint_pass(box write::Pass);
reg.register_late_lint_pass(box vec::Pass);
reg.register_early_lint_pass(box non_expressive_names::NonExpressiveNames {
single_char_binding_names_threshold: conf.single_char_binding_names_threshold,
@ -364,6 +355,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
reg.register_late_lint_pass(box let_if_seq::LetIfSeq);
reg.register_late_lint_pass(box eval_order_dependence::EvalOrderDependence);
reg.register_late_lint_pass(box missing_doc::MissingDoc::new());
reg.register_late_lint_pass(box missing_inline::MissingInline);
reg.register_late_lint_pass(box ok_if_let::Pass);
reg.register_late_lint_pass(box if_let_redundant_pattern_matching::Pass);
reg.register_late_lint_pass(box partialeq_ne_impl::Pass);
@ -422,6 +414,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
methods::WRONG_PUB_SELF_CONVENTION,
misc::FLOAT_CMP_CONST,
missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS,
missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS,
panic_unimplemented::UNIMPLEMENTED,
shadow::SHADOW_REUSE,
shadow::SHADOW_SAME,

View File

@ -1,11 +1,13 @@
use crate::reexport::*;
use matches::matches;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::hir::def::Def;
use rustc::hir::*;
use rustc::hir::intravisit::*;
use std::collections::{HashMap, HashSet};
use syntax::codemap::Span;
use crate::utils::{in_external_macro, last_path_segment, span_lint};
use crate::utils::{last_path_segment, span_lint};
use syntax::symbol::keywords;
/// **What it does:** Checks for lifetime annotations which can be removed by
@ -59,7 +61,7 @@ impl LintPass for LifetimePass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LifetimePass {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if let ItemFn(ref decl, _, ref generics, id) = item.node {
if let ItemKind::Fn(ref decl, _, ref generics, id) = item.node {
check_fn_inner(cx, decl, Some(id), generics, item.span);
}
}
@ -96,7 +98,7 @@ fn check_fn_inner<'a, 'tcx>(
generics: &'tcx Generics,
span: Span,
) {
if in_external_macro(cx, span) || has_where_lifetimes(cx, &generics.where_clause) {
if in_external_macro(cx.sess(), span) || has_where_lifetimes(cx, &generics.where_clause) {
return;
}
@ -126,7 +128,7 @@ fn check_fn_inner<'a, 'tcx>(
GenericArg::Type(_) => None,
});
for bound in lifetimes {
if bound.name.ident().name != "'static" && !bound.is_elided() {
if bound.name != LifetimeName::Static && !bound.is_elided() {
return;
}
bounds_lts.push(bound);
@ -251,7 +253,7 @@ fn allowed_lts_from(named_generics: &[GenericParam]) -> HashSet<RefLt> {
fn lts_from_bounds<'a, T: Iterator<Item = &'a Lifetime>>(mut vec: Vec<RefLt>, bounds_lts: T) -> Vec<RefLt> {
for lt in bounds_lts {
if lt.name.ident().name != "'static" {
if lt.name != LifetimeName::Static {
vec.push(RefLt::Named(lt.name.ident().name));
}
}
@ -282,7 +284,7 @@ impl<'v, 't> RefVisitor<'v, 't> {
fn record(&mut self, lifetime: &Option<Lifetime>) {
if let Some(ref lt) = *lifetime {
if lt.name.ident().name == "'static" {
if lt.name == LifetimeName::Static {
self.lts.push(RefLt::Static);
} else if lt.is_elided() {
self.lts.push(RefLt::Unnamed);
@ -338,22 +340,29 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
fn visit_ty(&mut self, ty: &'tcx Ty) {
match ty.node {
TyRptr(ref lt, _) if lt.is_elided() => {
TyKind::Rptr(ref lt, _) if lt.is_elided() => {
self.record(&None);
},
TyPath(ref path) => {
self.collect_anonymous_lifetimes(path, ty);
},
TyImplTraitExistential(exist_ty_id, _, _) => {
if let ItemExistential(ref exist_ty) = self.cx.tcx.hir.expect_item(exist_ty_id.id).node {
for bound in &exist_ty.bounds {
if let GenericBound::Outlives(_) = *bound {
self.record(&None);
TyKind::Path(ref path) => {
if let QPath::Resolved(_, ref path) = *path {
if let Def::Existential(def_id) = path.def {
let node_id = self.cx.tcx.hir.as_local_node_id(def_id).unwrap();
if let ItemKind::Existential(ref exist_ty) = self.cx.tcx.hir.expect_item(node_id).node {
for bound in &exist_ty.bounds {
if let GenericBound::Outlives(_) = *bound {
self.record(&None);
}
}
} else {
unreachable!()
}
walk_ty(self, ty);
return;
}
}
self.collect_anonymous_lifetimes(path, ty);
}
TyTraitObject(ref bounds, ref lt) => {
TyKind::TraitObject(ref bounds, ref lt) => {
if !lt.is_elided() {
self.abort = true;
}

View File

@ -2,9 +2,11 @@
//! floating-point literal expressions.
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use syntax::ast::*;
use syntax_pos;
use crate::utils::{in_external_macro, snippet_opt, span_lint_and_sugg};
use crate::utils::{snippet_opt, span_lint_and_sugg};
/// **What it does:** Warns if a long integral or floating-point constant does
/// not contain underscores.
@ -227,7 +229,7 @@ enum WarningType {
}
impl WarningType {
crate fn display(&self, grouping_hint: &str, cx: &EarlyContext, span: syntax_pos::Span) {
crate fn display(&self, grouping_hint: &str, cx: &EarlyContext<'_>, span: syntax_pos::Span) {
match self {
WarningType::UnreadableLiteral => span_lint_and_sugg(
cx,
@ -279,8 +281,8 @@ impl LintPass for LiteralDigitGrouping {
}
impl EarlyLintPass for LiteralDigitGrouping {
fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
if in_external_macro(cx, expr.span) {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
if in_external_macro(cx.sess(), expr.span) {
return;
}
@ -291,7 +293,7 @@ impl EarlyLintPass for LiteralDigitGrouping {
}
impl LiteralDigitGrouping {
fn check_lit(self, cx: &EarlyContext, lit: &Lit) {
fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) {
match lit.node {
LitKind::Int(..) => {
// Lint integral literals.
@ -419,8 +421,8 @@ impl LintPass for LiteralRepresentation {
}
impl EarlyLintPass for LiteralRepresentation {
fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
if in_external_macro(cx, expr.span) {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
if in_external_macro(cx.sess(), expr.span) {
return;
}
@ -436,7 +438,7 @@ impl LiteralRepresentation {
threshold,
}
}
fn check_lit(self, cx: &EarlyContext, lit: &Lit) {
fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) {
// Lint integral literals.
if_chain! {
if let LitKind::Int(..) = lit.node;

View File

@ -6,6 +6,8 @@ use rustc::hir::def_id;
use rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor};
use rustc::hir::map::Node::{NodeBlock, NodeExpr, NodeStmt};
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::middle::region;
// use rustc::middle::region::CodeExtent;
use rustc::middle::expr_use_visitor::*;
@ -21,9 +23,9 @@ use crate::utils::{sugg, sext};
use crate::utils::usage::mutated_variables;
use crate::consts::{constant, Constant};
use crate::utils::{get_enclosing_block, get_parent_expr, higher, in_external_macro, is_integer_literal, is_refutable,
use crate::utils::{get_enclosing_block, get_parent_expr, higher, is_integer_literal, is_refutable,
last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, snippet, snippet_opt,
span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then};
span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, SpanlessEq};
use crate::utils::paths;
/// **What it does:** Checks for for-loops that manually copy items between
@ -411,7 +413,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
// check for never_loop
match expr.node {
ExprWhile(_, ref block, _) | ExprLoop(ref block, _, _) => {
ExprKind::While(_, ref block, _) | ExprKind::Loop(ref block, _, _) => {
match never_loop_block(block, expr.id) {
NeverLoopResult::AlwaysBreak =>
span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"),
@ -424,7 +426,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
// check for `loop { if let {} else break }` that could be `while let`
// (also matches an explicit "match" instead of "if let")
// (even if the "match" or "if let" is used for declaration)
if let ExprLoop(ref block, _, LoopSource::Loop) = expr.node {
if let ExprKind::Loop(ref block, _, LoopSource::Loop) = expr.node {
// also check for empty `loop {}` statements
if block.stmts.is_empty() && block.expr.is_none() {
span_lint(
@ -440,7 +442,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
let inner_stmt_expr = extract_expr_from_first_stmt(block);
// or extract the first expression (if any) from the block
if let Some(inner) = inner_stmt_expr.or_else(|| extract_first_expr(block)) {
if let ExprMatch(ref matchexpr, ref arms, ref source) = inner.node {
if let ExprKind::Match(ref matchexpr, ref arms, ref source) = inner.node {
// ensure "if let" compatible match structure
match *source {
MatchSource::Normal | MatchSource::IfLetDesugar { .. } => {
@ -448,7 +450,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
&& arms[1].pats.len() == 1 && arms[1].guard.is_none()
&& is_simple_break_expr(&arms[1].body)
{
if in_external_macro(cx, expr.span) {
if in_external_macro(cx.sess(), expr.span) {
return;
}
@ -476,11 +478,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
}
}
}
if let ExprMatch(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node {
if let ExprKind::Match(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node {
let pat = &arms[0].pats[0].node;
if let (
&PatKind::TupleStruct(ref qpath, ref pat_args, _),
&ExprMethodCall(ref method_path, _, ref method_args),
&ExprKind::MethodCall(ref method_path, _, ref method_args),
) = (pat, &match_expr.node)
{
let iter_expr = &method_args[0];
@ -505,14 +507,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
}
// check for while loops which conditions never change
if let ExprWhile(ref cond, _, _) = expr.node {
if let ExprKind::While(ref cond, _, _) = expr.node {
check_infinite_loop(cx, cond, expr);
}
}
fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) {
if let StmtSemi(ref expr, _) = stmt.node {
if let ExprMethodCall(ref method, _, ref args) = expr.node {
if let StmtKind::Semi(ref expr, _) = stmt.node {
if let ExprKind::MethodCall(ref method, _, ref args) = expr.node {
if args.len() == 1 && method.ident.name == "collect" && match_trait_method(cx, expr, &paths::ITERATOR) {
span_lint(
cx,
@ -584,53 +586,53 @@ fn never_loop_block(block: &Block, main_loop_id: NodeId) -> NeverLoopResult {
fn stmt_to_expr(stmt: &Stmt) -> Option<&Expr> {
match stmt.node {
StmtSemi(ref e, ..) | StmtExpr(ref e, ..) => Some(e),
StmtDecl(ref d, ..) => decl_to_expr(d),
StmtKind::Semi(ref e, ..) | StmtKind::Expr(ref e, ..) => Some(e),
StmtKind::Decl(ref d, ..) => decl_to_expr(d),
}
}
fn decl_to_expr(decl: &Decl) -> Option<&Expr> {
match decl.node {
DeclLocal(ref local) => local.init.as_ref().map(|p| &**p),
DeclKind::Local(ref local) => local.init.as_ref().map(|p| &**p),
_ => None,
}
}
fn never_loop_expr(expr: &Expr, main_loop_id: NodeId) -> NeverLoopResult {
match expr.node {
ExprBox(ref e) |
ExprUnary(_, ref e) |
ExprCast(ref e, _) |
ExprType(ref e, _) |
ExprField(ref e, _) |
ExprAddrOf(_, ref e) |
ExprStruct(_, _, Some(ref e)) |
ExprRepeat(ref e, _) => never_loop_expr(e, main_loop_id),
ExprArray(ref es) | ExprMethodCall(_, _, ref es) | ExprTup(ref es) => {
ExprKind::Box(ref e) |
ExprKind::Unary(_, ref e) |
ExprKind::Cast(ref e, _) |
ExprKind::Type(ref e, _) |
ExprKind::Field(ref e, _) |
ExprKind::AddrOf(_, ref e) |
ExprKind::Struct(_, _, Some(ref e)) |
ExprKind::Repeat(ref e, _) => never_loop_expr(e, main_loop_id),
ExprKind::Array(ref es) | ExprKind::MethodCall(_, _, ref es) | ExprKind::Tup(ref es) => {
never_loop_expr_all(&mut es.iter(), main_loop_id)
},
ExprCall(ref e, ref es) => never_loop_expr_all(&mut once(&**e).chain(es.iter()), main_loop_id),
ExprBinary(_, ref e1, ref e2) |
ExprAssign(ref e1, ref e2) |
ExprAssignOp(_, ref e1, ref e2) |
ExprIndex(ref e1, ref e2) => never_loop_expr_all(&mut [&**e1, &**e2].iter().cloned(), main_loop_id),
ExprIf(ref e, ref e2, ref e3) => {
ExprKind::Call(ref e, ref es) => never_loop_expr_all(&mut once(&**e).chain(es.iter()), main_loop_id),
ExprKind::Binary(_, ref e1, ref e2) |
ExprKind::Assign(ref e1, ref e2) |
ExprKind::AssignOp(_, ref e1, ref e2) |
ExprKind::Index(ref e1, ref e2) => never_loop_expr_all(&mut [&**e1, &**e2].iter().cloned(), main_loop_id),
ExprKind::If(ref e, ref e2, ref e3) => {
let e1 = never_loop_expr(e, main_loop_id);
let e2 = never_loop_expr(e2, main_loop_id);
let e3 = e3.as_ref().map_or(NeverLoopResult::Otherwise, |e| never_loop_expr(e, main_loop_id));
combine_seq(e1, combine_branches(e2, e3))
},
ExprLoop(ref b, _, _) => {
ExprKind::Loop(ref b, _, _) => {
// Break can come from the inner loop so remove them.
absorb_break(&never_loop_block(b, main_loop_id))
},
ExprWhile(ref e, ref b, _) => {
ExprKind::While(ref e, ref b, _) => {
let e = never_loop_expr(e, main_loop_id);
let result = never_loop_block(b, main_loop_id);
// Break can come from the inner loop so remove them.
combine_seq(e, absorb_break(&result))
},
ExprMatch(ref e, ref arms, _) => {
ExprKind::Match(ref e, ref arms, _) => {
let e = never_loop_expr(e, main_loop_id);
if arms.is_empty() {
e
@ -639,8 +641,8 @@ fn never_loop_expr(expr: &Expr, main_loop_id: NodeId) -> NeverLoopResult {
combine_seq(e, arms)
}
},
ExprBlock(ref b, _) => never_loop_block(b, main_loop_id),
ExprContinue(d) => {
ExprKind::Block(ref b, _) => never_loop_block(b, main_loop_id),
ExprKind::Continue(d) => {
let id = d.target_id
.expect("target id can only be missing in the presence of compilation errors");
if id == main_loop_id {
@ -649,22 +651,22 @@ fn never_loop_expr(expr: &Expr, main_loop_id: NodeId) -> NeverLoopResult {
NeverLoopResult::AlwaysBreak
}
},
ExprBreak(_, _) => {
ExprKind::Break(_, _) => {
NeverLoopResult::AlwaysBreak
},
ExprRet(ref e) => {
ExprKind::Ret(ref e) => {
if let Some(ref e) = *e {
combine_seq(never_loop_expr(e, main_loop_id), NeverLoopResult::AlwaysBreak)
} else {
NeverLoopResult::AlwaysBreak
}
},
ExprStruct(_, _, None) |
ExprYield(_) |
ExprClosure(_, _, _, _, _) |
ExprInlineAsm(_, _, _) |
ExprPath(_) |
ExprLit(_) => NeverLoopResult::Otherwise,
ExprKind::Struct(_, _, None) |
ExprKind::Yield(_) |
ExprKind::Closure(_, _, _, _, _) |
ExprKind::InlineAsm(_, _, _) |
ExprKind::Path(_) |
ExprKind::Lit(_) => NeverLoopResult::Otherwise,
}
}
@ -701,7 +703,7 @@ fn check_for_loop<'a, 'tcx>(
fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: ast::NodeId) -> bool {
if_chain! {
if let ExprPath(ref qpath) = expr.node;
if let ExprKind::Path(ref qpath) = expr.node;
if let QPath::Resolved(None, ref path) = *qpath;
if path.segments.len() == 1;
if let Def::Local(local_id) = cx.tables.qpath_def(qpath, expr.hir_id);
@ -741,7 +743,7 @@ struct FixedOffsetVar {
offset: Offset,
}
fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty) -> bool {
fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'_>) -> bool {
let is_slice = match ty.sty {
ty::TyRef(_, subty, _) => is_slice_like(cx, subty),
ty::TySlice(..) | ty::TyArray(..) => true,
@ -754,24 +756,24 @@ fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty) -> bool {
fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: ast::NodeId) -> Option<FixedOffsetVar> {
fn extract_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &Expr, var: ast::NodeId) -> Option<String> {
match e.node {
ExprLit(ref l) => match l.node {
ExprKind::Lit(ref l) => match l.node {
ast::LitKind::Int(x, _ty) => Some(x.to_string()),
_ => None,
},
ExprPath(..) if !same_var(cx, e, var) => Some(snippet_opt(cx, e.span).unwrap_or_else(|| "??".into())),
ExprKind::Path(..) if !same_var(cx, e, var) => Some(snippet_opt(cx, e.span).unwrap_or_else(|| "??".into())),
_ => None,
}
}
if let ExprIndex(ref seqexpr, ref idx) = expr.node {
if let ExprKind::Index(ref seqexpr, ref idx) = expr.node {
let ty = cx.tables.expr_ty(seqexpr);
if !is_slice_like(cx, ty) {
return None;
}
let offset = match idx.node {
ExprBinary(op, ref lhs, ref rhs) => match op.node {
BinOp_::BiAdd => {
ExprKind::Binary(op, ref lhs, ref rhs) => match op.node {
BinOpKind::Add => {
let offset_opt = if same_var(cx, lhs, var) {
extract_offset(cx, rhs, var)
} else if same_var(cx, rhs, var) {
@ -782,10 +784,10 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var:
offset_opt.map(Offset::positive)
},
BinOp_::BiSub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative),
BinOpKind::Sub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative),
_ => None,
},
ExprPath(..) => if same_var(cx, idx, var) {
ExprKind::Path(..) => if same_var(cx, idx, var) {
Some(Offset::positive("0".into()))
} else {
None
@ -810,7 +812,7 @@ fn fetch_cloned_fixed_offset_var<'a, 'tcx>(
var: ast::NodeId,
) -> Option<FixedOffsetVar> {
if_chain! {
if let ExprMethodCall(ref method, _, ref args) = expr.node;
if let ExprKind::MethodCall(ref method, _, ref args) = expr.node;
if method.ident.name == "clone";
if args.len() == 1;
if let Some(arg) = args.get(0);
@ -832,7 +834,7 @@ fn get_indexed_assignments<'a, 'tcx>(
e: &Expr,
var: ast::NodeId,
) -> Option<(FixedOffsetVar, FixedOffsetVar)> {
if let Expr_::ExprAssign(ref lhs, ref rhs) = e.node {
if let ExprKind::Assign(ref lhs, ref rhs) = e.node {
match (get_fixed_offset_var(cx, lhs, var), fetch_cloned_fixed_offset_var(cx, rhs, var)) {
(Some(offset_left), Some(offset_right)) => {
// Source and destination must be different
@ -849,7 +851,7 @@ fn get_indexed_assignments<'a, 'tcx>(
}
}
if let Expr_::ExprBlock(ref b, _) = body.node {
if let ExprKind::Block(ref b, _) = body.node {
let Block {
ref stmts,
ref expr,
@ -859,8 +861,8 @@ fn get_indexed_assignments<'a, 'tcx>(
stmts
.iter()
.map(|stmt| match stmt.node {
Stmt_::StmtDecl(..) => None,
Stmt_::StmtExpr(ref e, _node_id) | Stmt_::StmtSemi(ref e, _node_id) => Some(get_assignment(cx, e, var)),
StmtKind::Decl(..) => None,
StmtKind::Expr(ref e, _node_id) | StmtKind::Semi(ref e, _node_id) => Some(get_assignment(cx, e, var)),
})
.chain(
expr.as_ref()
@ -906,7 +908,7 @@ fn detect_manual_memcpy<'a, 'tcx>(
let print_limit = |end: &Option<&Expr>, offset: Offset, var_name: &str| if let Some(end) = *end {
if_chain! {
if let ExprMethodCall(ref method, _, ref len_args) = end.node;
if let ExprKind::MethodCall(ref method, _, ref len_args) = end.node;
if method.ident.name == "len";
if len_args.len() == 1;
if let Some(arg) = len_args.get(0);
@ -1098,10 +1100,10 @@ fn check_for_loop_range<'a, 'tcx>(
fn is_len_call(expr: &Expr, var: Name) -> bool {
if_chain! {
if let ExprMethodCall(ref method, _, ref len_args) = expr.node;
if let ExprKind::MethodCall(ref method, _, ref len_args) = expr.node;
if len_args.len() == 1;
if method.ident.name == "len";
if let ExprPath(QPath::Resolved(_, ref path)) = len_args[0].node;
if let ExprKind::Path(QPath::Resolved(_, ref path)) = len_args[0].node;
if path.segments.len() == 1;
if path.segments[0].ident.name == var;
then {
@ -1183,7 +1185,7 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx
}
}
fn lint_iter_method(cx: &LateContext, args: &[Expr], arg: &Expr, method_name: &str) {
fn lint_iter_method(cx: &LateContext<'_, '_>, args: &[Expr], arg: &Expr, method_name: &str) {
let object = snippet(cx, args[0].span, "_");
let muta = if method_name == "iter_mut" {
"mut "
@ -1201,9 +1203,9 @@ fn lint_iter_method(cx: &LateContext, args: &[Expr], arg: &Expr, method_name: &s
)
}
fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) {
fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr, expr: &Expr) {
let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used
if let ExprMethodCall(ref method, _, ref args) = arg.node {
if let ExprKind::MethodCall(ref method, _, ref args) = arg.node {
// just the receiver, no arguments
if args.len() == 1 {
let method_name = &*method.ident.as_str();
@ -1256,7 +1258,7 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) {
}
/// Check for `for` loops over `Option`s and `Results`
fn check_arg_type(cx: &LateContext, pat: &Pat, arg: &Expr) {
fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr) {
let ty = cx.tables.expr_ty(arg);
if match_type(cx, ty, &paths::OPTION) {
span_help_and_lint(
@ -1377,7 +1379,7 @@ fn check_for_loop_over_map_kv<'a, 'tcx>(
MutMutable => "_mut",
};
let arg = match arg.node {
ExprAddrOf(_, ref expr) => &**expr,
ExprKind::AddrOf(_, ref expr) => &**expr,
_ => arg,
};
@ -1418,7 +1420,7 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate {
fn consume_pat(&mut self, _: &Pat, _: &cmt_<'tcx>, _: ConsumeMode) {}
fn borrow(&mut self, _: NodeId, sp: Span, cmt: &cmt_<'tcx>, _: ty::Region, bk: ty::BorrowKind, _: LoanCause) {
fn borrow(&mut self, _: NodeId, sp: Span, cmt: &cmt_<'tcx>, _: ty::Region<'_>, bk: ty::BorrowKind, _: LoanCause) {
if let ty::BorrowKind::MutBorrow = bk {
if let Categorization::Local(id) = cmt.cat {
if Some(id) == self.node_id_low {
@ -1451,7 +1453,7 @@ impl<'tcx> MutatePairDelegate {
}
}
fn check_for_mut_range_bound(cx: &LateContext, arg: &Expr, body: &Expr) {
fn check_for_mut_range_bound(cx: &LateContext<'_, '_>, arg: &Expr, body: &Expr) {
if let Some(higher::Range {
start: Some(start),
end: Some(end),
@ -1470,7 +1472,7 @@ fn check_for_mut_range_bound(cx: &LateContext, arg: &Expr, body: &Expr) {
}
}
fn mut_warn_with_span(cx: &LateContext, span: Option<Span>) {
fn mut_warn_with_span(cx: &LateContext<'_, '_>, span: Option<Span>) {
if let Some(sp) = span {
span_lint(
cx,
@ -1481,9 +1483,9 @@ fn mut_warn_with_span(cx: &LateContext, span: Option<Span>) {
}
}
fn check_for_mutability(cx: &LateContext, bound: &Expr) -> Option<NodeId> {
fn check_for_mutability(cx: &LateContext<'_, '_>, bound: &Expr) -> Option<NodeId> {
if_chain! {
if let ExprPath(ref qpath) = bound.node;
if let ExprKind::Path(ref qpath) = bound.node;
if let QPath::Resolved(None, _) = *qpath;
then {
let def = cx.tables.qpath_def(qpath, bound.hir_id);
@ -1503,7 +1505,7 @@ fn check_for_mutability(cx: &LateContext, bound: &Expr) -> Option<NodeId> {
None
}
fn check_for_mutation(cx: &LateContext, body: &Expr, bound_ids: &[Option<NodeId>]) -> (Option<Span>, Option<Span>) {
fn check_for_mutation(cx: &LateContext<'_, '_>, body: &Expr, bound_ids: &[Option<NodeId>]) -> (Option<Span>, Option<Span>) {
let mut delegate = MutatePairDelegate {
node_id_low: bound_ids[0],
node_id_high: bound_ids[1],
@ -1598,7 +1600,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
fn check(&mut self, idx: &'tcx Expr, seqexpr: &'tcx Expr, expr: &'tcx Expr) -> bool {
if_chain! {
// the indexed container is referenced by a name
if let ExprPath(ref seqpath) = seqexpr.node;
if let ExprKind::Path(ref seqpath) = seqexpr.node;
if let QPath::Resolved(None, ref seqvar) = *seqpath;
if seqvar.segments.len() == 1;
then {
@ -1655,7 +1657,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr) {
if_chain! {
// a range index op
if let ExprMethodCall(ref meth, _, ref args) = expr.node;
if let ExprKind::MethodCall(ref meth, _, ref args) = expr.node;
if (meth.ident.name == "index" && match_trait_method(self.cx, expr, &paths::INDEX))
|| (meth.ident.name == "index_mut" && match_trait_method(self.cx, expr, &paths::INDEX_MUT));
if !self.check(&args[1], &args[0], expr);
@ -1664,14 +1666,14 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
if_chain! {
// an index op
if let ExprIndex(ref seqexpr, ref idx) = expr.node;
if let ExprKind::Index(ref seqexpr, ref idx) = expr.node;
if !self.check(idx, seqexpr, expr);
then { return }
}
if_chain! {
// directly using a variable
if let ExprPath(ref qpath) = expr.node;
if let ExprKind::Path(ref qpath) = expr.node;
if let QPath::Resolved(None, ref path) = *qpath;
if path.segments.len() == 1;
if let Def::Local(local_id) = self.cx.tables.qpath_def(qpath, expr.hir_id);
@ -1687,20 +1689,20 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
}
let old = self.prefer_mutable;
match expr.node {
ExprAssignOp(_, ref lhs, ref rhs) |
ExprAssign(ref lhs, ref rhs) => {
ExprKind::AssignOp(_, ref lhs, ref rhs) |
ExprKind::Assign(ref lhs, ref rhs) => {
self.prefer_mutable = true;
self.visit_expr(lhs);
self.prefer_mutable = false;
self.visit_expr(rhs);
},
ExprAddrOf(mutbl, ref expr) => {
ExprKind::AddrOf(mutbl, ref expr) => {
if mutbl == MutMutable {
self.prefer_mutable = true;
}
self.visit_expr(expr);
},
ExprCall(ref f, ref args) => {
ExprKind::Call(ref f, ref args) => {
self.visit_expr(f);
for expr in args {
let ty = self.cx.tables.expr_ty_adjusted(expr);
@ -1713,7 +1715,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
self.visit_expr(expr);
}
},
ExprMethodCall(_, _, ref args) => {
ExprKind::MethodCall(_, _, ref args) => {
let def_id = self.cx.tables.type_dependent_defs()[expr.hir_id].def_id();
for (ty, expr) in self.cx.tcx.fn_sig(def_id).inputs().skip_binder().iter().zip(args) {
self.prefer_mutable = false;
@ -1780,7 +1782,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarUsedAfterLoopVisitor<'a, 'tcx> {
/// Return true if the type of expr is one that provides `IntoIterator` impls
/// for `&T` and `&mut T`, such as `Vec`.
#[cfg_attr(rustfmt, rustfmt_skip)]
fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool {
fn is_ref_iterable_type(cx: &LateContext<'_, '_>, e: &Expr) -> bool {
// no walk_ptrs_ty: calling iter() on a reference can make sense because it
// will allow further borrows afterwards
let ty = cx.tables.expr_ty(e);
@ -1795,7 +1797,7 @@ fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool {
match_type(cx, ty, &paths::BTREESET)
}
fn is_iterable_array(ty: Ty, cx: &LateContext) -> bool {
fn is_iterable_array(ty: Ty<'_>, cx: &LateContext<'_, '_>) -> bool {
// IntoIterator is currently only implemented for array sizes <= 32 in rustc
match ty.sty {
ty::TyArray(_, n) => (0..=32).contains(&n.assert_usize(cx.tcx).expect("array length")),
@ -1809,8 +1811,8 @@ fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> {
if block.stmts.is_empty() {
return None;
}
if let StmtDecl(ref decl, _) = block.stmts[0].node {
if let DeclLocal(ref local) = decl.node {
if let StmtKind::Decl(ref decl, _) = block.stmts[0].node {
if let DeclKind::Local(ref local) = decl.node {
if let Some(ref expr) = local.init {
Some(expr)
} else {
@ -1829,8 +1831,8 @@ fn extract_first_expr(block: &Block) -> Option<&Expr> {
match block.expr {
Some(ref expr) if block.stmts.is_empty() => Some(expr),
None if !block.stmts.is_empty() => match block.stmts[0].node {
StmtExpr(ref expr, _) | StmtSemi(ref expr, _) => Some(expr),
StmtDecl(..) => None,
StmtKind::Expr(ref expr, _) | StmtKind::Semi(ref expr, _) => Some(expr),
StmtKind::Decl(..) => None,
},
_ => None,
}
@ -1841,8 +1843,8 @@ fn extract_first_expr(block: &Block) -> Option<&Expr> {
/// passed expression. The expression may be within a block.
fn is_simple_break_expr(expr: &Expr) -> bool {
match expr.node {
ExprBreak(dest, ref passed_expr) if dest.label.is_none() && passed_expr.is_none() => true,
ExprBlock(ref b, _) => match extract_first_expr(b) {
ExprKind::Break(dest, ref passed_expr) if dest.label.is_none() && passed_expr.is_none() => true,
ExprKind::Block(ref b, _) => match extract_first_expr(b) {
Some(subexpr) => is_simple_break_expr(subexpr),
None => false,
},
@ -1882,9 +1884,9 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
let state = self.states.entry(def_id).or_insert(VarState::Initial);
match parent.node {
ExprAssignOp(op, ref lhs, ref rhs) => {
ExprKind::AssignOp(op, ref lhs, ref rhs) => {
if lhs.id == expr.id {
if op.node == BiAdd && is_integer_literal(rhs, 1) {
if op.node == BinOpKind::Add && is_integer_literal(rhs, 1) {
*state = match *state {
VarState::Initial if self.depth == 0 => VarState::IncrOnce,
_ => VarState::DontWarn,
@ -1895,8 +1897,8 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
}
}
},
ExprAssign(ref lhs, _) if lhs.id == expr.id => *state = VarState::DontWarn,
ExprAddrOf(mutability, _) if mutability == MutMutable => *state = VarState::DontWarn,
ExprKind::Assign(ref lhs, _) if lhs.id == expr.id => *state = VarState::DontWarn,
ExprKind::AddrOf(mutability, _) if mutability == MutMutable => *state = VarState::DontWarn,
_ => (),
}
}
@ -1931,7 +1933,7 @@ struct InitializeVisitor<'a, 'tcx: 'a> {
impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
fn visit_decl(&mut self, decl: &'tcx Decl) {
// Look for declarations of the variable
if let DeclLocal(ref local) = decl.node {
if let DeclKind::Local(ref local) = decl.node {
if local.pat.id == self.var_id {
if let PatKind::Binding(_, _, ident, _) = local.pat.node {
self.name = Some(ident.name);
@ -1955,7 +1957,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
if self.state == VarState::DontWarn {
return;
}
if expr == self.end_expr {
if SpanlessEq::new(self.cx).eq_expr(&expr, self.end_expr) {
self.past_loop = true;
return;
}
@ -1969,17 +1971,17 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
if var_def_id(self.cx, expr) == Some(self.var_id) {
if let Some(parent) = get_parent_expr(self.cx, expr) {
match parent.node {
ExprAssignOp(_, ref lhs, _) if lhs.id == expr.id => {
ExprKind::AssignOp(_, ref lhs, _) if lhs.id == expr.id => {
self.state = VarState::DontWarn;
},
ExprAssign(ref lhs, ref rhs) if lhs.id == expr.id => {
ExprKind::Assign(ref lhs, ref rhs) if lhs.id == expr.id => {
self.state = if is_integer_literal(rhs, 0) && self.depth == 0 {
VarState::Warn
} else {
VarState::DontWarn
}
},
ExprAddrOf(mutability, _) if mutability == MutMutable => self.state = VarState::DontWarn,
ExprKind::AddrOf(mutability, _) if mutability == MutMutable => self.state = VarState::DontWarn,
_ => (),
}
}
@ -2004,8 +2006,8 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
}
}
fn var_def_id(cx: &LateContext, expr: &Expr) -> Option<NodeId> {
if let ExprPath(ref qpath) = expr.node {
fn var_def_id(cx: &LateContext<'_, '_>, expr: &Expr) -> Option<NodeId> {
if let ExprKind::Path(ref qpath) = expr.node {
let path_res = cx.tables.qpath_def(qpath, expr.hir_id);
if let Def::Local(node_id) = path_res {
return Some(node_id);
@ -2016,19 +2018,19 @@ fn var_def_id(cx: &LateContext, expr: &Expr) -> Option<NodeId> {
fn is_loop(expr: &Expr) -> bool {
match expr.node {
ExprLoop(..) | ExprWhile(..) => true,
ExprKind::Loop(..) | ExprKind::While(..) => true,
_ => false,
}
}
fn is_conditional(expr: &Expr) -> bool {
match expr.node {
ExprIf(..) | ExprMatch(..) => true,
ExprKind::If(..) | ExprKind::Match(..) => true,
_ => false,
}
}
fn is_nested(cx: &LateContext, match_expr: &Expr, iter_expr: &Expr) -> bool {
fn is_nested(cx: &LateContext<'_, '_>, match_expr: &Expr, iter_expr: &Expr) -> bool {
if_chain! {
if let Some(loop_block) = get_enclosing_block(cx, match_expr.id);
if let Some(map::Node::NodeExpr(loop_expr)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(loop_block.id));
@ -2039,7 +2041,7 @@ fn is_nested(cx: &LateContext, match_expr: &Expr, iter_expr: &Expr) -> bool {
false
}
fn is_loop_nested(cx: &LateContext, loop_expr: &Expr, iter_expr: &Expr) -> bool {
fn is_loop_nested(cx: &LateContext<'_, '_>, loop_expr: &Expr, iter_expr: &Expr) -> bool {
let mut id = loop_expr.id;
let iter_name = if let Some(name) = path_name(iter_expr) {
name
@ -2053,7 +2055,7 @@ fn is_loop_nested(cx: &LateContext, loop_expr: &Expr, iter_expr: &Expr) -> bool
}
match cx.tcx.hir.find(parent) {
Some(NodeExpr(expr)) => match expr.node {
ExprLoop(..) | ExprWhile(..) => {
ExprKind::Loop(..) | ExprKind::While(..) => {
return true;
},
_ => (),
@ -2111,7 +2113,7 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor {
return;
}
match expr.node {
ExprAssign(ref path, _) | ExprAssignOp(_, ref path, _) => if match_var(path, self.iterator) {
ExprKind::Assign(ref path, _) | ExprKind::AssignOp(_, ref path, _) => if match_var(path, self.iterator) {
self.nesting = RuledOut;
},
_ => walk_expr(self, expr),
@ -2137,7 +2139,7 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor {
}
fn path_name(e: &Expr) -> Option<Name> {
if let ExprPath(QPath::Resolved(_, ref path)) = e.node {
if let ExprKind::Path(QPath::Resolved(_, ref path)) = e.node {
let segments = &path.segments;
if segments.len() == 1 {
return Some(segments[0].ident.name);
@ -2193,7 +2195,7 @@ struct VarCollectorVisitor<'a, 'tcx: 'a> {
impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> {
fn insert_def_id(&mut self, ex: &'tcx Expr) {
if_chain! {
if let ExprPath(ref qpath) = ex.node;
if let ExprKind::Path(ref qpath) = ex.node;
if let QPath::Resolved(None, _) = *qpath;
let def = self.cx.tables.qpath_def(qpath, ex.hir_id);
then {
@ -2214,9 +2216,9 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> {
impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> {
fn visit_expr(&mut self, ex: &'tcx Expr) {
match ex.node {
ExprPath(_) => self.insert_def_id(ex),
ExprKind::Path(_) => self.insert_def_id(ex),
// If there is any fuction/method call… we just stop analysis
ExprCall(..) | ExprMethodCall(..) => self.skip = true,
ExprKind::Call(..) | ExprKind::MethodCall(..) => self.skip = true,
_ => walk_expr(self, ex),
}

View File

@ -1,9 +1,11 @@
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::hir::*;
use rustc::ty;
use syntax::ast;
use crate::utils::{get_arg_ident, is_adjusted, iter_input_pats, match_qpath, match_trait_method, match_type,
paths, remove_blocks, snippet, span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth};
paths, remove_blocks, snippet, span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq};
/// **What it does:** Checks for mapping `clone()` over an iterator.
///
@ -30,10 +32,10 @@ pub struct Pass;
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
// call to .map()
if let ExprMethodCall(ref method, _, ref args) = expr.node {
if let ExprKind::MethodCall(ref method, _, ref args) = expr.node {
if method.ident.name == "map" && args.len() == 2 {
match args[1].node {
ExprClosure(_, ref decl, closure_eid, _, _) => {
ExprKind::Closure(_, ref decl, closure_eid, _, _) => {
let body = cx.tcx.hir.body(closure_eid);
let closure_expr = remove_blocks(&body.value);
if_chain! {
@ -62,11 +64,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
}
}
// explicit clone() calls ( .map(|x| x.clone()) )
else if let ExprMethodCall(ref clone_call, _, ref clone_args) = closure_expr.node {
else if let ExprKind::MethodCall(ref clone_call, _, ref clone_args) = closure_expr.node {
if clone_call.ident.name == "clone" &&
clone_args.len() == 1 &&
match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) &&
expr_eq_name(&clone_args[0], arg_ident)
expr_eq_name(cx, &clone_args[0], arg_ident)
{
span_help_and_lint(cx, MAP_CLONE, expr.span, &format!(
"you seem to be using .map() to clone the contents of an {}, consider \
@ -77,7 +79,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
}
}
},
ExprPath(ref path) => if match_qpath(path, &paths::CLONE) {
ExprKind::Path(ref path) => if match_qpath(path, &paths::CLONE) {
let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_");
span_help_and_lint(
cx,
@ -98,9 +100,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
}
}
fn expr_eq_name(expr: &Expr, id: ast::Ident) -> bool {
fn expr_eq_name(cx: &LateContext<'_, '_>, expr: &Expr, id: ast::Ident) -> bool {
match expr.node {
ExprPath(QPath::Resolved(None, ref path)) => {
ExprKind::Path(QPath::Resolved(None, ref path)) => {
let arg_segment = [
PathSegment {
ident: id,
@ -108,13 +110,13 @@ fn expr_eq_name(expr: &Expr, id: ast::Ident) -> bool {
infer_types: true,
},
];
!path.is_global() && path.segments[..] == arg_segment
!path.is_global() && SpanlessEq::new(cx).eq_path_segments(&path.segments[..], &arg_segment)
},
_ => false,
}
}
fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static str> {
fn get_type_name(cx: &LateContext<'_, '_>, expr: &Expr, arg: &Expr) -> Option<&'static str> {
if match_trait_method(cx, expr, &paths::ITERATOR) {
Some("iterator")
} else if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(arg)), &paths::OPTION) {
@ -124,10 +126,10 @@ fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static s
}
}
fn only_derefs(cx: &LateContext, expr: &Expr, id: ast::Ident) -> bool {
fn only_derefs(cx: &LateContext<'_, '_>, expr: &Expr, id: ast::Ident) -> bool {
match expr.node {
ExprUnary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => only_derefs(cx, subexpr, id),
_ => expr_eq_name(expr, id),
ExprKind::Unary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => only_derefs(cx, subexpr, id),
_ => expr_eq_name(cx, expr, id),
}
}

View File

@ -1,7 +1,9 @@
use rustc::hir;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::ty;
use rustc_errors::{Applicability};
use rustc_errors::Applicability;
use syntax::codemap::Span;
use crate::utils::{in_macro, iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then};
use crate::utils::paths;
@ -82,7 +84,7 @@ impl LintPass for Pass {
}
}
fn is_unit_type(ty: ty::Ty) -> bool {
fn is_unit_type(ty: ty::Ty<'_>) -> bool {
match ty.sty {
ty::TyTuple(slice) => slice.is_empty(),
ty::TyNever => true,
@ -90,7 +92,7 @@ fn is_unit_type(ty: ty::Ty) -> bool {
}
}
fn is_unit_function(cx: &LateContext, expr: &hir::Expr) -> bool {
fn is_unit_function(cx: &LateContext<'_, '_>, expr: &hir::Expr) -> bool {
let ty = cx.tables.expr_ty(expr);
if let ty::TyFnDef(id, _) = ty.sty {
@ -101,7 +103,7 @@ fn is_unit_function(cx: &LateContext, expr: &hir::Expr) -> bool {
false
}
fn is_unit_expression(cx: &LateContext, expr: &hir::Expr) -> bool {
fn is_unit_expression(cx: &LateContext<'_, '_>, expr: &hir::Expr) -> bool {
is_unit_type(cx.tables.expr_ty(expr))
}
@ -109,18 +111,18 @@ fn is_unit_expression(cx: &LateContext, expr: &hir::Expr) -> bool {
/// semicolons, which causes problems when generating a suggestion. Given an
/// expression that evaluates to '()' or '!', recursively remove useless braces
/// and semi-colons until is suitable for including in the suggestion template
fn reduce_unit_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option<Span> {
fn reduce_unit_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a hir::Expr) -> Option<Span> {
if !is_unit_expression(cx, expr) {
return None;
}
match expr.node {
hir::ExprCall(_, _) |
hir::ExprMethodCall(_, _, _) => {
hir::ExprKind::Call(_, _) |
hir::ExprKind::MethodCall(_, _, _) => {
// Calls can't be reduced any more
Some(expr.span)
},
hir::ExprBlock(ref block, _) => {
hir::ExprKind::Block(ref block, _) => {
match (&block.stmts[..], block.expr.as_ref()) {
(&[], Some(inner_expr)) => {
// If block only contains an expression,
@ -131,9 +133,9 @@ fn reduce_unit_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option<S
// If block only contains statements,
// reduce `{ X; }` to `X` or `X;`
match inner_stmt.node {
hir::StmtDecl(ref d, _) => Some(d.span),
hir::StmtExpr(ref e, _) => Some(e.span),
hir::StmtSemi(_, _) => Some(inner_stmt.span),
hir::StmtKind::Decl(ref d, _) => Some(d.span),
hir::StmtKind::Expr(ref e, _) => Some(e.span),
hir::StmtKind::Semi(_, _) => Some(inner_stmt.span),
}
},
_ => {
@ -151,7 +153,7 @@ fn reduce_unit_expression<'a>(cx: &LateContext, expr: &'a hir::Expr) -> Option<S
}
fn unit_closure<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'a hir::Expr) -> Option<(&'tcx hir::Arg, &'a hir::Expr)> {
if let hir::ExprClosure(_, ref decl, inner_expr_id, _, _) = expr.node {
if let hir::ExprKind::Closure(_, ref decl, inner_expr_id, _, _) = expr.node {
let body = cx.tcx.hir.body(inner_expr_id);
let body_expr = &body.value;
@ -173,10 +175,10 @@ fn unit_closure<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'a hir::Expr) -> Op
/// `y` => `_y`
///
/// Anything else will return `_`.
fn let_binding_name(cx: &LateContext, var_arg: &hir::Expr) -> String {
fn let_binding_name(cx: &LateContext<'_, '_>, var_arg: &hir::Expr) -> String {
match &var_arg.node {
hir::ExprField(_, _) => snippet(cx, var_arg.span, "_").replace(".", "_"),
hir::ExprPath(_) => format!("_{}", snippet(cx, var_arg.span, "")),
hir::ExprKind::Field(_, _) => snippet(cx, var_arg.span, "_").replace(".", "_"),
hir::ExprKind::Path(_) => format!("_{}", snippet(cx, var_arg.span, "")),
_ => "_".to_string()
}
}
@ -189,7 +191,7 @@ fn suggestion_msg(function_type: &str, map_type: &str) -> String {
)
}
fn lint_map_unit_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_args: &[hir::Expr]) {
fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt, expr: &hir::Expr, map_args: &[hir::Expr]) {
let var_arg = &map_args[0];
let fn_arg = &map_args[1];
@ -242,13 +244,13 @@ fn lint_map_unit_fn(cx: &LateContext, stmt: &hir::Stmt, expr: &hir::Expr, map_ar
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_stmt(&mut self, cx: &LateContext, stmt: &hir::Stmt) {
fn check_stmt(&mut self, cx: &LateContext<'_, '_>, stmt: &hir::Stmt) {
if in_macro(stmt.span) {
return;
}
if let hir::StmtSemi(ref expr, _) = stmt.node {
if let hir::ExprMethodCall(_, _, _) = expr.node {
if let hir::StmtKind::Semi(ref expr, _) = stmt.node {
if let hir::ExprKind::MethodCall(_, _, _) = expr.node {
if let Some(arglists) = method_chain_args(expr, &["map"]) {
lint_map_unit_fn(cx, stmt, expr, arglists[0]);
}

View File

@ -1,12 +1,14 @@
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::ty::{self, Ty};
use std::cmp::Ordering;
use std::collections::Bound;
use syntax::ast::LitKind;
use syntax::codemap::Span;
use crate::utils::paths;
use crate::utils::{expr_block, in_external_macro, is_allowed, is_expn_of, match_qpath, match_type, multispan_sugg,
use crate::utils::{expr_block, is_allowed, is_expn_of, match_qpath, match_type, multispan_sugg,
remove_blocks, snippet, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty};
use crate::utils::sugg::Sugg;
use crate::consts::{constant, Constant};
@ -181,31 +183,31 @@ impl LintPass for MatchPass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MatchPass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if in_external_macro(cx, expr.span) {
if in_external_macro(cx.sess(), expr.span) {
return;
}
if let ExprMatch(ref ex, ref arms, MatchSource::Normal) = expr.node {
if let ExprKind::Match(ref ex, ref arms, MatchSource::Normal) = expr.node {
check_single_match(cx, ex, arms, expr);
check_match_bool(cx, ex, arms, expr);
check_overlapping_arms(cx, ex, arms);
check_wild_err_arm(cx, ex, arms);
check_match_as_ref(cx, ex, arms, expr);
}
if let ExprMatch(ref ex, ref arms, _) = expr.node {
if let ExprKind::Match(ref ex, ref arms, _) = expr.node {
check_match_ref_pats(cx, ex, arms, expr);
}
}
}
#[cfg_attr(rustfmt, rustfmt_skip)]
fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
fn check_single_match(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr) {
if arms.len() == 2 &&
arms[0].pats.len() == 1 && arms[0].guard.is_none() &&
arms[1].pats.len() == 1 && arms[1].guard.is_none() {
let els = remove_blocks(&arms[1].body);
let els = if is_unit_expr(els) {
None
} else if let ExprBlock(_, _) = els.node {
} else if let ExprKind::Block(_, _) = els.node {
// matches with blocks that contain statements are prettier as `if let + else`
Some(els)
} else {
@ -220,13 +222,13 @@ fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
}
}
fn check_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, els: Option<&Expr>) {
if arms[1].pats[0].node == PatKind::Wild {
fn check_single_match_single_pattern(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr, els: Option<&Expr>) {
if is_wild(&arms[1].pats[0]) {
report_single_match_single_pattern(cx, ex, arms, expr, els);
}
}
fn report_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, els: Option<&Expr>) {
fn report_single_match_single_pattern(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr, els: Option<&Expr>) {
let lint = if els.is_some() {
SINGLE_MATCH_ELSE
} else {
@ -250,7 +252,7 @@ fn report_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm],
);
}
fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, ty: Ty, els: Option<&Expr>) {
fn check_single_match_opt_like(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr, ty: Ty<'_>, els: Option<&Expr>) {
// list of candidate Enums we know will never get any more members
let candidates = &[
(&paths::COW, "Borrowed"),
@ -265,7 +267,7 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr:
let path = match arms[1].pats[0].node {
PatKind::TupleStruct(ref path, ref inner, _) => {
// contains any non wildcard patterns? e.g. Err(err)
if inner.iter().any(|pat| pat.node != PatKind::Wild) {
if !inner.iter().all(is_wild) {
return;
}
print::to_string(print::NO_ANN, |s| s.print_qpath(path, false))
@ -282,7 +284,7 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr:
}
}
fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
fn check_match_bool(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr) {
// type of expression == bool
if cx.tables.expr_ty(ex).sty == ty::TyBool {
span_lint_and_then(
@ -294,7 +296,7 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
if arms.len() == 2 && arms[0].pats.len() == 1 {
// no guards
let exprs = if let PatKind::Lit(ref arm_bool) = arms[0].pats[0].node {
if let ExprLit(ref lit) = arm_bool.node {
if let ExprKind::Lit(ref lit) = arm_bool.node {
match lit.node {
LitKind::Bool(true) => Some((&*arms[0].body, &*arms[1].body)),
LitKind::Bool(false) => Some((&*arms[1].body, &*arms[0].body)),
@ -356,7 +358,14 @@ fn check_overlapping_arms<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ex: &'tcx Expr,
}
}
fn check_wild_err_arm(cx: &LateContext, ex: &Expr, arms: &[Arm]) {
fn is_wild(pat: &impl std::ops::Deref<Target = Pat>) -> bool {
match pat.node {
PatKind::Wild => true,
_ => false,
}
}
fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) {
let ex_ty = walk_ptrs_ty(cx.tables.expr_ty(ex));
if match_type(cx, ex_ty, &paths::RESULT) {
for arm in arms {
@ -364,8 +373,8 @@ fn check_wild_err_arm(cx: &LateContext, ex: &Expr, arms: &[Arm]) {
let path_str = print::to_string(print::NO_ANN, |s| s.print_qpath(path, false));
if_chain! {
if path_str == "Err";
if inner.iter().any(|pat| pat.node == PatKind::Wild);
if let ExprBlock(ref block, _) = arm.body.node;
if inner.iter().any(is_wild);
if let ExprKind::Block(ref block, _) = arm.body.node;
if is_panic_block(block);
then {
// `Err(_)` arm with `panic!` found
@ -396,10 +405,10 @@ fn is_panic_block(block: &Block) -> bool {
}
}
fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
fn check_match_ref_pats(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr) {
if has_only_ref_pats(arms) {
let mut suggs = Vec::new();
let (title, msg) = if let ExprAddrOf(Mutability::MutImmutable, ref inner) = ex.node {
let (title, msg) = if let ExprKind::AddrOf(Mutability::MutImmutable, ref inner) = ex.node {
suggs.push((ex.span, Sugg::hir(cx, inner, "..").to_string()));
(
"you don't need to add `&` to both the expression and the patterns",
@ -427,7 +436,7 @@ fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr)
}
}
fn check_match_as_ref(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
fn check_match_as_ref(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr) {
if arms.len() == 2 &&
arms[0].pats.len() == 1 && arms[0].guard.is_none() &&
arms[1].pats.len() == 1 && arms[1].guard.is_none() {
@ -533,8 +542,8 @@ fn type_ranges(ranges: &[SpannedRange<Constant>]) -> TypedRanges {
fn is_unit_expr(expr: &Expr) -> bool {
match expr.node {
ExprTup(ref v) if v.is_empty() => true,
ExprBlock(ref b, _) if b.stmts.is_empty() && b.expr.is_none() => true,
ExprKind::Tup(ref v) if v.is_empty() => true,
ExprKind::Block(ref b, _) if b.stmts.is_empty() && b.expr.is_none() => true,
_ => false,
}
}
@ -554,10 +563,10 @@ fn is_ref_some_arm(arm: &Arm) -> Option<BindingAnnotation> {
if pats.len() == 1 && match_qpath(path, &paths::OPTION_SOME);
if let PatKind::Binding(rb, _, ident, _) = pats[0].node;
if rb == BindingAnnotation::Ref || rb == BindingAnnotation::RefMut;
if let ExprCall(ref e, ref args) = remove_blocks(&arm.body).node;
if let ExprPath(ref some_path) = e.node;
if let ExprKind::Call(ref e, ref args) = remove_blocks(&arm.body).node;
if let ExprKind::Path(ref some_path) = e.node;
if match_qpath(some_path, &paths::OPTION_SOME) && args.len() == 1;
if let ExprPath(ref qpath) = args[0].node;
if let ExprKind::Path(ref qpath) = args[0].node;
if let &QPath::Resolved(_, ref path2) = qpath;
if path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name;
then {

View File

@ -1,5 +1,6 @@
use rustc::lint::*;
use rustc::hir::{Expr, ExprCall, ExprPath};
use rustc::{declare_lint, lint_array};
use rustc::hir::{Expr, ExprKind};
use crate::utils::{match_def_path, opt_def_id, paths, span_lint};
/// **What it does:** Checks for usage of `std::mem::forget(t)` where `t` is
@ -30,8 +31,8 @@ impl LintPass for MemForget {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemForget {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
if let ExprCall(ref path_expr, ref args) = e.node {
if let ExprPath(ref qpath) = path_expr.node {
if let ExprKind::Call(ref path_expr, ref args) = e.node {
if let ExprKind::Path(ref qpath) = path_expr.node {
if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path_expr.hir_id)) {
if match_def_path(cx.tcx, def_id, &paths::MEM_FORGET) {
let forgot_ty = cx.tables.expr_ty(&args[0]);

View File

@ -1,5 +1,8 @@
use matches::matches;
use rustc::hir;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::ty::{self, Ty};
use rustc::hir::def::Def;
use std::borrow::Cow;
@ -7,10 +10,10 @@ use std::fmt;
use std::iter;
use syntax::ast;
use syntax::codemap::{Span, BytePos};
use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_expn_of, is_self,
use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_macro, is_copy, is_expn_of, is_self,
is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method,
match_type, method_chain_args, match_var, return_ty, remove_blocks, same_tys, single_segment_path, snippet,
span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth};
span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq};
use crate::utils::paths;
use crate::utils::sugg;
use crate::consts::{constant, Constant};
@ -718,7 +721,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
}
match expr.node {
hir::ExprMethodCall(ref method_call, ref method_span, ref args) => {
hir::ExprKind::MethodCall(ref method_call, ref method_span, ref args) => {
// Chain calls
// GET_UNWRAP needs to be checked before general `UNWRAP` lints
if let Some(arglists) = method_chain_args(expr, &["get", "unwrap"]) {
@ -789,12 +792,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
_ => (),
}
},
hir::ExprBinary(op, ref lhs, ref rhs) if op.node == hir::BiEq || op.node == hir::BiNe => {
hir::ExprKind::Binary(op, ref lhs, ref rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => {
let mut info = BinaryExprInfo {
expr,
chain: lhs,
other: rhs,
eq: op.node == hir::BiEq,
eq: op.node == hir::BinOpKind::Eq,
};
lint_binary_expr_with_method_call(cx, &mut info);
},
@ -803,7 +806,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
}
fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, implitem: &'tcx hir::ImplItem) {
if in_external_macro(cx, implitem.span) {
if in_external_macro(cx.sess(), implitem.span) {
return;
}
let name = implitem.ident.name;
@ -813,15 +816,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
if let hir::ImplItemKind::Method(ref sig, id) = implitem.node;
if let Some(first_arg_ty) = sig.decl.inputs.get(0);
if let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir.body(id)).next();
if let hir::ItemImpl(_, _, _, _, None, ref self_ty, _) = item.node;
if let hir::ItemKind::Impl(_, _, _, _, None, ref self_ty, _) = item.node;
then {
if cx.access_levels.is_exported(implitem.id) {
// check missing trait implementations
for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS {
if name == method_name &&
sig.decl.inputs.len() == n_args &&
out_type.matches(&sig.decl.output) &&
self_kind.matches(first_arg_ty, first_arg, self_ty, false, &implitem.generics) {
out_type.matches(cx, &sig.decl.output) &&
self_kind.matches(cx, first_arg_ty, first_arg, self_ty, false, &implitem.generics) {
span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!(
"defining a method called `{}` on this type; consider implementing \
the `{}` trait or choosing a less ambiguous name", name, trait_name));
@ -838,9 +841,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
if conv.check(&name.as_str());
if !self_kinds
.iter()
.any(|k| k.matches(first_arg_ty, first_arg, self_ty, is_copy, &implitem.generics));
.any(|k| k.matches(cx, first_arg_ty, first_arg, self_ty, is_copy, &implitem.generics));
then {
let lint = if item.vis == hir::Visibility::Public {
let lint = if item.vis.node.is_pub() {
WRONG_PUB_SELF_CONVENTION
} else {
WRONG_SELF_CONVENTION
@ -873,10 +876,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
}
/// Checks for the `OR_FUN_CALL` lint.
fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) {
fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) {
/// Check for `unwrap_or(T::new())` or `unwrap_or(T::default())`.
fn check_unwrap_or_default(
cx: &LateContext,
cx: &LateContext<'_, '_>,
name: &str,
fun: &hir::Expr,
self_expr: &hir::Expr,
@ -889,7 +892,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name:
}
if name == "unwrap_or" {
if let hir::ExprPath(ref qpath) = fun.node {
if let hir::ExprKind::Path(ref qpath) = fun.node {
let path = &*last_path_segment(qpath).ident.as_str();
if ["default", "new"].contains(&path) {
@ -921,7 +924,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name:
/// Check for `*or(foo())`.
#[allow(too_many_arguments)]
fn check_general_case(
cx: &LateContext,
cx: &LateContext<'_, '_>,
name: &str,
method_span: Span,
fun_span: Span,
@ -964,7 +967,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name:
return;
}
let sugg: Cow<_> = match (fn_has_arguments, !or_has_args) {
let sugg: Cow<'_, _> = match (fn_has_arguments, !or_has_args) {
(true, _) => format!("|_| {}", snippet(cx, arg.span, "..")).into(),
(false, false) => format!("|| {}", snippet(cx, arg.span, "..")).into(),
(false, true) => snippet(cx, fun_span, ".."),
@ -982,13 +985,13 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name:
if args.len() == 2 {
match args[1].node {
hir::ExprCall(ref fun, ref or_args) => {
hir::ExprKind::Call(ref fun, ref or_args) => {
let or_has_args = !or_args.is_empty();
if !check_unwrap_or_default(cx, name, fun, &args[0], &args[1], or_has_args, expr.span) {
check_general_case(cx, name, method_span, fun.span, &args[0], &args[1], or_has_args, expr.span);
}
},
hir::ExprMethodCall(_, span, ref or_args) => {
hir::ExprKind::MethodCall(_, span, ref or_args) => {
check_general_case(cx, name, method_span, span, &args[0], &args[1], !or_args.is_empty(), expr.span)
},
_ => {},
@ -997,12 +1000,12 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name:
}
/// Checks for the `EXPECT_FUN_CALL` lint.
fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) {
fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) {
fn extract_format_args(arg: &hir::Expr) -> Option<&hir::HirVec<hir::Expr>> {
if let hir::ExprAddrOf(_, ref addr_of) = arg.node {
if let hir::ExprCall(ref inner_fun, ref inner_args) = addr_of.node {
if let hir::ExprKind::AddrOf(_, ref addr_of) = arg.node {
if let hir::ExprKind::Call(ref inner_fun, ref inner_args) = addr_of.node {
if is_expn_of(inner_fun.span, "format").is_some() && inner_args.len() == 1 {
if let hir::ExprCall(_, ref format_args) = inner_args[0].node {
if let hir::ExprKind::Call(_, ref format_args) = inner_args[0].node {
return Some(format_args);
}
}
@ -1012,10 +1015,10 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n
None
}
fn generate_format_arg_snippet(cx: &LateContext, a: &hir::Expr) -> String {
if let hir::ExprAddrOf(_, ref format_arg) = a.node {
if let hir::ExprMatch(ref format_arg_expr, _, _) = format_arg.node {
if let hir::ExprTup(ref format_arg_expr_tup) = format_arg_expr.node {
fn generate_format_arg_snippet(cx: &LateContext<'_, '_>, a: &hir::Expr) -> String {
if let hir::ExprKind::AddrOf(_, ref format_arg) = a.node {
if let hir::ExprKind::Match(ref format_arg_expr, _, _) = format_arg.node {
if let hir::ExprKind::Tup(ref format_arg_expr_tup) = format_arg_expr.node {
return snippet(cx, format_arg_expr_tup[0].span, "..").into_owned();
}
}
@ -1025,7 +1028,7 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n
}
fn check_general_case(
cx: &LateContext,
cx: &LateContext<'_, '_>,
name: &str,
method_span: Span,
self_expr: &hir::Expr,
@ -1076,7 +1079,7 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n
return;
}
let sugg: Cow<_> = snippet(cx, arg.span, "..");
let sugg: Cow<'_, _> = snippet(cx, arg.span, "..");
span_lint_and_sugg(
cx,
@ -1090,14 +1093,14 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n
if args.len() == 2 {
match args[1].node {
hir::ExprLit(_) => {},
hir::ExprKind::Lit(_) => {},
_ => check_general_case(cx, name, method_span, &args[0], &args[1], expr.span),
}
}
}
/// Checks for the `CLONE_ON_COPY` lint.
fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_ty: Ty) {
fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Expr, arg_ty: Ty<'_>) {
let ty = cx.tables.expr_ty(expr);
if let ty::TyRef(_, inner, _) = arg_ty.sty {
if let ty::TyRef(_, innermost, _) = inner.sty {
@ -1133,14 +1136,14 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t
match cx.tcx.hir.get(parent) {
hir::map::NodeExpr(parent) => match parent.node {
// &*x is a nop, &x.clone() is not
hir::ExprAddrOf(..) |
hir::ExprKind::AddrOf(..) |
// (*x).func() is useless, x.clone().func() can work in case func borrows mutably
hir::ExprMethodCall(..) => return,
hir::ExprKind::MethodCall(..) => return,
_ => {},
}
hir::map::NodeStmt(stmt) => {
if let hir::StmtDecl(ref decl, _) = stmt.node {
if let hir::DeclLocal(ref loc) = decl.node {
if let hir::StmtKind::Decl(ref decl, _) = stmt.node {
if let hir::DeclKind::Local(ref loc) = decl.node {
if let hir::PatKind::Ref(..) = loc.pat.node {
// let ref y = *x borrows x, let ref y = x.clone() does not
return;
@ -1165,7 +1168,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(cx.tables.expr_ty(arg));
if let ty::TyAdt(_, subst) = obj_ty.sty {
@ -1191,7 +1194,7 @@ fn lint_clone_on_ref_ptr(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) {
}
fn lint_string_extend(cx: &LateContext, expr: &hir::Expr, args: &[hir::Expr]) {
fn lint_string_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) {
let arg = &args[1];
if let Some(arglists) = method_chain_args(arg, &["chars"]) {
let target = &arglists[0][0];
@ -1220,18 +1223,18 @@ fn lint_string_extend(cx: &LateContext, expr: &hir::Expr, args: &[hir::Expr]) {
}
}
fn lint_extend(cx: &LateContext, expr: &hir::Expr, args: &[hir::Expr]) {
fn lint_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) {
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0]));
if match_type(cx, obj_ty, &paths::STRING) {
lint_string_extend(cx, expr, args);
}
}
fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwrap: &hir::Expr) {
fn lint_cstring_as_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr, new: &hir::Expr, unwrap: &hir::Expr) {
if_chain! {
if let hir::ExprCall(ref fun, ref args) = new.node;
if let hir::ExprKind::Call(ref fun, ref args) = new.node;
if args.len() == 1;
if let hir::ExprPath(ref path) = fun.node;
if let hir::ExprKind::Path(ref path) = fun.node;
if let Def::Method(did) = cx.tables.qpath_def(path, fun.hir_id);
if match_def_path(cx.tcx, did, &paths::CSTRING_NEW);
then {
@ -1248,7 +1251,7 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr
}
}
fn lint_iter_cloned_collect(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir::Expr]) {
fn lint_iter_cloned_collect(cx: &LateContext<'_, '_>, expr: &hir::Expr, iter_args: &[hir::Expr]) {
if match_type(cx, cx.tables.expr_ty(expr), &paths::VEC)
&& derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some()
{
@ -1262,7 +1265,7 @@ fn lint_iter_cloned_collect(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir
}
}
fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::Expr]) {
fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args: &[hir::Expr]) {
// Check that this is a call to Iterator::fold rather than just some function called fold
if !match_trait_method(cx, expr, &paths::ITERATOR) {
return;
@ -1272,20 +1275,20 @@ fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::E
"Expected fold_args to have three entries - the receiver, the initial value and the closure");
fn check_fold_with_op(
cx: &LateContext,
cx: &LateContext<'_, '_>,
fold_args: &[hir::Expr],
op: hir::BinOp_,
op: hir::BinOpKind,
replacement_method_name: &str,
replacement_has_args: bool) {
if_chain! {
// Extract the body of the closure passed to fold
if let hir::ExprClosure(_, _, body_id, _, _) = fold_args[2].node;
if let hir::ExprKind::Closure(_, _, body_id, _, _) = fold_args[2].node;
let closure_body = cx.tcx.hir.body(body_id);
let closure_expr = remove_blocks(&closure_body.value);
// Check if the closure body is of the form `acc <op> some_expr(x)`
if let hir::ExprBinary(ref bin_op, ref left_expr, ref right_expr) = closure_expr.node;
if let hir::ExprKind::Binary(ref bin_op, ref left_expr, ref right_expr) = closure_expr.node;
if bin_op.node == op;
// Extract the names of the two arguments to the closure
@ -1329,19 +1332,19 @@ fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::E
// Check if the first argument to .fold is a suitable literal
match fold_args[1].node {
hir::ExprLit(ref lit) => {
hir::ExprKind::Lit(ref lit) => {
match lit.node {
ast::LitKind::Bool(false) => check_fold_with_op(
cx, fold_args, hir::BinOp_::BiOr, "any", true
cx, fold_args, hir::BinOpKind::Or, "any", true
),
ast::LitKind::Bool(true) => check_fold_with_op(
cx, fold_args, hir::BinOp_::BiAnd, "all", true
cx, fold_args, hir::BinOpKind::And, "all", true
),
ast::LitKind::Int(0, _) => check_fold_with_op(
cx, fold_args, hir::BinOp_::BiAdd, "sum", false
cx, fold_args, hir::BinOpKind::Add, "sum", false
),
ast::LitKind::Int(1, _) => check_fold_with_op(
cx, fold_args, hir::BinOp_::BiMul, "product", false
cx, fold_args, hir::BinOpKind::Mul, "product", false
),
_ => return
}
@ -1350,7 +1353,7 @@ fn lint_unnecessary_fold(cx: &LateContext, expr: &hir::Expr, fold_args: &[hir::E
};
}
fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir::Expr], is_mut: bool) {
fn lint_iter_nth(cx: &LateContext<'_, '_>, expr: &hir::Expr, iter_args: &[hir::Expr], is_mut: bool) {
let mut_str = if is_mut { "_mut" } else { "" };
let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() {
"slice"
@ -1374,7 +1377,7 @@ fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &[hir::Expr], is
);
}
fn lint_get_unwrap(cx: &LateContext, expr: &hir::Expr, get_args: &[hir::Expr], is_mut: bool) {
fn lint_get_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, get_args: &[hir::Expr], is_mut: bool) {
// Note: we don't want to lint `get_mut().unwrap` for HashMap or BTreeMap,
// because they do not implement `IndexMut`
let expr_ty = cx.tables.expr_ty(&get_args[0]);
@ -1413,7 +1416,7 @@ fn lint_get_unwrap(cx: &LateContext, expr: &hir::Expr, get_args: &[hir::Expr], i
);
}
fn lint_iter_skip_next(cx: &LateContext, expr: &hir::Expr) {
fn lint_iter_skip_next(cx: &LateContext<'_, '_>, expr: &hir::Expr) {
// lint if caller of skip is an Iterator
if match_trait_method(cx, expr, &paths::ITERATOR) {
span_lint(
@ -1425,8 +1428,8 @@ fn lint_iter_skip_next(cx: &LateContext, expr: &hir::Expr) {
}
}
fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: Ty) -> Option<sugg::Sugg<'static>> {
fn may_slice(cx: &LateContext, ty: Ty) -> bool {
fn derefs_to_slice(cx: &LateContext<'_, '_>, expr: &hir::Expr, ty: Ty<'_>) -> Option<sugg::Sugg<'static>> {
fn may_slice(cx: &LateContext<'_, '_>, ty: Ty<'_>) -> bool {
match ty.sty {
ty::TySlice(_) => true,
ty::TyAdt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()),
@ -1437,7 +1440,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: Ty) -> Option<sugg::S
}
}
if let hir::ExprMethodCall(ref path, _, ref args) = expr.node {
if let hir::ExprKind::MethodCall(ref path, _, ref args) = expr.node {
if path.ident.name == "iter" && may_slice(cx, cx.tables.expr_ty(&args[0])) {
sugg::Sugg::hir_opt(cx, &args[0]).map(|sugg| sugg.addr())
} else {
@ -1458,7 +1461,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: Ty) -> Option<sugg::S
}
/// lint use of `unwrap()` for `Option`s and `Result`s
fn lint_unwrap(cx: &LateContext, expr: &hir::Expr, unwrap_args: &[hir::Expr]) {
fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr, unwrap_args: &[hir::Expr]) {
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&unwrap_args[0]));
let mess = if match_type(cx, obj_ty, &paths::OPTION) {
@ -1486,7 +1489,7 @@ fn lint_unwrap(cx: &LateContext, expr: &hir::Expr, unwrap_args: &[hir::Expr]) {
}
/// lint use of `ok().expect()` for `Result`s
fn lint_ok_expect(cx: &LateContext, expr: &hir::Expr, ok_args: &[hir::Expr]) {
fn lint_ok_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr, ok_args: &[hir::Expr]) {
// lint if the caller of `ok()` is a `Result`
if match_type(cx, cx.tables.expr_ty(&ok_args[0]), &paths::RESULT) {
let result_type = cx.tables.expr_ty(&ok_args[0]);
@ -1504,7 +1507,7 @@ fn lint_ok_expect(cx: &LateContext, expr: &hir::Expr, ok_args: &[hir::Expr]) {
}
/// lint use of `map().unwrap_or()` for `Option`s
fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &[hir::Expr], unwrap_args: &[hir::Expr]) {
fn lint_map_unwrap_or(cx: &LateContext<'_, '_>, expr: &hir::Expr, map_args: &[hir::Expr], unwrap_args: &[hir::Expr]) {
// lint if the caller of `map()` is an `Option`
if match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION) {
// get snippets for args to map() and unwrap_or()
@ -1615,7 +1618,7 @@ fn lint_map_unwrap_or_else<'a, 'tcx>(
fn lint_map_or_none<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, map_or_args: &'tcx [hir::Expr]) {
if match_type(cx, cx.tables.expr_ty(&map_or_args[0]), &paths::OPTION) {
// check if the first non-self argument to map_or() is None
let map_or_arg_is_none = if let hir::Expr_::ExprPath(ref qpath) = map_or_args[1].node {
let map_or_arg_is_none = if let hir::ExprKind::Path(ref qpath) = map_or_args[1].node {
match_qpath(qpath, &paths::OPTION_NONE)
} else {
false
@ -1762,7 +1765,7 @@ struct BinaryExprInfo<'a> {
}
/// Checks for the `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints.
fn lint_binary_expr_with_method_call<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, info: &mut BinaryExprInfo) {
fn lint_binary_expr_with_method_call(cx: &LateContext<'_, '_>, info: &mut BinaryExprInfo<'_>) {
macro_rules! lint_with_both_lhs_and_rhs {
($func:ident, $cx:expr, $info:ident) => {
if !$func($cx, $info) {
@ -1781,18 +1784,18 @@ fn lint_binary_expr_with_method_call<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, i
}
/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_NEXT_CMP` lints.
fn lint_chars_cmp<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>,
info: &BinaryExprInfo,
fn lint_chars_cmp(
cx: &LateContext<'_, '_>,
info: &BinaryExprInfo<'_>,
chain_methods: &[&str],
lint: &'static Lint,
suggest: &str,
) -> bool {
if_chain! {
if let Some(args) = method_chain_args(info.chain, chain_methods);
if let hir::ExprCall(ref fun, ref arg_char) = info.other.node;
if let hir::ExprKind::Call(ref fun, ref arg_char) = info.other.node;
if arg_char.len() == 1;
if let hir::ExprPath(ref qpath) = fun.node;
if let hir::ExprKind::Path(ref qpath) = fun.node;
if let Some(segment) = single_segment_path(qpath);
if segment.ident.name == "Some";
then {
@ -1821,12 +1824,12 @@ fn lint_chars_cmp<'a, 'tcx>(
}
/// Checks for the `CHARS_NEXT_CMP` lint.
fn lint_chars_next_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo) -> bool {
fn lint_chars_next_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool {
lint_chars_cmp(cx, info, &["chars", "next"], CHARS_NEXT_CMP, "starts_with")
}
/// Checks for the `CHARS_LAST_CMP` lint.
fn lint_chars_last_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo) -> bool {
fn lint_chars_last_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool {
if lint_chars_cmp(cx, info, &["chars", "last"], CHARS_NEXT_CMP, "ends_with") {
true
} else {
@ -1837,14 +1840,14 @@ fn lint_chars_last_cmp<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprIn
/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints with `unwrap()`.
fn lint_chars_cmp_with_unwrap<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>,
info: &BinaryExprInfo,
info: &BinaryExprInfo<'_>,
chain_methods: &[&str],
lint: &'static Lint,
suggest: &str,
) -> bool {
if_chain! {
if let Some(args) = method_chain_args(info.chain, chain_methods);
if let hir::ExprLit(ref lit) = info.other.node;
if let hir::ExprKind::Lit(ref lit) = info.other.node;
if let ast::LitKind::Char(c) = lit.node;
then {
span_lint_and_sugg(
@ -1868,12 +1871,12 @@ fn lint_chars_cmp_with_unwrap<'a, 'tcx>(
}
/// Checks for the `CHARS_NEXT_CMP` lint with `unwrap()`.
fn lint_chars_next_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo) -> bool {
fn lint_chars_next_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool {
lint_chars_cmp_with_unwrap(cx, info, &["chars", "next", "unwrap"], CHARS_NEXT_CMP, "starts_with")
}
/// Checks for the `CHARS_LAST_CMP` lint with `unwrap()`.
fn lint_chars_last_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo) -> bool {
fn lint_chars_last_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &BinaryExprInfo<'_>) -> bool {
if lint_chars_cmp_with_unwrap(cx, info, &["chars", "last", "unwrap"], CHARS_LAST_CMP, "ends_with") {
true
} else {
@ -1904,7 +1907,7 @@ fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hi
}
/// Checks for the `USELESS_ASREF` lint.
fn lint_asref(cx: &LateContext, expr: &hir::Expr, call_name: &str, as_ref_args: &[hir::Expr]) {
fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr, call_name: &str, as_ref_args: &[hir::Expr]) {
// when we get here, we've already checked that the call name is "as_ref" or "as_mut"
// check if the call is to the actual `AsRef` or `AsMut` trait
if match_trait_method(cx, expr, &paths::ASREF_TRAIT) || match_trait_method(cx, expr, &paths::ASMUT_TRAIT) {
@ -1928,7 +1931,7 @@ fn lint_asref(cx: &LateContext, expr: &hir::Expr, call_name: &str, as_ref_args:
}
/// Given a `Result<T, E>` type, return its error type (`E`).
fn get_error_type<'a>(cx: &LateContext, ty: Ty<'a>) -> Option<Ty<'a>> {
fn get_error_type<'a>(cx: &LateContext<'_, '_>, ty: Ty<'a>) -> Option<Ty<'a>> {
if let ty::TyAdt(_, substs) = ty.sty {
if match_type(cx, ty, &paths::RESULT) {
substs.types().nth(1)
@ -2030,6 +2033,7 @@ enum SelfKind {
impl SelfKind {
fn matches(
self,
cx: &LateContext<'_, '_>,
ty: &hir::Ty,
arg: &hir::Arg,
self_ty: &hir::Ty,
@ -2047,7 +2051,7 @@ impl SelfKind {
// `Self`, `&mut Self`,
// and `Box<Self>`, including the equivalent types with `Foo`.
let is_actually_self = |ty| is_self_ty(ty) || ty == self_ty;
let is_actually_self = |ty| is_self_ty(ty) || SpanlessEq::new(cx).eq_ty(ty, self_ty);
if is_self(arg) {
match self {
SelfKind::Value => is_actually_self(ty),
@ -2056,7 +2060,7 @@ impl SelfKind {
return true;
}
match ty.node {
hir::TyRptr(_, ref mt_ty) => {
hir::TyKind::Rptr(_, ref mt_ty) => {
let mutability_match = if self == SelfKind::Ref {
mt_ty.mutbl == hir::MutImmutable
} else {
@ -2127,8 +2131,8 @@ fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Gener
fn is_ty(ty: &hir::Ty, self_ty: &hir::Ty) -> bool {
match (&ty.node, &self_ty.node) {
(
&hir::TyPath(hir::QPath::Resolved(_, ref ty_path)),
&hir::TyPath(hir::QPath::Resolved(_, ref self_ty_path)),
&hir::TyKind::Path(hir::QPath::Resolved(_, ref ty_path)),
&hir::TyKind::Path(hir::QPath::Resolved(_, ref self_ty_path)),
) => ty_path
.segments
.iter()
@ -2139,7 +2143,7 @@ fn is_ty(ty: &hir::Ty, self_ty: &hir::Ty) -> bool {
}
fn single_segment_ty(ty: &hir::Ty) -> Option<&hir::PathSegment> {
if let hir::TyPath(ref path) = ty.node {
if let hir::TyKind::Path(ref path) = ty.node {
single_segment_path(path)
} else {
None
@ -2156,7 +2160,7 @@ impl Convention {
}
impl fmt::Display for Convention {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
match *self {
Convention::Eq(this) => this.fmt(f),
Convention::StartsWith(this) => this.fmt(f).and_then(|_| '*'.fmt(f)),
@ -2173,20 +2177,21 @@ enum OutType {
}
impl OutType {
fn matches(self, ty: &hir::FunctionRetTy) -> bool {
fn matches(self, cx: &LateContext<'_, '_>, ty: &hir::FunctionRetTy) -> bool {
let is_unit = |ty: &hir::Ty| SpanlessEq::new(cx).eq_ty_kind(&ty.node, &hir::TyKind::Tup(vec![].into()));
match (self, ty) {
(OutType::Unit, &hir::DefaultReturn(_)) => true,
(OutType::Unit, &hir::Return(ref ty)) if ty.node == hir::TyTup(vec![].into()) => true,
(OutType::Unit, &hir::Return(ref ty)) if is_unit(ty) => true,
(OutType::Bool, &hir::Return(ref ty)) if is_bool(ty) => true,
(OutType::Any, &hir::Return(ref ty)) if ty.node != hir::TyTup(vec![].into()) => true,
(OutType::Ref, &hir::Return(ref ty)) => matches!(ty.node, hir::TyRptr(_, _)),
(OutType::Any, &hir::Return(ref ty)) if !is_unit(ty) => true,
(OutType::Ref, &hir::Return(ref ty)) => matches!(ty.node, hir::TyKind::Rptr(_, _)),
_ => false,
}
}
}
fn is_bool(ty: &hir::Ty) -> bool {
if let hir::TyPath(ref p) = ty.node {
if let hir::TyKind::Path(ref p) = ty.node {
match_qpath(p, &["bool"])
} else {
false

View File

@ -2,6 +2,7 @@ use crate::consts::{constant_simple, Constant};
use crate::utils::{match_def_path, opt_def_id, paths, span_lint};
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use std::cmp::Ordering;
/// **What it does:** Checks for expressions where `std::cmp::min` and `max` are
@ -65,9 +66,9 @@ enum MinMax {
Max,
}
fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &'a Expr)> {
if let ExprCall(ref path, ref args) = expr.node {
if let ExprPath(ref qpath) = path.node {
fn min_max<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<(MinMax, Constant, &'a Expr)> {
if let ExprKind::Call(ref path, ref args) = expr.node {
if let ExprKind::Path(ref qpath) = path.node {
opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)).and_then(|def_id| {
if match_def_path(cx.tcx, def_id, &paths::CMP_MIN) {
fetch_const(cx, args, MinMax::Min)
@ -85,7 +86,7 @@ fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &'
}
}
fn fetch_const<'a>(cx: &LateContext, args: &'a [Expr], m: MinMax) -> Option<(MinMax, Constant, &'a Expr)> {
fn fetch_const<'a>(cx: &LateContext<'_, '_>, args: &'a [Expr], m: MinMax) -> Option<(MinMax, Constant, &'a Expr)> {
if args.len() != 2 {
return None;
}

View File

@ -1,12 +1,15 @@
use crate::reexport::*;
use matches::matches;
use rustc::hir::*;
use rustc::hir::intravisit::FnKind;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::ty;
use syntax::codemap::{ExpnFormat, Span};
use crate::utils::{get_item_name, get_parent_expr, implements_trait, in_constant, in_macro, is_integer_literal,
iter_input_pats, last_path_segment, match_qpath, match_trait_method, paths, snippet, span_lint,
span_lint_and_then, walk_ptrs_ty};
span_lint_and_then, walk_ptrs_ty, SpanlessEq};
use crate::utils::sugg::Sugg;
use syntax::ast::{LitKind, CRATE_NODE_ID};
use crate::consts::{constant, Constant};
@ -269,8 +272,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, s: &'tcx Stmt) {
if_chain! {
if let StmtDecl(ref d, _) = s.node;
if let DeclLocal(ref l) = d.node;
if let StmtKind::Decl(ref d, _) = s.node;
if let DeclKind::Local(ref l) = d.node;
if let PatKind::Binding(an, _, i, None) = l.pat.node;
if let Some(ref init) = l.init;
then {
@ -303,9 +306,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
}
};
if_chain! {
if let StmtSemi(ref expr, _) = s.node;
if let Expr_::ExprBinary(ref binop, ref a, ref b) = expr.node;
if binop.node == BiAnd || binop.node == BiOr;
if let StmtKind::Semi(ref expr, _) = s.node;
if let ExprKind::Binary(ref binop, ref a, ref b) = expr.node;
if binop.node == BinOpKind::And || binop.node == BinOpKind::Or;
if let Some(sugg) = Sugg::hir_opt(cx, a);
then {
span_lint_and_then(cx,
@ -313,7 +316,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
s.span,
"boolean short circuit operator in statement may be clearer using an explicit test",
|db| {
let sugg = if binop.node == BiOr { !sugg } else { sugg };
let sugg = if binop.node == BinOpKind::Or { !sugg } else { sugg };
db.span_suggestion(s.span, "replace it with",
format!("if {} {{ {}; }}", sugg, &snippet(cx, b.span, "..")));
});
@ -323,23 +326,23 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
match expr.node {
ExprCast(ref e, ref ty) => {
ExprKind::Cast(ref e, ref ty) => {
check_cast(cx, expr.span, e, ty);
return;
},
ExprBinary(ref cmp, ref left, ref right) => {
ExprKind::Binary(ref cmp, ref left, ref right) => {
let op = cmp.node;
if op.is_comparison() {
if let ExprPath(QPath::Resolved(_, ref path)) = left.node {
if let ExprKind::Path(QPath::Resolved(_, ref path)) = left.node {
check_nan(cx, path, expr);
}
if let ExprPath(QPath::Resolved(_, ref path)) = right.node {
if let ExprKind::Path(QPath::Resolved(_, ref path)) = right.node {
check_nan(cx, path, expr);
}
check_to_owned(cx, left, right);
check_to_owned(cx, right, left);
}
if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) {
if (op == BinOpKind::Eq || op == BinOpKind::Ne) && (is_float(cx, left) || is_float(cx, right)) {
if is_allowed(cx, left) || is_allowed(cx, right) {
return;
}
@ -367,7 +370,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
);
db.span_note(expr.span, "std::f32::EPSILON and std::f64::EPSILON are available.");
});
} else if op == BiRem && is_integer_literal(right, 1) {
} else if op == BinOpKind::Rem && is_integer_literal(right, 1) {
span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0");
}
},
@ -378,7 +381,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
return;
}
let binding = match expr.node {
ExprPath(ref qpath) => {
ExprKind::Path(ref qpath) => {
let binding = last_path_segment(qpath).ident.as_str();
if binding.starts_with('_') &&
!binding.starts_with("__") &&
@ -392,7 +395,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
None
}
},
ExprField(_, ident) => {
ExprKind::Field(_, ident) => {
let name = ident.as_str();
if name.starts_with('_') && !name.starts_with("__") {
Some(name)
@ -418,7 +421,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) {
if let PatKind::Binding(_, _, ident, Some(ref right)) = pat.node {
if right.node == PatKind::Wild {
if let PatKind::Wild = right.node {
span_lint(
cx,
REDUNDANT_PATTERN,
@ -430,7 +433,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
}
}
fn check_nan(cx: &LateContext, path: &Path, expr: &Expr) {
fn check_nan(cx: &LateContext<'_, '_>, path: &Path, expr: &Expr) {
if !in_constant(cx, expr.id) {
if let Some(seg) = path.segments.last() {
if seg.ident.name == "NAN" {
@ -461,20 +464,20 @@ fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool {
}
}
fn is_float(cx: &LateContext, expr: &Expr) -> bool {
fn is_float(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
matches!(walk_ptrs_ty(cx.tables.expr_ty(expr)).sty, ty::TyFloat(_))
}
fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) {
fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) {
let (arg_ty, snip) = match expr.node {
ExprMethodCall(.., ref args) if args.len() == 1 => {
ExprKind::MethodCall(.., ref args) if args.len() == 1 => {
if match_trait_method(cx, expr, &paths::TO_STRING) || match_trait_method(cx, expr, &paths::TO_OWNED) {
(cx.tables.expr_ty_adjusted(&args[0]), snippet(cx, args[0].span, ".."))
} else {
return;
}
},
ExprCall(ref path, ref v) if v.len() == 1 => if let ExprPath(ref path) = path.node {
ExprKind::Call(ref path, ref v) if v.len() == 1 => if let ExprKind::Path(ref path) = path.node {
if match_qpath(path, &["String", "from_str"]) || match_qpath(path, &["String", "from"]) {
(cx.tables.expr_ty_adjusted(&v[0]), snippet(cx, v[0].span, ".."))
} else {
@ -520,7 +523,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) {
let parent_impl = cx.tcx.hir.get_parent(parent_fn);
if parent_impl != CRATE_NODE_ID {
if let map::NodeItem(item) = cx.tcx.hir.get(parent_impl) {
if let ItemImpl(.., Some(ref trait_ref), _, _) = item.node {
if let ItemKind::Impl(.., Some(ref trait_ref), _, _) = item.node {
if trait_ref.path.def.def_id() == partial_eq_trait_id {
// we are implementing PartialEq, don't suggest not doing `to_owned`, otherwise
// we go into
@ -539,10 +542,10 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) {
/// Heuristic to see if an expression is used. Should be compatible with
/// `unused_variables`'s idea
/// of what it means for an expression to be "used".
fn is_used(cx: &LateContext, expr: &Expr) -> bool {
fn is_used(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
if let Some(parent) = get_parent_expr(cx, expr) {
match parent.node {
ExprAssign(_, ref rhs) | ExprAssignOp(_, _, ref rhs) => **rhs == *expr,
ExprKind::Assign(_, ref rhs) | ExprKind::AssignOp(_, _, ref rhs) => SpanlessEq::new(cx).eq_expr(rhs, expr),
_ => is_used(cx, parent),
}
} else {
@ -562,17 +565,17 @@ fn in_attributes_expansion(expr: &Expr) -> bool {
}
/// Test whether `def` is a variable defined outside a macro.
fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool {
fn non_macro_local(cx: &LateContext<'_, '_>, def: &def::Def) -> bool {
match *def {
def::Def::Local(id) | def::Def::Upvar(id, _, _) => !in_macro(cx.tcx.hir.span(id)),
_ => false,
}
}
fn check_cast(cx: &LateContext, span: Span, e: &Expr, ty: &Ty) {
fn check_cast(cx: &LateContext<'_, '_>, span: Span, e: &Expr, ty: &Ty) {
if_chain! {
if let TyPtr(MutTy { mutbl, .. }) = ty.node;
if let ExprLit(ref lit) = e.node;
if let TyKind::Ptr(MutTy { mutbl, .. }) = ty.node;
if let ExprKind::Lit(ref lit) = e.node;
if let LitKind::Int(value, ..) = lit.node;
if value == 0;
if !in_constant(cx, e.id);

View File

@ -1,10 +1,12 @@
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use std::collections::HashMap;
use std::char;
use syntax::ast::*;
use syntax::codemap::Span;
use syntax::visit::FnKind;
use crate::utils::{constants, in_external_macro, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_then};
use crate::utils::{constants, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_then};
/// **What it does:** Checks for structure field patterns bound to wildcards.
///
@ -187,7 +189,7 @@ impl LintPass for MiscEarly {
}
impl EarlyLintPass for MiscEarly {
fn check_generics(&mut self, cx: &EarlyContext, gen: &Generics) {
fn check_generics(&mut self, cx: &EarlyContext<'_>, gen: &Generics) {
for param in &gen.params {
if let GenericParamKind::Type { .. } = param.kind {
let name = param.ident.as_str();
@ -203,7 +205,7 @@ impl EarlyLintPass for MiscEarly {
}
}
fn check_pat(&mut self, cx: &EarlyContext, pat: &Pat) {
fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat) {
if let PatKind::Struct(ref npat, ref pfields, _) = pat.node {
let mut wilds = 0;
let type_name = npat.segments
@ -213,7 +215,7 @@ impl EarlyLintPass for MiscEarly {
.name;
for field in pfields {
if field.node.pat.node == PatKind::Wild {
if let PatKind::Wild = field.node.pat.node {
wilds += 1;
}
}
@ -231,14 +233,15 @@ impl EarlyLintPass for MiscEarly {
let mut normal = vec![];
for field in pfields {
if field.node.pat.node != PatKind::Wild {
if let Ok(n) = cx.sess().codemap().span_to_snippet(field.span) {
match field.node.pat.node {
PatKind::Wild => {},
_ => if let Ok(n) = cx.sess().codemap().span_to_snippet(field.span) {
normal.push(n);
}
},
}
}
for field in pfields {
if field.node.pat.node == PatKind::Wild {
if let PatKind::Wild = field.node.pat.node {
wilds -= 1;
if wilds > 0 {
span_lint(
@ -263,7 +266,7 @@ impl EarlyLintPass for MiscEarly {
}
}
fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, decl: &FnDecl, _: Span, _: NodeId) {
fn check_fn(&mut self, cx: &EarlyContext<'_>, _: FnKind<'_>, decl: &FnDecl, _: Span, _: NodeId) {
let mut registered_names: HashMap<String, Span> = HashMap::new();
for arg in &decl.inputs {
@ -290,8 +293,8 @@ impl EarlyLintPass for MiscEarly {
}
}
fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
if in_external_macro(cx, expr.span) {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
if in_external_macro(cx.sess(), expr.span) {
return;
}
match expr.node {
@ -322,7 +325,7 @@ impl EarlyLintPass for MiscEarly {
}
}
fn check_block(&mut self, cx: &EarlyContext, block: &Block) {
fn check_block(&mut self, cx: &EarlyContext<'_>, block: &Block) {
for w in block.stmts.windows(2) {
if_chain! {
if let StmtKind::Local(ref local) = w[0].node;
@ -349,7 +352,7 @@ impl EarlyLintPass for MiscEarly {
}
impl MiscEarly {
fn check_lit(self, cx: &EarlyContext, lit: &Lit) {
fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) {
if_chain! {
if let LitKind::Int(value, ..) = lit.node;
if let Some(src) = snippet_opt(cx, lit.span);

View File

@ -20,6 +20,7 @@
use rustc::hir;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::ty;
use syntax::ast;
use syntax::attr;
@ -66,7 +67,7 @@ impl MissingDoc {
.expect("empty doc_hidden_stack")
}
fn check_missing_docs_attrs(&self, cx: &LateContext, attrs: &[ast::Attribute], sp: Span, desc: &'static str) {
fn check_missing_docs_attrs(&self, cx: &LateContext<'_, '_>, attrs: &[ast::Attribute], sp: Span, desc: &'static str) {
// If we're building a test harness, then warning about
// documentation is probably not really relevant right now.
if cx.sess().opts.test {
@ -122,9 +123,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item) {
let desc = match it.node {
hir::ItemConst(..) => "a constant",
hir::ItemEnum(..) => "an enum",
hir::ItemFn(..) => {
hir::ItemKind::Const(..) => "a constant",
hir::ItemKind::Enum(..) => "an enum",
hir::ItemKind::Fn(..) => {
// ignore main()
if it.name == "main" {
let def_id = cx.tcx.hir.local_def_id(it.id);
@ -135,19 +136,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
}
"a function"
},
hir::ItemMod(..) => "a module",
hir::ItemStatic(..) => "a static",
hir::ItemStruct(..) => "a struct",
hir::ItemTrait(..) => "a trait",
hir::ItemTraitAlias(..) => "a trait alias",
hir::ItemGlobalAsm(..) => "an assembly blob",
hir::ItemTy(..) => "a type alias",
hir::ItemUnion(..) => "a union",
hir::ItemExistential(..) => "an existential type",
hir::ItemExternCrate(..) |
hir::ItemForeignMod(..) |
hir::ItemImpl(..) |
hir::ItemUse(..) => return,
hir::ItemKind::Mod(..) => "a module",
hir::ItemKind::Static(..) => "a static",
hir::ItemKind::Struct(..) => "a struct",
hir::ItemKind::Trait(..) => "a trait",
hir::ItemKind::TraitAlias(..) => "a trait alias",
hir::ItemKind::GlobalAsm(..) => "an assembly blob",
hir::ItemKind::Ty(..) => "a type alias",
hir::ItemKind::Union(..) => "a union",
hir::ItemKind::Existential(..) => "an existential type",
hir::ItemKind::ExternCrate(..) |
hir::ItemKind::ForeignMod(..) |
hir::ItemKind::Impl(..) |
hir::ItemKind::Use(..) => return,
};
self.check_missing_docs_attrs(cx, &it.attrs, it.span, desc);
@ -177,6 +178,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
hir::ImplItemKind::Const(..) => "an associated constant",
hir::ImplItemKind::Method(..) => "a method",
hir::ImplItemKind::Type(_) => "an associated type",
hir::ImplItemKind::Existential(_) => "an existential type",
};
self.check_missing_docs_attrs(cx, &impl_item.attrs, impl_item.span, desc);
}

View File

@ -0,0 +1,191 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
use rustc::hir;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use syntax::ast;
use syntax::codemap::Span;
/// **What it does:** it lints if an exported function, method, trait method with default impl,
/// or trait method impl is not `#[inline]`.
///
/// **Why is this bad?** In general, it is not. Functions can be inlined across
/// crates when that's profitable as long as any form of LTO is used. When LTO is disabled,
/// functions that are not `#[inline]` cannot be inlined across crates. Certain types of crates
/// might intend for most of the methods in their public API to be able to be inlined across
/// crates even when LTO is disabled. For these types of crates, enabling this lint might make sense.
/// It allows the crate to require all exported methods to be `#[inline]` by default, and then opt
/// out for specific methods where this might not make sense.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// pub fn foo() {} // missing #[inline]
/// fn ok() {} // ok
/// #[inline] pub fn bar() {} // ok
/// #[inline(always)] pub fn baz() {} // ok
///
/// pub trait Bar {
/// fn bar(); // ok
/// fn def_bar() {} // missing #[inline]
/// }
///
/// struct Baz;
/// impl Baz {
/// fn priv() {} // ok
/// }
///
/// impl Bar for Baz {
/// fn bar() {} // ok - Baz is not exported
/// }
///
/// pub struct PubBaz;
/// impl PubBaz {
/// fn priv() {} // ok
/// pub not_ptriv() {} // missing #[inline]
/// }
///
/// impl Bar for PubBaz {
/// fn bar() {} // missing #[inline]
/// fn def_bar() {} // missing #[inline]
/// }
/// ```
declare_clippy_lint! {
pub MISSING_INLINE_IN_PUBLIC_ITEMS,
restriction,
"detects missing #[inline] attribute for public callables (functions, trait methods, methods...)"
}
pub struct MissingInline;
fn check_missing_inline_attrs(cx: &LateContext<'_, '_>,
attrs: &[ast::Attribute], sp: Span, desc: &'static str) {
let has_inline = attrs
.iter()
.any(|a| a.name() == "inline" );
if !has_inline {
cx.span_lint(
MISSING_INLINE_IN_PUBLIC_ITEMS,
sp,
&format!("missing `#[inline]` for {}", desc),
);
}
}
fn is_executable<'a, 'tcx>(cx: &LateContext<'a, 'tcx>) -> bool {
use rustc::session::config::CrateType;
cx.tcx.sess.crate_types.get().iter().any(|t: &CrateType| {
match t {
CrateType::CrateTypeExecutable => true,
_ => false,
}
})
}
impl LintPass for MissingInline {
fn get_lints(&self) -> LintArray {
lint_array![MISSING_INLINE_IN_PUBLIC_ITEMS]
}
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item) {
if is_executable(cx) {
return;
}
if !cx.access_levels.is_exported(it.id) {
return;
}
match it.node {
hir::ItemKind::Fn(..) => {
let desc = "a function";
check_missing_inline_attrs(cx, &it.attrs, it.span, desc);
},
hir::ItemKind::Trait(ref _is_auto, ref _unsafe, ref _generics,
ref _bounds, ref trait_items) => {
// note: we need to check if the trait is exported so we can't use
// `LateLintPass::check_trait_item` here.
for tit in trait_items {
let tit_ = cx.tcx.hir.trait_item(tit.id);
match tit_.node {
hir::TraitItemKind::Const(..) |
hir::TraitItemKind::Type(..) => {},
hir::TraitItemKind::Method(..) => {
if tit.defaultness.has_value() {
// trait method with default body needs inline in case
// an impl is not provided
let desc = "a default trait method";
let item = cx.tcx.hir.expect_trait_item(tit.id.node_id);
check_missing_inline_attrs(cx, &item.attrs,
item.span, desc);
}
},
}
}
}
hir::ItemKind::Const(..) |
hir::ItemKind::Enum(..) |
hir::ItemKind::Mod(..) |
hir::ItemKind::Static(..) |
hir::ItemKind::Struct(..) |
hir::ItemKind::TraitAlias(..) |
hir::ItemKind::GlobalAsm(..) |
hir::ItemKind::Ty(..) |
hir::ItemKind::Union(..) |
hir::ItemKind::Existential(..) |
hir::ItemKind::ExternCrate(..) |
hir::ItemKind::ForeignMod(..) |
hir::ItemKind::Impl(..) |
hir::ItemKind::Use(..) => {},
};
}
fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem) {
use rustc::ty::{TraitContainer, ImplContainer};
if is_executable(cx) {
return;
}
// If the item being implemented is not exported, then we don't need #[inline]
if !cx.access_levels.is_exported(impl_item.id) {
return;
}
let desc = match impl_item.node {
hir::ImplItemKind::Method(..) => "a method",
hir::ImplItemKind::Const(..) |
hir::ImplItemKind::Type(_) |
hir::ImplItemKind::Existential(_) => return,
};
let def_id = cx.tcx.hir.local_def_id(impl_item.id);
let trait_def_id = match cx.tcx.associated_item(def_id).container {
TraitContainer(cid) => Some(cid),
ImplContainer(cid) => cx.tcx.impl_trait_ref(cid).map(|t| t.def_id),
};
if let Some(trait_def_id) = trait_def_id {
if let Some(n) = cx.tcx.hir.as_local_node_id(trait_def_id) {
if !cx.access_levels.is_exported(n) {
// If a trait is being implemented for an item, and the
// trait is not exported, we don't need #[inline]
return;
}
}
}
check_missing_inline_attrs(cx, &impl_item.attrs, impl_item.span, desc);
}
}

View File

@ -1,6 +1,7 @@
//! lint on multiple versions of a crate being used
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use syntax::ast::*;
use cargo_metadata;
@ -38,7 +39,7 @@ impl LintPass for Pass {
}
impl EarlyLintPass for Pass {
fn check_crate(&mut self, cx: &EarlyContext, krate: &Crate) {
fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) {
let metadata = match cargo_metadata::metadata_deps(None, true) {
Ok(metadata) => metadata,
Err(_) => {

View File

@ -1,8 +1,9 @@
use rustc::hir;
use rustc::hir::intravisit;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::ty;
use crate::utils::{higher, in_external_macro, span_lint};
use crate::utils::{higher, span_lint};
/// **What it does:** Checks for instances of `mut mut` references.
///
@ -49,7 +50,7 @@ pub struct MutVisitor<'a, 'tcx: 'a> {
impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
if in_external_macro(self.cx, expr.span) {
if in_external_macro(self.cx.sess(), expr.span) {
return;
}
@ -62,8 +63,8 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> {
// Let's ignore the generated code.
intravisit::walk_expr(self, arg);
intravisit::walk_expr(self, body);
} else if let hir::ExprAddrOf(hir::MutMutable, ref e) = expr.node {
if let hir::ExprAddrOf(hir::MutMutable, _) = e.node {
} else if let hir::ExprKind::AddrOf(hir::MutMutable, ref e) = expr.node {
if let hir::ExprKind::AddrOf(hir::MutMutable, _) = e.node {
span_lint(
self.cx,
MUT_MUT,
@ -87,7 +88,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> {
}
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
if let hir::TyRptr(
if let hir::TyKind::Rptr(
_,
hir::MutTy {
ty: ref pty,
@ -95,7 +96,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> {
},
) = ty.node
{
if let hir::TyRptr(
if let hir::TyKind::Rptr(
_,
hir::MutTy {
mutbl: hir::MutMutable,

View File

@ -1,4 +1,5 @@
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::ty::{self, Ty};
use rustc::ty::subst::Subst;
use rustc::hir::*;
@ -36,7 +37,7 @@ impl LintPass for UnnecessaryMutPassed {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
match e.node {
ExprCall(ref fn_expr, ref arguments) => if let ExprPath(ref path) = fn_expr.node {
ExprKind::Call(ref fn_expr, ref arguments) => if let ExprKind::Path(ref path) = fn_expr.node {
check_arguments(
cx,
arguments,
@ -44,7 +45,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed {
&print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)),
);
},
ExprMethodCall(ref path, _, ref arguments) => {
ExprKind::MethodCall(ref path, _, ref arguments) => {
let def_id = cx.tables.type_dependent_defs()[e.hir_id].def_id();
let substs = cx.tables.node_substs(e.hir_id);
let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs);
@ -69,7 +70,7 @@ fn check_arguments<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arguments: &[Expr], typ
ty::TyRawPtr(ty::TypeAndMut {
mutbl: MutImmutable,
..
}) => if let ExprAddrOf(MutMutable, _) = argument.node {
}) => if let ExprKind::AddrOf(MutMutable, _) = argument.node {
span_lint(
cx,
UNNECESSARY_MUT_PASSED,

View File

@ -3,6 +3,7 @@
//! This lint is **warn** by default
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint, lint_array};
use rustc::ty::{self, Ty};
use rustc::hir::Expr;
use syntax::ast;
@ -79,7 +80,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutexAtomic {
}
}
fn get_atomic_name(ty: Ty) -> Option<(&'static str)> {
fn get_atomic_name(ty: Ty<'_>) -> Option<(&'static str)> {
match ty.sty {
ty::TyBool => Some("AtomicBool"),
ty::TyUint(_) => Some("AtomicUsize"),

View File

@ -3,6 +3,7 @@
//! This lint is **warn** by default
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::hir::*;
use syntax::ast::LitKind;
use syntax::codemap::Spanned;
@ -60,7 +61,7 @@ impl LintPass for NeedlessBool {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
use self::Expression::*;
if let ExprIf(ref pred, ref then_block, Some(ref else_expr)) = e.node {
if let ExprKind::If(ref pred, ref then_block, Some(ref else_expr)) = e.node {
let reduce = |ret, not| {
let snip = Sugg::hir(cx, pred, "<predicate>");
let snip = if not { !snip } else { snip };
@ -80,7 +81,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool {
hint,
);
};
if let ExprBlock(ref then_block, _) = then_block.node {
if let ExprKind::Block(ref then_block, _) = then_block.node {
match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) {
(RetBool(true), RetBool(true)) | (Bool(true), Bool(true)) => {
span_lint(
@ -105,7 +106,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool {
_ => (),
}
} else {
panic!("IfExpr 'then' node is not an ExprBlock");
panic!("IfExpr 'then' node is not an ExprKind::Block");
}
}
}
@ -123,7 +124,7 @@ impl LintPass for BoolComparison {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
use self::Expression::*;
if let ExprBinary(Spanned { node: BiEq, .. }, ref left_side, ref right_side) = e.node {
if let ExprKind::Binary(Spanned { node: BinOpKind::Eq, .. }, ref left_side, ref right_side) = e.node {
match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) {
(Bool(true), Other) => {
let hint = snippet(cx, right_side.span, "..").into_owned();
@ -184,8 +185,8 @@ enum Expression {
fn fetch_bool_block(block: &Block) -> Expression {
match (&*block.stmts, block.expr.as_ref()) {
(&[], Some(e)) => fetch_bool_expr(&**e),
(&[ref e], None) => if let StmtSemi(ref e, _) = e.node {
if let ExprRet(_) = e.node {
(&[ref e], None) => if let StmtKind::Semi(ref e, _) = e.node {
if let ExprKind::Ret(_) = e.node {
fetch_bool_expr(&**e)
} else {
Expression::Other
@ -199,13 +200,13 @@ fn fetch_bool_block(block: &Block) -> Expression {
fn fetch_bool_expr(expr: &Expr) -> Expression {
match expr.node {
ExprBlock(ref block, _) => fetch_bool_block(block),
ExprLit(ref lit_ptr) => if let LitKind::Bool(value) = lit_ptr.node {
ExprKind::Block(ref block, _) => fetch_bool_block(block),
ExprKind::Lit(ref lit_ptr) => if let LitKind::Bool(value) = lit_ptr.node {
Expression::Bool(value)
} else {
Expression::Other
},
ExprRet(Some(ref expr)) => match fetch_bool_expr(expr) {
ExprKind::Ret(Some(ref expr)) => match fetch_bool_expr(expr) {
Expression::Bool(value) => Expression::RetBool(value),
_ => Expression::Other,
},

View File

@ -3,7 +3,9 @@
//! This lint is **warn** by default
use rustc::lint::*;
use rustc::hir::{BindingAnnotation, Expr, ExprAddrOf, MutImmutable, Pat, PatKind};
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::hir::{BindingAnnotation, Expr, ExprKind, MutImmutable, Pat, PatKind};
use rustc::ty;
use rustc::ty::adjustment::{Adjust, Adjustment};
use crate::utils::{in_macro, snippet_opt, span_lint_and_then};
@ -40,7 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow {
if in_macro(e.span) {
return;
}
if let ExprAddrOf(MutImmutable, ref inner) = e.node {
if let ExprKind::AddrOf(MutImmutable, ref inner) = e.node {
if let ty::TyRef(..) = cx.tables.expr_ty(inner).sty {
for adj3 in cx.tables.expr_adjustments(e).windows(3) {
if let [Adjustment {

View File

@ -3,6 +3,8 @@
//! This lint is **warn** by default
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::hir::{BindingAnnotation, MutImmutable, Pat, PatKind};
use crate::utils::{in_macro, snippet, span_lint_and_then};

View File

@ -28,6 +28,7 @@
//!
//! This lint is **warn** by default.
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use syntax::ast;
use syntax::codemap::{original_sp, DUMMY_SP};
use std::borrow::Cow;
@ -109,7 +110,7 @@ impl LintPass for NeedlessContinue {
}
impl EarlyLintPass for NeedlessContinue {
fn check_expr(&mut self, ctx: &EarlyContext, expr: &ast::Expr) {
fn check_expr(&mut self, ctx: &EarlyContext<'_>, expr: &ast::Expr) {
if !in_macro(expr.span) {
check_and_warn(ctx, expr);
}
@ -264,7 +265,7 @@ const DROP_ELSE_BLOCK_MSG: &str = "Consider dropping the else clause, and moving
block, like so:\n";
fn emit_warning<'a>(ctx: &EarlyContext, data: &'a LintData, header: &str, typ: LintType) {
fn emit_warning<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str, typ: LintType) {
// snip is the whole *help* message that appears after the warning.
// message is the warning message.
// expr is the expression which the lint warning message refers to.
@ -283,7 +284,7 @@ fn emit_warning<'a>(ctx: &EarlyContext, data: &'a LintData, header: &str, typ: L
span_help_and_lint(ctx, NEEDLESS_CONTINUE, expr.span, message, &snip);
}
fn suggestion_snippet_for_continue_inside_if<'a>(ctx: &EarlyContext, data: &'a LintData, header: &str) -> String {
fn suggestion_snippet_for_continue_inside_if<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str) -> String {
let cond_code = snippet(ctx, data.if_cond.span, "..");
let if_code = format!("if {} {{\n continue;\n}}\n", cond_code);
@ -300,7 +301,7 @@ fn suggestion_snippet_for_continue_inside_if<'a>(ctx: &EarlyContext, data: &'a L
ret
}
fn suggestion_snippet_for_continue_inside_else<'a>(ctx: &EarlyContext, data: &'a LintData, header: &str) -> String {
fn suggestion_snippet_for_continue_inside_else<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str) -> String {
let cond_code = snippet(ctx, data.if_cond.span, "..");
let mut if_code = format!("if {} {{\n", cond_code);
@ -331,7 +332,7 @@ fn suggestion_snippet_for_continue_inside_else<'a>(ctx: &EarlyContext, data: &'a
ret
}
fn check_and_warn<'a>(ctx: &EarlyContext, expr: &'a ast::Expr) {
fn check_and_warn<'a>(ctx: &EarlyContext<'_>, expr: &'a ast::Expr) {
with_loop_block(expr, |loop_block| {
for (i, stmt) in loop_block.stmts.iter().enumerate() {
with_if_expr(stmt, |if_expr, cond, then_block, else_expr| {

View File

@ -1,7 +1,10 @@
use matches::matches;
use rustc::hir::*;
use rustc::hir::map::*;
use rustc::hir::intravisit::FnKind;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::ty::{self, RegionKind, TypeFoldable};
use rustc::traits;
use rustc::middle::expr_use_visitor as euv;
@ -88,8 +91,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
// Exclude non-inherent impls
if let Some(NodeItem(item)) = cx.tcx.hir.find(cx.tcx.hir.get_parent_node(node_id)) {
if matches!(item.node, ItemImpl(_, _, _, _, Some(_), _, _) |
ItemTrait(..))
if matches!(item.node, ItemKind::Impl(_, _, _, _, Some(_), _, _) |
ItemKind::Trait(..))
{
return;
}
@ -201,7 +204,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
}
// Dereference suggestion
let sugg = |db: &mut DiagnosticBuilder| {
let sugg = |db: &mut DiagnosticBuilder<'_>| {
if let ty::TypeVariants::TyAdt(def, ..) = ty.sty {
if let Some(span) = cx.tcx.hir.span_if_local(def.did) {
if cx.param_env.can_type_implement_copy(cx.tcx, ty).is_ok() {
@ -215,7 +218,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
if match_type(cx, ty, &paths::VEC);
if let Some(clone_spans) =
get_spans(cx, Some(body.id()), idx, &[("clone", ".to_owned()")]);
if let TyPath(QPath::Resolved(_, ref path)) = input.node;
if let TyKind::Path(QPath::Resolved(_, ref path)) = input.node;
if let Some(elem_ty) = path.segments.iter()
.find(|seg| seg.ident.name == "Vec")
.and_then(|ps| ps.args.as_ref())
@ -339,7 +342,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> {
match node {
map::Node::NodeExpr(e) => {
// `match` and `if let`
if let ExprMatch(ref c, ..) = e.node {
if let ExprKind::Match(ref c, ..) = e.node {
self.spans_need_deref
.entry(vid)
.or_insert_with(HashSet::new)
@ -350,8 +353,8 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> {
map::Node::NodeStmt(s) => {
// `let <pat> = x;`
if_chain! {
if let StmtDecl(ref decl, _) = s.node;
if let DeclLocal(ref local) = decl.node;
if let StmtKind::Decl(ref decl, _) = s.node;
if let DeclKind::Local(ref local) = decl.node;
then {
self.spans_need_deref
.entry(vid)
@ -393,7 +396,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt<'a, 'tcx> {
}
}
fn borrow(&mut self, _: NodeId, _: Span, _: &mc::cmt_<'tcx>, _: ty::Region, _: ty::BorrowKind, _: euv::LoanCause) {}
fn borrow(&mut self, _: NodeId, _: Span, _: &mc::cmt_<'tcx>, _: ty::Region<'_>, _: ty::BorrowKind, _: euv::LoanCause) {}
fn mutate(&mut self, _: NodeId, _: Span, _: &mc::cmt_<'tcx>, _: euv::MutateMode) {}

View File

@ -1,6 +1,7 @@
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint, lint_array};
use rustc::ty;
use rustc::hir::{Expr, ExprStruct};
use rustc::hir::{Expr, ExprKind};
use crate::utils::span_lint;
/// **What it does:** Checks for needlessly including a base struct on update
@ -32,7 +33,7 @@ impl LintPass for Pass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let ExprStruct(_, ref fields, Some(ref base)) = expr.node {
if let ExprKind::Struct(_, ref fields, Some(ref base)) = expr.node {
let ty = cx.tables.expr_ty(expr);
if let ty::TyAdt(def, _) = ty.sty {
if fields.len() == def.non_enum_variant().fields.len() {

View File

@ -1,7 +1,9 @@
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use crate::utils::{self, paths, span_lint, in_external_macro};
use crate::utils::{self, paths, span_lint};
/// **What it does:**
/// Checks for the usage of negated comparison operators on types which only implement
@ -22,16 +24,16 @@ use crate::utils::{self, paths, span_lint, in_external_macro};
/// // Bad
/// let a = 1.0;
/// let b = std::f64::NAN;
///
///
/// let _not_less_or_equal = !(a <= b);
///
/// // Good
/// let a = 1.0;
/// let b = std::f64::NAN;
///
///
/// let _not_less_or_equal = match a.partial_cmp(&b) {
/// None | Some(Ordering::Greater) => true,
/// _ => false,
/// _ => false,
/// };
/// ```
declare_clippy_lint! {
@ -53,10 +55,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if_chain! {
if !in_external_macro(cx, expr.span);
if let Expr_::ExprUnary(UnOp::UnNot, ref inner) = expr.node;
if let Expr_::ExprBinary(ref op, ref left, _) = inner.node;
if let BinOp_::BiLe | BinOp_::BiGe | BinOp_::BiLt | BinOp_::BiGt = op.node;
if !in_external_macro(cx.sess(), expr.span);
if let ExprKind::Unary(UnOp::UnNot, ref inner) = expr.node;
if let ExprKind::Binary(ref op, ref left, _) = inner.node;
if let BinOpKind::Le | BinOpKind::Ge | BinOpKind::Lt | BinOpKind::Gt = op.node;
then {

View File

@ -1,5 +1,7 @@
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use syntax::codemap::{Span, Spanned};
use crate::consts::{self, Constant};
@ -33,20 +35,20 @@ impl LintPass for NegMultiply {
#[allow(match_same_arms)]
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NegMultiply {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
if let ExprBinary(Spanned { node: BiMul, .. }, ref l, ref r) = e.node {
if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref l, ref r) = e.node {
match (&l.node, &r.node) {
(&ExprUnary(..), &ExprUnary(..)) => (),
(&ExprUnary(UnNeg, ref lit), _) => check_mul(cx, e.span, lit, r),
(_, &ExprUnary(UnNeg, ref lit)) => check_mul(cx, e.span, lit, l),
(&ExprKind::Unary(..), &ExprKind::Unary(..)) => (),
(&ExprKind::Unary(UnNeg, ref lit), _) => check_mul(cx, e.span, lit, r),
(_, &ExprKind::Unary(UnNeg, ref lit)) => check_mul(cx, e.span, lit, l),
_ => (),
}
}
}
}
fn check_mul(cx: &LateContext, span: Span, lit: &Expr, exp: &Expr) {
fn check_mul(cx: &LateContext<'_, '_>, span: Span, lit: &Expr, exp: &Expr) {
if_chain! {
if let ExprLit(ref l) = lit.node;
if let ExprKind::Lit(ref l) = lit.node;
if let Constant::Int(val) = consts::lit_to_constant(&l.node, cx.tables.expr_ty(lit));
if val == 1;
if cx.tables.expr_ty(exp).is_integral();

View File

@ -1,10 +1,12 @@
use rustc::hir::def_id::DefId;
use rustc::hir;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::ty::{self, Ty};
use syntax::codemap::Span;
use crate::utils::paths;
use crate::utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint_and_then};
use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_and_then};
use crate::utils::sugg::DiagnosticBuilderExt;
/// **What it does:** Checks for types with a `fn new() -> Self` method and no
@ -89,11 +91,11 @@ impl LintPass for NewWithoutDefault {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) {
if let hir::ItemImpl(_, _, _, _, None, _, ref items) = item.node {
if let hir::ItemKind::Impl(_, _, _, _, None, _, ref items) = item.node {
for assoc_item in items {
if let hir::AssociatedItemKind::Method { has_self: false } = assoc_item.kind {
let impl_item = cx.tcx.hir.impl_item(assoc_item.id);
if in_external_macro(cx, impl_item.span) {
if in_external_macro(cx.sess(), impl_item.span) {
return;
}
if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
@ -155,7 +157,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
}
}
fn create_new_without_default_suggest_msg(ty: Ty) -> String {
fn create_new_without_default_suggest_msg(ty: Ty<'_>) -> String {
#[cfg_attr(rustfmt, rustfmt_skip)]
format!(
"impl Default for {} {{

View File

@ -1,6 +1,7 @@
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint, lint_array};
use rustc::hir::def::Def;
use rustc::hir::{BiAnd, BiOr, BlockCheckMode, Expr, Expr_, Stmt, StmtSemi, UnsafeSource};
use rustc::hir::{BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource};
use crate::utils::{has_drop, in_macro, snippet_opt, span_lint, span_lint_and_sugg};
use std::ops::Deref;
@ -40,31 +41,31 @@ declare_clippy_lint! {
"outer expressions with no effect"
}
fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool {
fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
if in_macro(expr.span) {
return false;
}
match expr.node {
Expr_::ExprLit(..) | Expr_::ExprClosure(.., _) => true,
Expr_::ExprPath(..) => !has_drop(cx, expr),
Expr_::ExprIndex(ref a, ref b) | Expr_::ExprBinary(_, ref a, ref b) => {
ExprKind::Lit(..) | ExprKind::Closure(.., _) => true,
ExprKind::Path(..) => !has_drop(cx, expr),
ExprKind::Index(ref a, ref b) | ExprKind::Binary(_, ref a, ref b) => {
has_no_effect(cx, a) && has_no_effect(cx, b)
},
Expr_::ExprArray(ref v) | Expr_::ExprTup(ref v) => v.iter().all(|val| has_no_effect(cx, val)),
Expr_::ExprRepeat(ref inner, _) |
Expr_::ExprCast(ref inner, _) |
Expr_::ExprType(ref inner, _) |
Expr_::ExprUnary(_, ref inner) |
Expr_::ExprField(ref inner, _) |
Expr_::ExprAddrOf(_, ref inner) |
Expr_::ExprBox(ref inner) => has_no_effect(cx, inner),
Expr_::ExprStruct(_, ref fields, ref base) => {
ExprKind::Array(ref v) | ExprKind::Tup(ref v) => v.iter().all(|val| has_no_effect(cx, val)),
ExprKind::Repeat(ref inner, _) |
ExprKind::Cast(ref inner, _) |
ExprKind::Type(ref inner, _) |
ExprKind::Unary(_, ref inner) |
ExprKind::Field(ref inner, _) |
ExprKind::AddrOf(_, ref inner) |
ExprKind::Box(ref inner) => has_no_effect(cx, inner),
ExprKind::Struct(_, ref fields, ref base) => {
!has_drop(cx, expr) && fields.iter().all(|field| has_no_effect(cx, &field.expr)) && match *base {
Some(ref base) => has_no_effect(cx, base),
None => true,
}
},
Expr_::ExprCall(ref callee, ref args) => if let Expr_::ExprPath(ref qpath) = callee.node {
ExprKind::Call(ref callee, ref args) => if let ExprKind::Path(ref qpath) = callee.node {
let def = cx.tables.qpath_def(qpath, callee.hir_id);
match def {
Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) => {
@ -75,7 +76,7 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool {
} else {
false
},
Expr_::ExprBlock(ref block, _) => {
ExprKind::Block(ref block, _) => {
block.stmts.is_empty() && if let Some(ref expr) = block.expr {
has_no_effect(cx, expr)
} else {
@ -97,7 +98,7 @@ impl LintPass for Pass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) {
if let StmtSemi(ref expr, _) = stmt.node {
if let StmtKind::Semi(ref expr, _) = stmt.node {
if has_no_effect(cx, expr) {
span_lint(cx, NO_EFFECT, stmt.span, "statement with no effect");
} else if let Some(reduced) = reduce_expression(cx, expr) {
@ -127,24 +128,24 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
}
fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option<Vec<&'a Expr>> {
fn reduce_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<Vec<&'a Expr>> {
if in_macro(expr.span) {
return None;
}
match expr.node {
Expr_::ExprIndex(ref a, ref b) => Some(vec![&**a, &**b]),
Expr_::ExprBinary(ref binop, ref a, ref b) if binop.node != BiAnd && binop.node != BiOr => {
ExprKind::Index(ref a, ref b) => Some(vec![&**a, &**b]),
ExprKind::Binary(ref binop, ref a, ref b) if binop.node != BinOpKind::And && binop.node != BinOpKind::Or => {
Some(vec![&**a, &**b])
},
Expr_::ExprArray(ref v) | Expr_::ExprTup(ref v) => Some(v.iter().collect()),
Expr_::ExprRepeat(ref inner, _) |
Expr_::ExprCast(ref inner, _) |
Expr_::ExprType(ref inner, _) |
Expr_::ExprUnary(_, ref inner) |
Expr_::ExprField(ref inner, _) |
Expr_::ExprAddrOf(_, ref inner) |
Expr_::ExprBox(ref inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])),
Expr_::ExprStruct(_, ref fields, ref base) => if has_drop(cx, expr) {
ExprKind::Array(ref v) | ExprKind::Tup(ref v) => Some(v.iter().collect()),
ExprKind::Repeat(ref inner, _) |
ExprKind::Cast(ref inner, _) |
ExprKind::Type(ref inner, _) |
ExprKind::Unary(_, ref inner) |
ExprKind::Field(ref inner, _) |
ExprKind::AddrOf(_, ref inner) |
ExprKind::Box(ref inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])),
ExprKind::Struct(_, ref fields, ref base) => if has_drop(cx, expr) {
None
} else {
Some(
@ -156,7 +157,7 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option<Vec<&'a Exp
.collect(),
)
},
Expr_::ExprCall(ref callee, ref args) => if let Expr_::ExprPath(ref qpath) = callee.node {
ExprKind::Call(ref callee, ref args) => if let ExprKind::Path(ref qpath) = callee.node {
let def = cx.tables.qpath_def(qpath, callee.hir_id);
match def {
Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..)
@ -169,7 +170,7 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option<Vec<&'a Exp
} else {
None
},
Expr_::ExprBlock(ref block, _) => {
ExprKind::Block(ref block, _) => {
if block.stmts.is_empty() {
block.expr.as_ref().and_then(|e| {
match block.rules {

View File

@ -3,6 +3,7 @@
//! This lint is **deny** by default.
use rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass};
use rustc::{declare_lint, lint_array};
use rustc::hir::*;
use rustc::hir::def::Def;
use rustc::ty::{self, TypeFlags};
@ -164,7 +165,7 @@ impl LintPass for NonCopyConst {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx Item) {
if let ItemConst(hir_ty, ..) = &it.node {
if let ItemKind::Const(hir_ty, ..) = &it.node {
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
verify_ty_bound(cx, ty, Source::Item { item: it.span });
}
@ -182,7 +183,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst {
let item_node_id = cx.tcx.hir.get_parent_node(impl_item.id);
let item = cx.tcx.hir.expect_item(item_node_id);
// ensure the impl is an inherent impl.
if let ItemImpl(_, _, _, _, None, _, _) = item.node {
if let ItemKind::Impl(_, _, _, _, None, _, _) = item.node {
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
verify_ty_bound(cx, ty, Source::Assoc { ty: hir_ty.span, item: impl_item.span });
}
@ -190,7 +191,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst {
}
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let ExprPath(qpath) = &expr.node {
if let ExprKind::Path(qpath) = &expr.node {
// Only lint if we use the const item inside a function.
if in_constant(cx, expr.id) {
return;
@ -213,22 +214,22 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCopyConst {
}
if let Some(map::NodeExpr(parent_expr)) = cx.tcx.hir.find(parent_id) {
match &parent_expr.node {
ExprAddrOf(..) => {
ExprKind::AddrOf(..) => {
// `&e` => `e` must be referenced
needs_check_adjustment = false;
}
ExprField(..) => {
ExprKind::Field(..) => {
dereferenced_expr = parent_expr;
needs_check_adjustment = true;
}
ExprIndex(e, _) if ptr::eq(&**e, cur_expr) => {
ExprKind::Index(e, _) if ptr::eq(&**e, cur_expr) => {
// `e[i]` => desugared to `*Index::index(&e, i)`,
// meaning `e` must be referenced.
// no need to go further up since a method call is involved now.
needs_check_adjustment = false;
break;
}
ExprUnary(UnDeref, _) => {
ExprKind::Unary(UnDeref, _) => {
// `*e` => desugared to `*Deref::deref(&e)`,
// meaning `e` must be referenced.
// no need to go further up since a method call is involved now.

View File

@ -1,4 +1,5 @@
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use syntax::codemap::Span;
use syntax::symbol::LocalInternedString;
use syntax::ast::*;
@ -311,13 +312,13 @@ impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> {
}
impl EarlyLintPass for NonExpressiveNames {
fn check_item(&mut self, cx: &EarlyContext, item: &Item) {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
if let ItemKind::Fn(ref decl, _, _, ref blk) = item.node {
do_check(self, cx, &item.attrs, decl, blk);
}
}
fn check_impl_item(&mut self, cx: &EarlyContext, item: &ImplItem) {
fn check_impl_item(&mut self, cx: &EarlyContext<'_>, item: &ImplItem) {
if let ImplItemKind::Method(ref sig, ref blk) = item.node {
do_check(self, cx, &item.attrs, &sig.decl, blk);
}
@ -325,7 +326,7 @@ impl EarlyLintPass for NonExpressiveNames {
}
fn do_check(lint: &mut NonExpressiveNames, cx: &EarlyContext, attrs: &[Attribute], decl: &FnDecl, blk: &Block) {
fn do_check(lint: &mut NonExpressiveNames, cx: &EarlyContext<'_>, attrs: &[Attribute], decl: &FnDecl, blk: &Block) {
if !attr::contains_name(attrs, "test") {
let mut visitor = SimilarNamesLocalVisitor {
names: Vec::new(),

View File

@ -1,4 +1,6 @@
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::hir::*;
use crate::utils::{match_type, method_chain_args, paths, snippet, span_help_and_lint};
@ -44,9 +46,9 @@ impl LintPass for Pass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if_chain! { //begin checking variables
if let ExprMatch(ref op, ref body, ref source) = expr.node; //test if expr is a match
if let ExprKind::Match(ref op, ref body, ref source) = expr.node; //test if expr is a match
if let MatchSource::IfLetDesugar { .. } = *source; //test if it is an If Let
if let ExprMethodCall(_, _, ref result_types) = op.node; //check is expr.ok() has type Result<T,E>.ok()
if let ExprKind::MethodCall(_, _, ref result_types) = op.node; //check is expr.ok() has type Result<T,E>.ok()
if let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _) = body[0].pats[0].node; //get operation
if method_chain_args(op, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized;

View File

@ -1,5 +1,6 @@
use rustc::hir::{Expr, ExprLit, ExprMethodCall};
use rustc::hir::{Expr, ExprKind};
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use syntax::ast::LitKind;
use syntax::codemap::{Span, Spanned};
use crate::utils::{match_type, paths, span_lint, walk_ptrs_ty};
@ -33,7 +34,7 @@ impl LintPass for NonSensical {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSensical {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
if let ExprMethodCall(ref path, _, ref arguments) = e.node {
if let ExprKind::MethodCall(ref path, _, ref arguments) = e.node {
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&arguments[0]));
if path.ident.name == "open" && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) {
let mut options = Vec::new();
@ -60,14 +61,14 @@ enum OpenOption {
Append,
}
fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOption, Argument)>) {
if let ExprMethodCall(ref path, _, ref arguments) = argument.node {
fn get_open_options(cx: &LateContext<'_, '_>, argument: &Expr, options: &mut Vec<(OpenOption, Argument)>) {
if let ExprKind::MethodCall(ref path, _, ref arguments) = argument.node {
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&arguments[0]));
// Only proceed if this is a call on some object of type std::fs::OpenOptions
if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 2 {
let argument_option = match arguments[1].node {
ExprLit(ref span) => {
ExprKind::Lit(ref span) => {
if let Spanned {
node: LitKind::Bool(lit),
..
@ -111,7 +112,7 @@ fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOp
}
}
fn check_open_options(cx: &LateContext, options: &[(OpenOption, Argument)], span: Span) {
fn check_open_options(cx: &LateContext<'_, '_>, options: &[(OpenOption, Argument)], span: Span) {
let (mut create, mut append, mut truncate, mut read, mut write) = (false, false, false, false, false);
let (mut create_arg, mut append_arg, mut truncate_arg, mut read_arg, mut write_arg) =
(false, false, false, false, false);

View File

@ -1,6 +1,8 @@
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::hir::*;
use crate::utils::span_lint;
use crate::utils::{span_lint, SpanlessEq};
/// **What it does:** Detects classic underflow/overflow checks.
///
@ -31,24 +33,25 @@ impl LintPass for OverflowCheckConditional {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OverflowCheckConditional {
// a + b < a, a > a + b, a < a - b, a - b > a
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
let eq = |l, r| SpanlessEq::new(cx).eq_path_segment(l, r);
if_chain! {
if let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node;
if let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = first.node;
if let Expr_::ExprPath(QPath::Resolved(_, ref path1)) = ident1.node;
if let Expr_::ExprPath(QPath::Resolved(_, ref path2)) = ident2.node;
if let Expr_::ExprPath(QPath::Resolved(_, ref path3)) = second.node;
if path1.segments[0] == path3.segments[0] || path2.segments[0] == path3.segments[0];
if let ExprKind::Binary(ref op, ref first, ref second) = expr.node;
if let ExprKind::Binary(ref op2, ref ident1, ref ident2) = first.node;
if let ExprKind::Path(QPath::Resolved(_, ref path1)) = ident1.node;
if let ExprKind::Path(QPath::Resolved(_, ref path2)) = ident2.node;
if let ExprKind::Path(QPath::Resolved(_, ref path3)) = second.node;
if eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0]);
if cx.tables.expr_ty(ident1).is_integral();
if cx.tables.expr_ty(ident2).is_integral();
then {
if let BinOp_::BiLt = op.node {
if let BinOp_::BiAdd = op2.node {
if let BinOpKind::Lt = op.node {
if let BinOpKind::Add = op2.node {
span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span,
"You are trying to use classic C overflow conditions that will fail in Rust.");
}
}
if let BinOp_::BiGt = op.node {
if let BinOp_::BiSub = op2.node {
if let BinOpKind::Gt = op.node {
if let BinOpKind::Sub = op2.node {
span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span,
"You are trying to use classic C underflow conditions that will fail in Rust.");
}
@ -57,23 +60,23 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OverflowCheckConditional {
}
if_chain! {
if let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node;
if let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = second.node;
if let Expr_::ExprPath(QPath::Resolved(_, ref path1)) = ident1.node;
if let Expr_::ExprPath(QPath::Resolved(_, ref path2)) = ident2.node;
if let Expr_::ExprPath(QPath::Resolved(_, ref path3)) = first.node;
if path1.segments[0] == path3.segments[0] || path2.segments[0] == path3.segments[0];
if let ExprKind::Binary(ref op, ref first, ref second) = expr.node;
if let ExprKind::Binary(ref op2, ref ident1, ref ident2) = second.node;
if let ExprKind::Path(QPath::Resolved(_, ref path1)) = ident1.node;
if let ExprKind::Path(QPath::Resolved(_, ref path2)) = ident2.node;
if let ExprKind::Path(QPath::Resolved(_, ref path3)) = first.node;
if eq(&path1.segments[0], &path3.segments[0]) || eq(&path2.segments[0], &path3.segments[0]);
if cx.tables.expr_ty(ident1).is_integral();
if cx.tables.expr_ty(ident2).is_integral();
then {
if let BinOp_::BiGt = op.node {
if let BinOp_::BiAdd = op2.node {
if let BinOpKind::Gt = op.node {
if let BinOpKind::Add = op2.node {
span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span,
"You are trying to use classic C overflow conditions that will fail in Rust.");
}
}
if let BinOp_::BiLt = op.node {
if let BinOp_::BiSub = op2.node {
if let BinOpKind::Lt = op.node {
if let BinOpKind::Sub = op2.node {
span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span,
"You are trying to use classic C underflow conditions that will fail in Rust.");
}

View File

@ -1,5 +1,7 @@
use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use syntax::ast::LitKind;
use syntax::ptr::P;
use syntax::ext::quote::rt::Span;
@ -52,10 +54,10 @@ impl LintPass for Pass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if_chain! {
if let ExprBlock(ref block, _) = expr.node;
if let ExprKind::Block(ref block, _) = expr.node;
if let Some(ref ex) = block.expr;
if let ExprCall(ref fun, ref params) = ex.node;
if let ExprPath(ref qpath) = fun.node;
if let ExprKind::Call(ref fun, ref params) = ex.node;
if let ExprKind::Path(ref qpath) = fun.node;
if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id));
if match_def_path(cx.tcx, fun_def_id, &paths::BEGIN_PANIC);
if params.len() == 2;
@ -84,9 +86,9 @@ fn get_outer_span(expr: &Expr) -> Span {
}
}
fn match_panic(params: &P<[Expr]>, expr: &Expr, cx: &LateContext) {
fn match_panic(params: &P<[Expr]>, expr: &Expr, cx: &LateContext<'_, '_>) {
if_chain! {
if let ExprLit(ref lit) = params[0].node;
if let ExprKind::Lit(ref lit) = params[0].node;
if is_direct_expn_of(expr.span, "panic").is_some();
if let LitKind::Str(ref string, _) = lit.node;
let string = string.as_str().replace("{{", "").replace("}}", "");

View File

@ -1,4 +1,6 @@
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::hir::*;
use crate::utils::{is_automatically_derived, span_lint};
@ -38,7 +40,7 @@ impl LintPass for Pass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if_chain! {
if let ItemImpl(_, _, _, _, Some(ref trait_ref), _, ref impl_items) = item.node;
if let ItemKind::Impl(_, _, _, _, Some(ref trait_ref), _, ref impl_items) = item.node;
if !is_automatically_derived(&*item.attrs);
if let Some(eq_trait) = cx.tcx.lang_items().eq_trait();
if trait_ref.path.def.def_id() == eq_trait;

View File

@ -1,4 +1,5 @@
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use syntax::ast::*;
use syntax::codemap::Spanned;
use crate::utils::{in_macro, snippet, span_lint_and_sugg};
@ -36,7 +37,7 @@ impl LintPass for Precedence {
}
impl EarlyLintPass for Precedence {
fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
if in_macro(expr.span) {
return;
}

View File

@ -5,6 +5,8 @@ use rustc::hir::*;
use rustc::hir::map::NodeItem;
use rustc::hir::QPath;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::ty;
use syntax::ast::NodeId;
use syntax::codemap::Span;
@ -103,7 +105,7 @@ impl LintPass for PointerPass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if let ItemFn(ref decl, _, _, body_id) = item.node {
if let ItemKind::Fn(ref decl, _, _, body_id) = item.node {
check_fn(cx, decl, item.id, Some(body_id));
}
}
@ -111,7 +113,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass {
fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) {
if let ImplItemKind::Method(ref sig, body_id) = item.node {
if let Some(NodeItem(it)) = cx.tcx.hir.find(cx.tcx.hir.get_parent(item.id)) {
if let ItemImpl(_, _, _, _, Some(_), _, _) = it.node {
if let ItemKind::Impl(_, _, _, _, Some(_), _, _) = it.node {
return; // ignore trait impls
}
}
@ -131,8 +133,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass {
}
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let ExprBinary(ref op, ref l, ref r) = expr.node {
if (op.node == BiEq || op.node == BiNe) && (is_null_path(l) || is_null_path(r)) {
if let ExprKind::Binary(ref op, ref l, ref r) = expr.node {
if (op.node == BinOpKind::Eq || op.node == BinOpKind::Ne) && (is_null_path(l) || is_null_path(r)) {
span_lint(
cx,
CMP_NULL,
@ -144,7 +146,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass {
}
}
fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option<BodyId>) {
fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option<BodyId>) {
let fn_def_id = cx.tcx.hir.local_def_id(fn_id);
let sig = cx.tcx.fn_sig(fn_def_id);
let fn_ty = sig.skip_binder();
@ -159,7 +161,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option<
if match_type(cx, ty, &paths::VEC) {
let mut ty_snippet = None;
if_chain! {
if let TyPath(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).node;
if let TyKind::Path(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).node;
if let Some(&PathSegment{args: Some(ref parameters), ..}) = path.segments.last();
then {
let types: Vec<_> = parameters.args.iter().filter_map(|arg| match arg {
@ -219,8 +221,8 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option<
}
} else if match_type(cx, ty, &paths::COW) {
if_chain! {
if let TyRptr(_, MutTy { ref ty, ..} ) = arg.node;
if let TyPath(ref path) = ty.node;
if let TyKind::Rptr(_, MutTy { ref ty, ..} ) = arg.node;
if let TyKind::Path(ref path) = ty.node;
if let QPath::Resolved(None, ref pp) = *path;
if let [ref bx] = *pp.segments;
if let Some(ref params) = bx.args;
@ -273,7 +275,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option<
}
fn get_rptr_lm(ty: &Ty) -> Option<(&Lifetime, Mutability, Span)> {
if let Ty_::TyRptr(ref lt, ref m) = ty.node {
if let TyKind::Rptr(ref lt, ref m) = ty.node {
Some((lt, m.mutbl, ty.span))
} else {
None
@ -281,9 +283,9 @@ fn get_rptr_lm(ty: &Ty) -> Option<(&Lifetime, Mutability, Span)> {
}
fn is_null_path(expr: &Expr) -> bool {
if let ExprCall(ref pathexp, ref args) = expr.node {
if let ExprKind::Call(ref pathexp, ref args) = expr.node {
if args.is_empty() {
if let ExprPath(ref path) = pathexp.node {
if let ExprKind::Path(ref path) = pathexp.node {
return match_qpath(path, &paths::PTR_NULL) || match_qpath(path, &paths::PTR_NULL_MUT);
}
}

Some files were not shown because too many files have changed in this diff Show More