mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-23 13:13:34 +00:00
Merge branch 'origin/master' into flat-map
This commit is contained in:
commit
05d9f884e1
213 changed files with 3350 additions and 1588 deletions
6
.github/PULL_REQUEST_TEMPLATE
vendored
6
.github/PULL_REQUEST_TEMPLATE
vendored
|
@ -16,9 +16,11 @@ checked during review or continuous integration.
|
||||||
- [ ] Followed [lint naming conventions][lint_naming]
|
- [ ] Followed [lint naming conventions][lint_naming]
|
||||||
- [ ] Added passing UI tests (including committed `.stderr` file)
|
- [ ] Added passing UI tests (including committed `.stderr` file)
|
||||||
- [ ] `cargo test` passes locally
|
- [ ] `cargo test` passes locally
|
||||||
- [ ] Executed `util/dev update_lints`
|
- [ ] Executed `./util/dev update_lints`
|
||||||
- [ ] Added lint documentation
|
- [ ] Added lint documentation
|
||||||
- [ ] Run `cargo fmt`
|
- [ ] Run `./util/dev fmt`
|
||||||
|
|
||||||
|
[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
|
||||||
|
|
||||||
Note that you can skip the above if you are just opening a WIP PR in
|
Note that you can skip the above if you are just opening a WIP PR in
|
||||||
order to get feedback.
|
order to get feedback.
|
||||||
|
|
26
.travis.yml
26
.travis.yml
|
@ -17,6 +17,7 @@ branches:
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- RUST_BACKTRACE=1
|
- RUST_BACKTRACE=1
|
||||||
|
- secure: "OKulfkA5OGd/d1IhvBKzRkHQwMcWjzrzbimo7+5NhkUkWxndAzl+719TB3wWvIh1i2wXXrEXsyZkXM5FtRrHm55v1VKQ5ibjEvFg1w3NIg81iDyoLq186fLqywvxGkOAFPrsePPsBj5USd5xvhwwbrjO6L7/RK6Z8shBwOSc41s="
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- |
|
- |
|
||||||
|
@ -45,7 +46,7 @@ matrix:
|
||||||
- os: linux
|
- os: linux
|
||||||
env: BASE_TESTS=true
|
env: BASE_TESTS=true
|
||||||
- os: windows
|
- os: windows
|
||||||
env: CARGO_INCREMENTAL=0 BASE_TESTS=true
|
env: CARGO_INCREMENTAL=0 BASE_TESTS=true OS_WINDOWS=true
|
||||||
|
|
||||||
# Builds that are only executed when a PR is r+ed or a try build is started
|
# Builds that are only executed when a PR is r+ed or a try build is started
|
||||||
# We don't want to run these always because they go towards
|
# We don't want to run these always because they go towards
|
||||||
|
@ -81,9 +82,6 @@ matrix:
|
||||||
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
|
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
|
||||||
- env: INTEGRATION=chronotope/chrono
|
- env: INTEGRATION=chronotope/chrono
|
||||||
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
|
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
|
||||||
allow_failures:
|
|
||||||
- os: windows
|
|
||||||
env: CARGO_INCREMENTAL=0 BASE_TESTS=true
|
|
||||||
# prevent these jobs with default env vars
|
# prevent these jobs with default env vars
|
||||||
exclude:
|
exclude:
|
||||||
- os: linux
|
- os: linux
|
||||||
|
@ -91,10 +89,28 @@ matrix:
|
||||||
- os: windows
|
- os: windows
|
||||||
|
|
||||||
script:
|
script:
|
||||||
|
- |
|
||||||
|
if [ "$TRAVIS_BRANCH" == "auto" ] || [ "$TRAVIS_BRANCH" == "try" ]; then
|
||||||
|
pr=$(echo $TRAVIS_COMMIT_MESSAGE | grep -o "#[0-9]*" | head -1 | sed 's/^#//g')
|
||||||
|
output=$(curl -H "Authorization: token $GITHUB_API_TOKEN" -s "https://api.github.com/repos/rust-lang/rust-clippy/pulls/$pr" | \
|
||||||
|
python -c "import sys, json; print(json.load(sys.stdin)['body'])" | \
|
||||||
|
grep "^changelog: " | \
|
||||||
|
sed "s/changelog: //g")
|
||||||
|
if [ -z "$output" ]; then
|
||||||
|
echo "ERROR: PR body must contain 'changelog: ...'"
|
||||||
|
exit 1
|
||||||
|
elif [ "$output" = "none" ]; then
|
||||||
|
echo "WARNING: changelog is 'none'"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
- |
|
- |
|
||||||
rm rust-toolchain
|
rm rust-toolchain
|
||||||
./setup-toolchain.sh
|
./setup-toolchain.sh
|
||||||
|
if [ "$TRAVIS_OS_NAME" == "windows" ]; then
|
||||||
|
export PATH=$PATH:$(rustc --print sysroot)/bin
|
||||||
|
else
|
||||||
export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib
|
export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib
|
||||||
|
fi
|
||||||
- |
|
- |
|
||||||
if [ -z ${INTEGRATION} ]; then
|
if [ -z ${INTEGRATION} ]; then
|
||||||
travis_wait 30 ./ci/base-tests.sh && sleep 5
|
travis_wait 30 ./ci/base-tests.sh && sleep 5
|
||||||
|
@ -104,7 +120,7 @@ script:
|
||||||
|
|
||||||
after_success: |
|
after_success: |
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
if [ $(uname) == Linux ]; then
|
if [ "$TRAVIS_OS_NAME" == "linux" ]; then
|
||||||
set -ex
|
set -ex
|
||||||
if [ -z ${INTEGRATION} ]; then
|
if [ -z ${INTEGRATION} ]; then
|
||||||
./.github/deploy.sh
|
./.github/deploy.sh
|
||||||
|
|
|
@ -974,6 +974,8 @@ Released 2018-09-13
|
||||||
[`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask
|
[`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask
|
||||||
[`infallible_destructuring_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#infallible_destructuring_match
|
[`infallible_destructuring_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#infallible_destructuring_match
|
||||||
[`infinite_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#infinite_iter
|
[`infinite_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#infinite_iter
|
||||||
|
[`inherent_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#inherent_to_string
|
||||||
|
[`inherent_to_string_shadow_display`]: https://rust-lang.github.io/rust-clippy/master/index.html#inherent_to_string_shadow_display
|
||||||
[`inline_always`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_always
|
[`inline_always`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_always
|
||||||
[`inline_fn_without_body`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_fn_without_body
|
[`inline_fn_without_body`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_fn_without_body
|
||||||
[`int_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#int_plus_one
|
[`int_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#int_plus_one
|
||||||
|
@ -981,7 +983,6 @@ Released 2018-09-13
|
||||||
[`integer_division`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division
|
[`integer_division`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division
|
||||||
[`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array
|
[`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array
|
||||||
[`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref
|
[`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref
|
||||||
[`invalid_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_ref
|
|
||||||
[`invalid_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_regex
|
[`invalid_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_regex
|
||||||
[`invalid_upcast_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons
|
[`invalid_upcast_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons
|
||||||
[`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements
|
[`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements
|
||||||
|
@ -999,6 +1000,7 @@ Released 2018-09-13
|
||||||
[`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value
|
[`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value
|
||||||
[`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist
|
[`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist
|
||||||
[`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug
|
[`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug
|
||||||
|
[`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion
|
||||||
[`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy
|
[`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy
|
||||||
[`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap
|
[`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap
|
||||||
[`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names
|
[`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names
|
||||||
|
@ -1137,6 +1139,7 @@ Released 2018-09-13
|
||||||
[`trivially_copy_pass_by_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref
|
[`trivially_copy_pass_by_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref
|
||||||
[`try_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#try_err
|
[`try_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#try_err
|
||||||
[`type_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity
|
[`type_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity
|
||||||
|
[`type_repetition_in_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds
|
||||||
[`unicode_not_nfc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unicode_not_nfc
|
[`unicode_not_nfc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unicode_not_nfc
|
||||||
[`unimplemented`]: https://rust-lang.github.io/rust-clippy/master/index.html#unimplemented
|
[`unimplemented`]: https://rust-lang.github.io/rust-clippy/master/index.html#unimplemented
|
||||||
[`unit_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_arg
|
[`unit_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_arg
|
||||||
|
|
|
@ -61,4 +61,5 @@ rustc-workspace-hack = "1.0.0"
|
||||||
rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"}
|
rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"}
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
deny-warnings = []
|
||||||
debugging = []
|
debugging = []
|
||||||
|
|
31
README.md
31
README.md
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
|
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
|
||||||
|
|
||||||
[There are 306 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
|
[There are 309 lints included in this crate!](https://rust-lang.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:
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ Table of contents:
|
||||||
|
|
||||||
* [Usage instructions](#usage)
|
* [Usage instructions](#usage)
|
||||||
* [Configuration](#configuration)
|
* [Configuration](#configuration)
|
||||||
|
* [Contributing](#contributing)
|
||||||
* [License](#license)
|
* [License](#license)
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
@ -52,7 +53,7 @@ subcommand.
|
||||||
|
|
||||||
#### Step 1: Install rustup
|
#### Step 1: Install rustup
|
||||||
|
|
||||||
You can install [rustup](http://rustup.rs/) on supported platforms. This will help
|
You can install [rustup](https://rustup.rs/) on supported platforms. This will help
|
||||||
us install Clippy and its dependencies.
|
us install Clippy and its dependencies.
|
||||||
|
|
||||||
If you already have rustup installed, update to ensure you have the latest
|
If you already have rustup installed, update to ensure you have the latest
|
||||||
|
@ -79,6 +80,15 @@ Now you can run Clippy by invoking the following command:
|
||||||
cargo clippy
|
cargo clippy
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Automatically applying Clippy suggestions
|
||||||
|
|
||||||
|
Some Clippy lint suggestions can be automatically applied by `cargo fix`.
|
||||||
|
Note that this is still experimental and only supported on the nightly channel:
|
||||||
|
|
||||||
|
```terminal
|
||||||
|
cargo fix -Z unstable-options --clippy
|
||||||
|
```
|
||||||
|
|
||||||
### Running Clippy from the command line without installing it
|
### 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
|
||||||
|
@ -88,8 +98,7 @@ in your code, you can use:
|
||||||
cargo run --bin cargo-clippy --manifest-path=path_to_clippys_Cargo.toml
|
cargo run --bin cargo-clippy --manifest-path=path_to_clippys_Cargo.toml
|
||||||
```
|
```
|
||||||
|
|
||||||
*[Note](https://github.com/rust-lang/rust-clippy/wiki#a-word-of-warning):*
|
*Note:* 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!
|
|
||||||
|
|
||||||
### Travis CI
|
### Travis CI
|
||||||
|
|
||||||
|
@ -113,7 +122,7 @@ script:
|
||||||
```
|
```
|
||||||
|
|
||||||
If you are on nightly, It might happen that Clippy is not available for a certain nightly release.
|
If you are on nightly, It might happen that Clippy is not available for a certain nightly release.
|
||||||
In this case you can try to conditionally install Clippy from the git repo.
|
In this case you can try to conditionally install Clippy from the Git repo.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
language: rust
|
language: rust
|
||||||
|
@ -121,12 +130,12 @@ rust:
|
||||||
- nightly
|
- nightly
|
||||||
before_script:
|
before_script:
|
||||||
- rustup component add clippy --toolchain=nightly || cargo install --git https://github.com/rust-lang/rust-clippy/ --force clippy
|
- rustup component add clippy --toolchain=nightly || cargo install --git https://github.com/rust-lang/rust-clippy/ --force clippy
|
||||||
# etc
|
# etc.
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that adding `-D warnings` will cause your build to fail if **any** warnings are found in your code.
|
Note that adding `-D warnings` will cause your build to fail if **any** warnings are found in your code.
|
||||||
That includes warnings found by rustc (e.g. `dead_code`, etc.). If you want to avoid this and only cause
|
That includes warnings found by rustc (e.g. `dead_code`, etc.). If you want to avoid this and only cause
|
||||||
an error for clippy warnings, use `#![deny(clippy::all)]` in your code or `-D clippy::all` on the command
|
an error for Clippy warnings, use `#![deny(clippy::all)]` in your code or `-D clippy::all` on the command
|
||||||
line. (You can swap `clippy::all` with the specific lint category you are targeting.)
|
line. (You can swap `clippy::all` with the specific lint category you are targeting.)
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
@ -154,9 +163,9 @@ You can add options to your code to `allow`/`warn`/`deny` Clippy lints:
|
||||||
`#![deny(clippy::pedantic)]`). Note that `clippy::pedantic` contains some very aggressive
|
`#![deny(clippy::pedantic)]`). Note that `clippy::pedantic` contains some very aggressive
|
||||||
lints prone to false positives.
|
lints prone to false positives.
|
||||||
|
|
||||||
* only some lints (`#![deny(clippy::single_match, clippy::box_vec)]`, etc)
|
* only some lints (`#![deny(clippy::single_match, clippy::box_vec)]`, etc.)
|
||||||
|
|
||||||
* `allow`/`warn`/`deny` can be limited to a single function or module using `#[allow(...)]`, etc
|
* `allow`/`warn`/`deny` can be limited to a single function or module using `#[allow(...)]`, etc.
|
||||||
|
|
||||||
Note: `deny` produces errors instead of warnings.
|
Note: `deny` produces errors instead of warnings.
|
||||||
|
|
||||||
|
@ -171,7 +180,7 @@ If you want to contribute to Clippy, you can find more information in [CONTRIBUT
|
||||||
Copyright 2014-2019 The Rust Project Developers
|
Copyright 2014-2019 The Rust Project Developers
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)> or the MIT license
|
[https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)> or the MIT license
|
||||||
<LICENSE-MIT or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT)>, at your
|
<LICENSE-MIT or [https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT)>, at your
|
||||||
option. All files in the project carrying such notice may not be
|
option. All files in the project carrying such notice may not be
|
||||||
copied, modified, or distributed except according to those terms.
|
copied, modified, or distributed except according to those terms.
|
||||||
|
|
|
@ -8,11 +8,10 @@ environment:
|
||||||
- TARGET: x86_64-pc-windows-msvc
|
- TARGET: x86_64-pc-windows-msvc
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
# Only build AppVeyor on r+, try and the master branch
|
# Only build AppVeyor on r+ and try branch
|
||||||
only:
|
only:
|
||||||
- auto
|
- auto
|
||||||
- try
|
- try
|
||||||
- master
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
|
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
|
||||||
|
@ -23,6 +22,7 @@ install:
|
||||||
- del rust-toolchain
|
- del rust-toolchain
|
||||||
- cargo install rustup-toolchain-install-master --debug || echo "rustup-toolchain-install-master already installed"
|
- cargo install rustup-toolchain-install-master --debug || echo "rustup-toolchain-install-master already installed"
|
||||||
- rustup-toolchain-install-master %RUSTC_HASH% -f -n master
|
- rustup-toolchain-install-master %RUSTC_HASH% -f -n master
|
||||||
|
- rustup component add rustfmt --toolchain nightly & exit 0 # Format test handles missing rustfmt
|
||||||
- rustup default master
|
- rustup default master
|
||||||
- set PATH=%PATH%;C:\Users\appveyor\.rustup\toolchains\master\bin
|
- set PATH=%PATH%;C:\Users\appveyor\.rustup\toolchains\master\bin
|
||||||
- rustc -V
|
- rustc -V
|
||||||
|
|
|
@ -7,8 +7,8 @@ if [ "$TRAVIS_OS_NAME" == "linux" ]; then
|
||||||
remark -f *.md -f doc/*.md > /dev/null
|
remark -f *.md -f doc/*.md > /dev/null
|
||||||
fi
|
fi
|
||||||
# build clippy in debug mode and run tests
|
# build clippy in debug mode and run tests
|
||||||
cargo build --features debugging
|
cargo build --features "debugging deny-warnings"
|
||||||
cargo test --features debugging
|
cargo test --features "debugging deny-warnings"
|
||||||
# for faster build, share target dir between subcrates
|
# for faster build, share target dir between subcrates
|
||||||
export CARGO_TARGET_DIR=`pwd`/target/
|
export CARGO_TARGET_DIR=`pwd`/target/
|
||||||
(cd clippy_lints && cargo test)
|
(cd clippy_lints && cargo test)
|
||||||
|
@ -24,21 +24,23 @@ export CARGO_TARGET_DIR=`pwd`/target/
|
||||||
# Perform various checks for lint registration
|
# Perform various checks for lint registration
|
||||||
./util/dev update_lints --check
|
./util/dev update_lints --check
|
||||||
./util/dev --limit-stderr-length
|
./util/dev --limit-stderr-length
|
||||||
cargo +nightly fmt --all -- --check
|
|
||||||
|
|
||||||
# Check running clippy-driver without cargo
|
# Check running clippy-driver without cargo
|
||||||
(
|
(
|
||||||
export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib
|
|
||||||
|
|
||||||
# Check sysroot handling
|
# Check sysroot handling
|
||||||
sysroot=$(./target/debug/clippy-driver --print sysroot)
|
sysroot=$(./target/debug/clippy-driver --print sysroot)
|
||||||
test $sysroot = $(rustc --print sysroot)
|
test $sysroot = $(rustc --print sysroot)
|
||||||
|
|
||||||
sysroot=$(./target/debug/clippy-driver --sysroot /tmp --print sysroot)
|
if [ -z $OS_WINDOWS ]; then
|
||||||
test $sysroot = /tmp
|
desired_sysroot=/tmp
|
||||||
|
else
|
||||||
|
desired_sysroot=C:/tmp
|
||||||
|
fi
|
||||||
|
sysroot=$(./target/debug/clippy-driver --sysroot $desired_sysroot --print sysroot)
|
||||||
|
test $sysroot = $desired_sysroot
|
||||||
|
|
||||||
sysroot=$(SYSROOT=/tmp ./target/debug/clippy-driver --print sysroot)
|
sysroot=$(SYSROOT=$desired_sysroot ./target/debug/clippy-driver --print sysroot)
|
||||||
test $sysroot = /tmp
|
test $sysroot = $desired_sysroot
|
||||||
|
|
||||||
# Make sure this isn't set - clippy-driver should cope without it
|
# Make sure this isn't set - clippy-driver should cope without it
|
||||||
unset CARGO_MANIFEST_DIR
|
unset CARGO_MANIFEST_DIR
|
||||||
|
@ -50,32 +52,3 @@ cargo +nightly fmt --all -- --check
|
||||||
|
|
||||||
# TODO: CLIPPY_CONF_DIR / CARGO_MANIFEST_DIR
|
# TODO: CLIPPY_CONF_DIR / CARGO_MANIFEST_DIR
|
||||||
)
|
)
|
||||||
|
|
||||||
# make sure tests are formatted
|
|
||||||
|
|
||||||
# some lints are sensitive to formatting, exclude some files
|
|
||||||
tests_need_reformatting="false"
|
|
||||||
# switch to nightly
|
|
||||||
rustup override set nightly
|
|
||||||
# avoid loop spam and allow cmds with exit status != 0
|
|
||||||
set +ex
|
|
||||||
|
|
||||||
# Excluding `ice-3891.rs` because the code triggers a rustc parse error which
|
|
||||||
# makes rustfmt fail.
|
|
||||||
for file in `find tests -not -path "tests/ui/crashes/ice-3891.rs" | grep "\.rs$"` ; do
|
|
||||||
rustfmt ${file} --check
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "${file} needs reformatting!"
|
|
||||||
tests_need_reformatting="true"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
set -ex # reset
|
|
||||||
|
|
||||||
if [ "${tests_need_reformatting}" == "true" ] ; then
|
|
||||||
echo "Tests need reformatting!"
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
# switch back to master
|
|
||||||
rustup override set master
|
|
||||||
|
|
|
@ -9,4 +9,5 @@ clap = "2.33"
|
||||||
itertools = "0.8"
|
itertools = "0.8"
|
||||||
regex = "1"
|
regex = "1"
|
||||||
lazy_static = "1.0"
|
lazy_static = "1.0"
|
||||||
|
shell-escape = "0.1"
|
||||||
walkdir = "2"
|
walkdir = "2"
|
||||||
|
|
200
clippy_dev/src/fmt.rs
Normal file
200
clippy_dev/src/fmt.rs
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
use shell_escape::escape;
|
||||||
|
use std::ffi::OsStr;
|
||||||
|
use std::io;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::process::{self, Command};
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum CliError {
|
||||||
|
CommandFailed(String),
|
||||||
|
IoError(io::Error),
|
||||||
|
ProjectRootNotFound,
|
||||||
|
RustfmtNotInstalled,
|
||||||
|
WalkDirError(walkdir::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<io::Error> for CliError {
|
||||||
|
fn from(error: io::Error) -> Self {
|
||||||
|
Self::IoError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<walkdir::Error> for CliError {
|
||||||
|
fn from(error: walkdir::Error) -> Self {
|
||||||
|
Self::WalkDirError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FmtContext {
|
||||||
|
check: bool,
|
||||||
|
verbose: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(check: bool, verbose: bool) {
|
||||||
|
fn try_run(context: &FmtContext) -> Result<bool, CliError> {
|
||||||
|
let mut success = true;
|
||||||
|
|
||||||
|
let project_root = project_root()?;
|
||||||
|
|
||||||
|
rustfmt_test(context)?;
|
||||||
|
|
||||||
|
success &= cargo_fmt(context, project_root.as_path())?;
|
||||||
|
success &= cargo_fmt(context, &project_root.join("clippy_dev"))?;
|
||||||
|
success &= cargo_fmt(context, &project_root.join("rustc_tools_util"))?;
|
||||||
|
|
||||||
|
for entry in WalkDir::new(project_root.join("tests")) {
|
||||||
|
let entry = entry?;
|
||||||
|
let path = entry.path();
|
||||||
|
|
||||||
|
if path.extension() != Some("rs".as_ref())
|
||||||
|
|| entry.file_name() == "ice-3891.rs"
|
||||||
|
// Avoid rustfmt bug rust-lang/rustfmt#1873
|
||||||
|
|| cfg!(windows) && entry.file_name() == "implicit_hasher.rs"
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
success &= rustfmt(context, &path)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(success)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn output_err(err: CliError) {
|
||||||
|
match err {
|
||||||
|
CliError::CommandFailed(command) => {
|
||||||
|
eprintln!("error: A command failed! `{}`", command);
|
||||||
|
},
|
||||||
|
CliError::IoError(err) => {
|
||||||
|
eprintln!("error: {}", err);
|
||||||
|
},
|
||||||
|
CliError::ProjectRootNotFound => {
|
||||||
|
eprintln!("error: Can't determine root of project. Please run inside a Clippy working dir.");
|
||||||
|
},
|
||||||
|
CliError::RustfmtNotInstalled => {
|
||||||
|
eprintln!("error: rustfmt nightly is not installed.");
|
||||||
|
},
|
||||||
|
CliError::WalkDirError(err) => {
|
||||||
|
eprintln!("error: {}", err);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let context = FmtContext { check, verbose };
|
||||||
|
let result = try_run(&context);
|
||||||
|
let code = match result {
|
||||||
|
Ok(true) => 0,
|
||||||
|
Ok(false) => {
|
||||||
|
eprintln!();
|
||||||
|
eprintln!("Formatting check failed.");
|
||||||
|
eprintln!("Run `./util/dev fmt` to update formatting.");
|
||||||
|
1
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
output_err(err);
|
||||||
|
1
|
||||||
|
},
|
||||||
|
};
|
||||||
|
process::exit(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_command(program: impl AsRef<OsStr>, dir: impl AsRef<Path>, args: &[impl AsRef<OsStr>]) -> String {
|
||||||
|
let arg_display: Vec<_> = args
|
||||||
|
.iter()
|
||||||
|
.map(|a| escape(a.as_ref().to_string_lossy()).to_owned())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
format!(
|
||||||
|
"cd {} && {} {}",
|
||||||
|
escape(dir.as_ref().to_string_lossy()),
|
||||||
|
escape(program.as_ref().to_string_lossy()),
|
||||||
|
arg_display.join(" ")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exec(
|
||||||
|
context: &FmtContext,
|
||||||
|
program: impl AsRef<OsStr>,
|
||||||
|
dir: impl AsRef<Path>,
|
||||||
|
args: &[impl AsRef<OsStr>],
|
||||||
|
) -> Result<bool, CliError> {
|
||||||
|
if context.verbose {
|
||||||
|
println!("{}", format_command(&program, &dir, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut child = Command::new(&program).current_dir(&dir).args(args.iter()).spawn()?;
|
||||||
|
let code = child.wait()?;
|
||||||
|
let success = code.success();
|
||||||
|
|
||||||
|
if !context.check && !success {
|
||||||
|
return Err(CliError::CommandFailed(format_command(&program, &dir, args)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(success)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cargo_fmt(context: &FmtContext, path: &Path) -> Result<bool, CliError> {
|
||||||
|
let mut args = vec!["+nightly", "fmt", "--all"];
|
||||||
|
if context.check {
|
||||||
|
args.push("--");
|
||||||
|
args.push("--check");
|
||||||
|
}
|
||||||
|
let success = exec(context, "cargo", path, &args)?;
|
||||||
|
|
||||||
|
Ok(success)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rustfmt_test(context: &FmtContext) -> Result<(), CliError> {
|
||||||
|
let program = "rustfmt";
|
||||||
|
let dir = std::env::current_dir()?;
|
||||||
|
let args = &["+nightly", "--version"];
|
||||||
|
|
||||||
|
if context.verbose {
|
||||||
|
println!("{}", format_command(&program, &dir, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
let output = Command::new(&program).current_dir(&dir).args(args.iter()).output()?;
|
||||||
|
|
||||||
|
if output.status.success() {
|
||||||
|
Ok(())
|
||||||
|
} else if std::str::from_utf8(&output.stderr)
|
||||||
|
.unwrap_or("")
|
||||||
|
.starts_with("error: 'rustfmt' is not installed")
|
||||||
|
{
|
||||||
|
Err(CliError::RustfmtNotInstalled)
|
||||||
|
} else {
|
||||||
|
Err(CliError::CommandFailed(format_command(&program, &dir, args)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rustfmt(context: &FmtContext, path: &Path) -> Result<bool, CliError> {
|
||||||
|
let mut args = vec!["+nightly".as_ref(), path.as_os_str()];
|
||||||
|
if context.check {
|
||||||
|
args.push("--check".as_ref());
|
||||||
|
}
|
||||||
|
let success = exec(context, "rustfmt", std::env::current_dir()?, &args)?;
|
||||||
|
if !success {
|
||||||
|
eprintln!("rustfmt failed on {}", path.display());
|
||||||
|
}
|
||||||
|
Ok(success)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn project_root() -> Result<PathBuf, CliError> {
|
||||||
|
let current_dir = std::env::current_dir()?;
|
||||||
|
for path in current_dir.ancestors() {
|
||||||
|
let result = std::fs::read_to_string(path.join("Cargo.toml"));
|
||||||
|
if let Err(err) = &result {
|
||||||
|
if err.kind() == io::ErrorKind::NotFound {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = result?;
|
||||||
|
if content.contains("[package]\nname = \"clippy\"") {
|
||||||
|
return Ok(path.to_path_buf());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(CliError::ProjectRootNotFound)
|
||||||
|
}
|
|
@ -4,6 +4,8 @@ extern crate regex;
|
||||||
|
|
||||||
use clap::{App, Arg, SubCommand};
|
use clap::{App, Arg, SubCommand};
|
||||||
use clippy_dev::*;
|
use clippy_dev::*;
|
||||||
|
|
||||||
|
mod fmt;
|
||||||
mod stderr_length_check;
|
mod stderr_length_check;
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
|
@ -14,6 +16,21 @@ enum UpdateMode {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let matches = App::new("Clippy developer tooling")
|
let matches = App::new("Clippy developer tooling")
|
||||||
|
.subcommand(
|
||||||
|
SubCommand::with_name("fmt")
|
||||||
|
.about("Run rustfmt on all projects and tests")
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("check")
|
||||||
|
.long("check")
|
||||||
|
.help("Use the rustfmt --check option"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("verbose")
|
||||||
|
.short("v")
|
||||||
|
.long("verbose")
|
||||||
|
.help("Echo commands run"),
|
||||||
|
),
|
||||||
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
SubCommand::with_name("update_lints")
|
SubCommand::with_name("update_lints")
|
||||||
.about("Updates lint registration and information from the source code")
|
.about("Updates lint registration and information from the source code")
|
||||||
|
@ -46,7 +63,12 @@ fn main() {
|
||||||
if matches.is_present("limit-stderr-length") {
|
if matches.is_present("limit-stderr-length") {
|
||||||
stderr_length_check::check();
|
stderr_length_check::check();
|
||||||
}
|
}
|
||||||
if let Some(matches) = matches.subcommand_matches("update_lints") {
|
|
||||||
|
match matches.subcommand() {
|
||||||
|
("fmt", Some(matches)) => {
|
||||||
|
fmt::run(matches.is_present("check"), matches.is_present("verbose"));
|
||||||
|
},
|
||||||
|
("update_lints", Some(matches)) => {
|
||||||
if matches.is_present("print-only") {
|
if matches.is_present("print-only") {
|
||||||
print_lints();
|
print_lints();
|
||||||
} else if matches.is_present("check") {
|
} else if matches.is_present("check") {
|
||||||
|
@ -54,6 +76,8 @@ fn main() {
|
||||||
} else {
|
} else {
|
||||||
update_lints(&UpdateMode::Change);
|
update_lints(&UpdateMode::Change);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::io::prelude::*;
|
||||||
// The maximum length allowed for stderr files.
|
// The maximum length allowed for stderr files.
|
||||||
//
|
//
|
||||||
// We limit this because small files are easier to deal with than bigger files.
|
// We limit this because small files are easier to deal with than bigger files.
|
||||||
const LIMIT: usize = 320;
|
const LIMIT: usize = 275;
|
||||||
|
|
||||||
pub fn check() {
|
pub fn check() {
|
||||||
let stderr_files = stderr_files();
|
let stderr_files = stderr_files();
|
||||||
|
@ -23,8 +23,7 @@ pub fn check() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exceeding_stderr_files(files: impl Iterator<Item = walkdir::DirEntry>) -> impl Iterator<Item = String> {
|
fn exceeding_stderr_files(files: impl Iterator<Item = walkdir::DirEntry>) -> impl Iterator<Item = String> {
|
||||||
files
|
files.filter_map(|file| {
|
||||||
.filter_map(|file| {
|
|
||||||
let path = file.path().to_str().expect("Could not convert path to str").to_string();
|
let path = file.path().to_str().expect("Could not convert path to str").to_string();
|
||||||
let linecount = count_linenumbers(&path);
|
let linecount = count_linenumbers(&path);
|
||||||
if linecount > LIMIT {
|
if linecount > LIMIT {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "clippy_dummy" # rename to clippy before publishing
|
name = "clippy_dummy" # rename to clippy before publishing
|
||||||
version = "0.0.302"
|
version = "0.0.303"
|
||||||
authors = ["Manish Goregaokar <manishsmail@gmail.com>"]
|
authors = ["Manish Goregaokar <manishsmail@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
readme = "crates-readme.md"
|
readme = "crates-readme.md"
|
||||||
|
|
|
@ -3,7 +3,7 @@ extern crate term;
|
||||||
fn main() {
|
fn main() {
|
||||||
if let Err(_) = foo() {
|
if let Err(_) = foo() {
|
||||||
eprintln!("error: Clippy is no longer available via crates.io\n");
|
eprintln!("error: Clippy is no longer available via crates.io\n");
|
||||||
eprintln!("help: please run `rustup component add clippy-preview` instead");
|
eprintln!("help: please run `rustup component add clippy` instead");
|
||||||
}
|
}
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ fn foo() -> Result<(), ()> {
|
||||||
write!(t, "please run `").map_err(|_| ())?;
|
write!(t, "please run `").map_err(|_| ())?;
|
||||||
|
|
||||||
t.attr(term::Attr::Bold).map_err(|_| ())?;
|
t.attr(term::Attr::Bold).map_err(|_| ())?;
|
||||||
write!(t, "rustup component add clippy-preview").map_err(|_| ())?;
|
write!(t, "rustup component add clippy").map_err(|_| ())?;
|
||||||
|
|
||||||
t.reset().map_err(|_| ())?;
|
t.reset().map_err(|_| ())?;
|
||||||
t.fg(term::color::WHITE).map_err(|_| ())?;
|
t.fg(term::color::WHITE).map_err(|_| ())?;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
Installing clippy via crates.io is deprecated. Please use the following:
|
Installing clippy via crates.io is deprecated. Please use the following:
|
||||||
|
|
||||||
```terminal
|
```terminal
|
||||||
rustup component add clippy-preview
|
rustup component add clippy
|
||||||
```
|
```
|
||||||
|
|
||||||
on a Rust version 1.29 or later. You may need to run `rustup self update` if it complains about a missing clippy binary.
|
on a Rust version 1.29 or later. You may need to run `rustup self update` if it complains about a missing clippy binary.
|
||||||
|
|
|
@ -27,7 +27,7 @@ semver = "0.9.0"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
toml = "0.5"
|
toml = "0.5"
|
||||||
unicode-normalization = "0.1"
|
unicode-normalization = "0.1"
|
||||||
pulldown-cmark = "0.5.2"
|
pulldown-cmark = "0.5.3"
|
||||||
url = "1.7.0"
|
url = "1.7.0"
|
||||||
if_chain = "1.0.0"
|
if_chain = "1.0.0"
|
||||||
smallvec = { version = "0.6.5", features = ["union"] }
|
smallvec = { version = "0.6.5", features = ["union"] }
|
||||||
|
|
|
@ -16,7 +16,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// a + 1
|
/// # let a = 0;
|
||||||
|
/// a + 1;
|
||||||
/// ```
|
/// ```
|
||||||
pub INTEGER_ARITHMETIC,
|
pub INTEGER_ARITHMETIC,
|
||||||
restriction,
|
restriction,
|
||||||
|
@ -33,7 +34,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// a + 1.0
|
/// # let a = 0.0;
|
||||||
|
/// a + 1.0;
|
||||||
/// ```
|
/// ```
|
||||||
pub FLOAT_ARITHMETIC,
|
pub FLOAT_ARITHMETIC,
|
||||||
restriction,
|
restriction,
|
||||||
|
|
|
@ -45,7 +45,8 @@ declare_clippy_lint! {
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let mut a = 5;
|
/// let mut a = 5;
|
||||||
/// ...
|
/// let b = 2;
|
||||||
|
/// // ...
|
||||||
/// a += a + b;
|
/// a += a + b;
|
||||||
/// ```
|
/// ```
|
||||||
pub MISREFACTORED_ASSIGN_OP,
|
pub MISREFACTORED_ASSIGN_OP,
|
||||||
|
|
|
@ -113,19 +113,19 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// // Bad
|
|
||||||
/// #[inline(always)]
|
|
||||||
///
|
|
||||||
/// fn not_quite_good_code(..) { ... }
|
|
||||||
///
|
|
||||||
/// // Good (as inner attribute)
|
/// // Good (as inner attribute)
|
||||||
/// #![inline(always)]
|
/// #![inline(always)]
|
||||||
///
|
///
|
||||||
/// fn this_is_fine(..) { ... }
|
/// fn this_is_fine() { }
|
||||||
|
///
|
||||||
|
/// // Bad
|
||||||
|
/// #[inline(always)]
|
||||||
|
///
|
||||||
|
/// fn not_quite_good_code() { }
|
||||||
///
|
///
|
||||||
/// // Good (as outer attribute)
|
/// // Good (as outer attribute)
|
||||||
/// #[inline(always)]
|
/// #[inline(always)]
|
||||||
/// fn this_is_fine_too(..) { ... }
|
/// fn this_is_fine_too() { }
|
||||||
/// ```
|
/// ```
|
||||||
pub EMPTY_LINE_AFTER_OUTER_ATTR,
|
pub EMPTY_LINE_AFTER_OUTER_ATTR,
|
||||||
nursery,
|
nursery,
|
||||||
|
|
|
@ -24,7 +24,8 @@ declare_clippy_lint! {
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// &my_data.filter(|&x| x == 0u8).count() // use bytecount::count instead
|
/// # let vec = vec![1_u8];
|
||||||
|
/// &vec.iter().filter(|x| **x == 0u8).count(); // use bytecount::count instead
|
||||||
/// ```
|
/// ```
|
||||||
pub NAIVE_BYTECOUNT,
|
pub NAIVE_BYTECOUNT,
|
||||||
perf,
|
perf,
|
||||||
|
|
|
@ -27,6 +27,8 @@ declare_clippy_lint! {
|
||||||
/// Could be written:
|
/// Could be written:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # use std::convert::TryFrom;
|
||||||
|
/// # let foo = 1;
|
||||||
/// # let _ =
|
/// # let _ =
|
||||||
/// i32::try_from(foo).is_ok()
|
/// i32::try_from(foo).is_ok()
|
||||||
/// # ;
|
/// # ;
|
||||||
|
@ -160,12 +162,12 @@ impl ConversionType {
|
||||||
/// Creates a conversion type if the type is allowed & conversion is valid
|
/// Creates a conversion type if the type is allowed & conversion is valid
|
||||||
fn try_new(from: &str, to: &str) -> Option<Self> {
|
fn try_new(from: &str, to: &str) -> Option<Self> {
|
||||||
if UINTS.contains(&from) {
|
if UINTS.contains(&from) {
|
||||||
Some(ConversionType::FromUnsigned)
|
Some(Self::FromUnsigned)
|
||||||
} else if SINTS.contains(&from) {
|
} else if SINTS.contains(&from) {
|
||||||
if UINTS.contains(&to) {
|
if UINTS.contains(&to) {
|
||||||
Some(ConversionType::SignedToUnsigned)
|
Some(Self::SignedToUnsigned)
|
||||||
} else if SINTS.contains(&to) {
|
} else if SINTS.contains(&to) {
|
||||||
Some(ConversionType::SignedToSigned)
|
Some(Self::SignedToSigned)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,27 +48,25 @@ pub enum Constant {
|
||||||
impl PartialEq for Constant {
|
impl PartialEq for Constant {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(&Constant::Str(ref ls), &Constant::Str(ref rs)) => ls == rs,
|
(&Self::Str(ref ls), &Self::Str(ref rs)) => ls == rs,
|
||||||
(&Constant::Binary(ref l), &Constant::Binary(ref r)) => l == r,
|
(&Self::Binary(ref l), &Self::Binary(ref r)) => l == r,
|
||||||
(&Constant::Char(l), &Constant::Char(r)) => l == r,
|
(&Self::Char(l), &Self::Char(r)) => l == r,
|
||||||
(&Constant::Int(l), &Constant::Int(r)) => l == r,
|
(&Self::Int(l), &Self::Int(r)) => l == r,
|
||||||
(&Constant::F64(l), &Constant::F64(r)) => {
|
(&Self::F64(l), &Self::F64(r)) => {
|
||||||
// We want `Fw32 == FwAny` and `FwAny == Fw64`, and by transitivity we must have
|
// We want `Fw32 == FwAny` and `FwAny == Fw64`, and by transitivity we must have
|
||||||
// `Fw32 == Fw64`, so don’t compare them.
|
// `Fw32 == Fw64`, so don’t compare them.
|
||||||
// `to_bits` is required to catch non-matching 0.0, -0.0, and NaNs.
|
// `to_bits` is required to catch non-matching 0.0, -0.0, and NaNs.
|
||||||
l.to_bits() == r.to_bits()
|
l.to_bits() == r.to_bits()
|
||||||
},
|
},
|
||||||
(&Constant::F32(l), &Constant::F32(r)) => {
|
(&Self::F32(l), &Self::F32(r)) => {
|
||||||
// We want `Fw32 == FwAny` and `FwAny == Fw64`, and by transitivity we must have
|
// We want `Fw32 == FwAny` and `FwAny == Fw64`, and by transitivity we must have
|
||||||
// `Fw32 == Fw64`, so don’t compare them.
|
// `Fw32 == Fw64`, so don’t compare them.
|
||||||
// `to_bits` is required to catch non-matching 0.0, -0.0, and NaNs.
|
// `to_bits` is required to catch non-matching 0.0, -0.0, and NaNs.
|
||||||
f64::from(l).to_bits() == f64::from(r).to_bits()
|
f64::from(l).to_bits() == f64::from(r).to_bits()
|
||||||
},
|
},
|
||||||
(&Constant::Bool(l), &Constant::Bool(r)) => l == r,
|
(&Self::Bool(l), &Self::Bool(r)) => l == r,
|
||||||
(&Constant::Vec(ref l), &Constant::Vec(ref r)) | (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) => {
|
(&Self::Vec(ref l), &Self::Vec(ref r)) | (&Self::Tuple(ref l), &Self::Tuple(ref r)) => l == r,
|
||||||
l == r
|
(&Self::Repeat(ref lv, ref ls), &Self::Repeat(ref rv, ref rs)) => ls == rs && lv == rv,
|
||||||
},
|
|
||||||
(&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => ls == rs && lv == rv,
|
|
||||||
// TODO: are there inter-type equalities?
|
// TODO: are there inter-type equalities?
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -82,38 +80,38 @@ impl Hash for Constant {
|
||||||
{
|
{
|
||||||
std::mem::discriminant(self).hash(state);
|
std::mem::discriminant(self).hash(state);
|
||||||
match *self {
|
match *self {
|
||||||
Constant::Str(ref s) => {
|
Self::Str(ref s) => {
|
||||||
s.hash(state);
|
s.hash(state);
|
||||||
},
|
},
|
||||||
Constant::Binary(ref b) => {
|
Self::Binary(ref b) => {
|
||||||
b.hash(state);
|
b.hash(state);
|
||||||
},
|
},
|
||||||
Constant::Char(c) => {
|
Self::Char(c) => {
|
||||||
c.hash(state);
|
c.hash(state);
|
||||||
},
|
},
|
||||||
Constant::Int(i) => {
|
Self::Int(i) => {
|
||||||
i.hash(state);
|
i.hash(state);
|
||||||
},
|
},
|
||||||
Constant::F32(f) => {
|
Self::F32(f) => {
|
||||||
f64::from(f).to_bits().hash(state);
|
f64::from(f).to_bits().hash(state);
|
||||||
},
|
},
|
||||||
Constant::F64(f) => {
|
Self::F64(f) => {
|
||||||
f.to_bits().hash(state);
|
f.to_bits().hash(state);
|
||||||
},
|
},
|
||||||
Constant::Bool(b) => {
|
Self::Bool(b) => {
|
||||||
b.hash(state);
|
b.hash(state);
|
||||||
},
|
},
|
||||||
Constant::Vec(ref v) | Constant::Tuple(ref v) => {
|
Self::Vec(ref v) | Self::Tuple(ref v) => {
|
||||||
v.hash(state);
|
v.hash(state);
|
||||||
},
|
},
|
||||||
Constant::Repeat(ref c, l) => {
|
Self::Repeat(ref c, l) => {
|
||||||
c.hash(state);
|
c.hash(state);
|
||||||
l.hash(state);
|
l.hash(state);
|
||||||
},
|
},
|
||||||
Constant::RawPtr(u) => {
|
Self::RawPtr(u) => {
|
||||||
u.hash(state);
|
u.hash(state);
|
||||||
},
|
},
|
||||||
Constant::Err(ref s) => {
|
Self::Err(ref s) => {
|
||||||
s.hash(state);
|
s.hash(state);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -123,25 +121,25 @@ impl Hash for Constant {
|
||||||
impl Constant {
|
impl Constant {
|
||||||
pub fn partial_cmp(tcx: TyCtxt<'_>, cmp_type: Ty<'_>, left: &Self, right: &Self) -> Option<Ordering> {
|
pub fn partial_cmp(tcx: TyCtxt<'_>, cmp_type: Ty<'_>, left: &Self, right: &Self) -> Option<Ordering> {
|
||||||
match (left, right) {
|
match (left, right) {
|
||||||
(&Constant::Str(ref ls), &Constant::Str(ref rs)) => Some(ls.cmp(rs)),
|
(&Self::Str(ref ls), &Self::Str(ref rs)) => Some(ls.cmp(rs)),
|
||||||
(&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)),
|
(&Self::Char(ref l), &Self::Char(ref r)) => Some(l.cmp(r)),
|
||||||
(&Constant::Int(l), &Constant::Int(r)) => {
|
(&Self::Int(l), &Self::Int(r)) => {
|
||||||
if let ty::Int(int_ty) = cmp_type.sty {
|
if let ty::Int(int_ty) = cmp_type.sty {
|
||||||
Some(sext(tcx, l, int_ty).cmp(&sext(tcx, r, int_ty)))
|
Some(sext(tcx, l, int_ty).cmp(&sext(tcx, r, int_ty)))
|
||||||
} else {
|
} else {
|
||||||
Some(l.cmp(&r))
|
Some(l.cmp(&r))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(&Constant::F64(l), &Constant::F64(r)) => l.partial_cmp(&r),
|
(&Self::F64(l), &Self::F64(r)) => l.partial_cmp(&r),
|
||||||
(&Constant::F32(l), &Constant::F32(r)) => l.partial_cmp(&r),
|
(&Self::F32(l), &Self::F32(r)) => l.partial_cmp(&r),
|
||||||
(&Constant::Bool(ref l), &Constant::Bool(ref r)) => Some(l.cmp(r)),
|
(&Self::Bool(ref l), &Self::Bool(ref r)) => Some(l.cmp(r)),
|
||||||
(&Constant::Tuple(ref l), &Constant::Tuple(ref r)) | (&Constant::Vec(ref l), &Constant::Vec(ref r)) => l
|
(&Self::Tuple(ref l), &Self::Tuple(ref r)) | (&Self::Vec(ref l), &Self::Vec(ref r)) => l
|
||||||
.iter()
|
.iter()
|
||||||
.zip(r.iter())
|
.zip(r.iter())
|
||||||
.map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri))
|
.map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri))
|
||||||
.find(|r| r.map_or(true, |o| o != Ordering::Equal))
|
.find(|r| r.map_or(true, |o| o != Ordering::Equal))
|
||||||
.unwrap_or_else(|| Some(l.len().cmp(&r.len()))),
|
.unwrap_or_else(|| Some(l.len().cmp(&r.len()))),
|
||||||
(&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => {
|
(&Self::Repeat(ref lv, ref ls), &Self::Repeat(ref rv, ref rs)) => {
|
||||||
match Self::partial_cmp(tcx, cmp_type, lv, rv) {
|
match Self::partial_cmp(tcx, cmp_type, lv, rv) {
|
||||||
Some(Equal) => Some(ls.cmp(rs)),
|
Some(Equal) => Some(ls.cmp(rs)),
|
||||||
x => x,
|
x => x,
|
||||||
|
@ -232,7 +230,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
|
||||||
ExprKind::Tup(ref tup) => self.multi(tup).map(Constant::Tuple),
|
ExprKind::Tup(ref tup) => self.multi(tup).map(Constant::Tuple),
|
||||||
ExprKind::Repeat(ref value, _) => {
|
ExprKind::Repeat(ref value, _) => {
|
||||||
let n = match self.tables.expr_ty(e).sty {
|
let n = match self.tables.expr_ty(e).sty {
|
||||||
ty::Array(_, n) => n.assert_usize(self.lcx.tcx).expect("array length"),
|
ty::Array(_, n) => n.eval_usize(self.lcx.tcx, self.lcx.param_env),
|
||||||
_ => span_bug!(e.span, "typeck error"),
|
_ => span_bug!(e.span, "typeck error"),
|
||||||
};
|
};
|
||||||
self.expr(value).map(|v| Constant::Repeat(Box::new(v), n))
|
self.expr(value).map(|v| Constant::Repeat(Box::new(v), n))
|
||||||
|
|
|
@ -13,7 +13,7 @@ declare_clippy_lint! {
|
||||||
/// **Known problems:** None.
|
/// **Known problems:** None.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// #[derive(Copy, Clone)]
|
/// #[derive(Copy, Clone)]
|
||||||
/// struct Countdown(u8);
|
/// struct Countdown(u8);
|
||||||
///
|
///
|
||||||
|
|
|
@ -113,3 +113,12 @@ declare_deprecated_lint! {
|
||||||
pub UNSAFE_VECTOR_INITIALIZATION,
|
pub UNSAFE_VECTOR_INITIALIZATION,
|
||||||
"the replacement suggested by this lint had substantially different behavior"
|
"the replacement suggested by this lint had substantially different behavior"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// **What it does:** Nothing. This lint has been deprecated.
|
||||||
|
///
|
||||||
|
/// **Deprecation reason:** This lint has been superseded by the warn-by-default
|
||||||
|
/// `invalid_value` rustc lint.
|
||||||
|
declare_clippy_lint! {
|
||||||
|
pub INVALID_REF,
|
||||||
|
"superseded by rustc lint `invalid_value`"
|
||||||
|
}
|
||||||
|
|
|
@ -49,12 +49,12 @@ declare_clippy_lint! {
|
||||||
/// **Known problems:** Bounds of generic types are sometimes wrong: https://github.com/rust-lang/rust/issues/26925
|
/// **Known problems:** Bounds of generic types are sometimes wrong: https://github.com/rust-lang/rust/issues/26925
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// #[derive(Copy)]
|
/// #[derive(Copy)]
|
||||||
/// struct Foo;
|
/// struct Foo;
|
||||||
///
|
///
|
||||||
/// impl Clone for Foo {
|
/// impl Clone for Foo {
|
||||||
/// ..
|
/// // ..
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub EXPL_IMPL_CLONE_ON_COPY,
|
pub EXPL_IMPL_CLONE_ON_COPY,
|
||||||
|
|
|
@ -27,7 +27,7 @@ declare_clippy_lint! {
|
||||||
/// /// Do something with the foo_bar parameter. See also
|
/// /// Do something with the foo_bar parameter. See also
|
||||||
/// /// that::other::module::foo.
|
/// /// that::other::module::foo.
|
||||||
/// // ^ `foo_bar` and `that::other::module::foo` should be ticked.
|
/// // ^ `foo_bar` and `that::other::module::foo` should be ticked.
|
||||||
/// fn doit(foo_bar) { .. }
|
/// fn doit(foo_bar: usize) {}
|
||||||
/// ```
|
/// ```
|
||||||
pub DOC_MARKDOWN,
|
pub DOC_MARKDOWN,
|
||||||
pedantic,
|
pedantic,
|
||||||
|
|
|
@ -18,13 +18,17 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// x == y || x < y
|
/// # let x = 1;
|
||||||
|
/// # let y = 2;
|
||||||
|
/// if x == y || x < y {}
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Could be written as:
|
/// Could be written as:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// x <= y
|
/// # let x = 1;
|
||||||
|
/// # let y = 2;
|
||||||
|
/// if x <= y {}
|
||||||
/// ```
|
/// ```
|
||||||
pub DOUBLE_COMPARISONS,
|
pub DOUBLE_COMPARISONS,
|
||||||
complexity,
|
complexity,
|
||||||
|
@ -63,6 +67,7 @@ impl<'a, 'tcx> DoubleComparisons {
|
||||||
);
|
);
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
#[rustfmt::skip]
|
||||||
match (op, lkind, rkind) {
|
match (op, lkind, rkind) {
|
||||||
(BinOpKind::Or, BinOpKind::Eq, BinOpKind::Lt) | (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Eq) => {
|
(BinOpKind::Or, BinOpKind::Eq, BinOpKind::Lt) | (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Eq) => {
|
||||||
lint_double_comparison!(<=)
|
lint_double_comparison!(<=)
|
||||||
|
|
|
@ -13,9 +13,10 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// ((0))
|
/// # fn foo(bar: usize) {}
|
||||||
/// foo((0))
|
/// ((0));
|
||||||
/// ((1, 2))
|
/// foo((0));
|
||||||
|
/// ((1, 2));
|
||||||
/// ```
|
/// ```
|
||||||
pub DOUBLE_PARENS,
|
pub DOUBLE_PARENS,
|
||||||
complexity,
|
complexity,
|
||||||
|
|
|
@ -20,6 +20,7 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # use std::time::Duration;
|
||||||
/// let dur = Duration::new(5, 0);
|
/// let dur = Duration::new(5, 0);
|
||||||
/// let _micros = dur.subsec_nanos() / 1_000;
|
/// let _micros = dur.subsec_nanos() / 1_000;
|
||||||
/// let _millis = dur.subsec_nanos() / 1_000_000;
|
/// let _millis = dur.subsec_nanos() / 1_000_000;
|
||||||
|
|
|
@ -16,6 +16,9 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # fn a() {}
|
||||||
|
/// # fn b() {}
|
||||||
|
/// # let x: i32 = 1;
|
||||||
/// if x.is_positive() {
|
/// if x.is_positive() {
|
||||||
/// a();
|
/// a();
|
||||||
/// } else if x.is_negative() {
|
/// } else if x.is_negative() {
|
||||||
|
@ -26,6 +29,9 @@ declare_clippy_lint! {
|
||||||
/// Could be written:
|
/// Could be written:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # fn a() {}
|
||||||
|
/// # fn b() {}
|
||||||
|
/// # let x: i32 = 1;
|
||||||
/// if x.is_positive() {
|
/// if x.is_positive() {
|
||||||
/// a();
|
/// a();
|
||||||
/// } else if x.is_negative() {
|
/// } else if x.is_negative() {
|
||||||
|
|
|
@ -16,21 +16,32 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Known problems:** Some false negatives, eg.:
|
/// **Known problems:** Some false negatives, eg.:
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let k = &key;
|
/// # use std::collections::HashMap;
|
||||||
/// if !m.contains_key(k) {
|
/// # let mut map = HashMap::new();
|
||||||
/// m.insert(k.clone(), v);
|
/// # let v = 1;
|
||||||
|
/// # let k = 1;
|
||||||
|
/// if !map.contains_key(&k) {
|
||||||
|
/// map.insert(k.clone(), v);
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// if !m.contains_key(&k) {
|
/// # use std::collections::HashMap;
|
||||||
/// m.insert(k, v)
|
/// # let mut map = HashMap::new();
|
||||||
|
/// # let k = 1;
|
||||||
|
/// # let v = 1;
|
||||||
|
/// if !map.contains_key(&k) {
|
||||||
|
/// map.insert(k, v);
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
/// can be rewritten as:
|
/// can both be rewritten as:
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// m.entry(k).or_insert(v);
|
/// # use std::collections::HashMap;
|
||||||
|
/// # let mut map = HashMap::new();
|
||||||
|
/// # let k = 1;
|
||||||
|
/// # let v = 1;
|
||||||
|
/// map.entry(k).or_insert(v);
|
||||||
/// ```
|
/// ```
|
||||||
pub MAP_ENTRY,
|
pub MAP_ENTRY,
|
||||||
perf,
|
perf,
|
||||||
|
|
|
@ -160,6 +160,7 @@ fn check_variant(
|
||||||
let name = var2str(var);
|
let name = var2str(var);
|
||||||
if partial_match(item_name, &name) == item_name_chars
|
if partial_match(item_name, &name) == item_name_chars
|
||||||
&& name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase())
|
&& name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase())
|
||||||
|
&& name.chars().nth(item_name_chars + 1).map_or(false, |c| !c.is_numeric())
|
||||||
{
|
{
|
||||||
span_lint(cx, lint, var.span, "Variant name starts with the enum's name");
|
span_lint(cx, lint, var.span, "Variant name starts with the enum's name");
|
||||||
}
|
}
|
||||||
|
@ -178,6 +179,9 @@ fn check_variant(
|
||||||
let pre_camel = camel_case::until(pre);
|
let pre_camel = camel_case::until(pre);
|
||||||
pre = &pre[..pre_camel];
|
pre = &pre[..pre_camel];
|
||||||
while let Some((next, last)) = name[pre.len()..].chars().zip(pre.chars().rev()).next() {
|
while let Some((next, last)) = name[pre.len()..].chars().zip(pre.chars().rev()).next() {
|
||||||
|
if next.is_numeric() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if next.is_lowercase() {
|
if next.is_lowercase() {
|
||||||
let last = pre.len() - last.len_utf8();
|
let last = pre.len() - last.len_utf8();
|
||||||
let last_camel = camel_case::until(&pre[..last]);
|
let last_camel = camel_case::until(&pre[..last]);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use rustc::hir::intravisit as visit;
|
use rustc::hir::intravisit as visit;
|
||||||
use rustc::hir::*;
|
use rustc::hir::{self, *};
|
||||||
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||||
use rustc::middle::expr_use_visitor::*;
|
use rustc::middle::expr_use_visitor::*;
|
||||||
use rustc::middle::mem_categorization::{cmt_, Categorization};
|
use rustc::middle::mem_categorization::{cmt_, Categorization};
|
||||||
|
@ -28,11 +28,10 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// fn main() {
|
/// # fn foo(bar: usize) {}
|
||||||
/// let x = Box::new(1);
|
/// let x = Box::new(1);
|
||||||
/// foo(*x);
|
/// foo(*x);
|
||||||
/// println!("{}", *x);
|
/// println!("{}", *x);
|
||||||
/// }
|
|
||||||
/// ```
|
/// ```
|
||||||
pub BOXED_LOCAL,
|
pub BOXED_LOCAL,
|
||||||
perf,
|
perf,
|
||||||
|
@ -101,6 +100,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxedLocal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Replace with Map::is_argument(..) when it's fixed
|
||||||
|
fn is_argument(map: &hir::map::Map<'_>, id: HirId) -> bool {
|
||||||
|
match map.find(id) {
|
||||||
|
Some(Node::Binding(_)) => (),
|
||||||
|
_ => return false,
|
||||||
|
}
|
||||||
|
|
||||||
|
match map.find(map.get_parent_node(id)) {
|
||||||
|
Some(Node::Arg(_)) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
|
impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
|
||||||
fn consume(&mut self, _: HirId, _: Span, cmt: &cmt_<'tcx>, mode: ConsumeMode) {
|
fn consume(&mut self, _: HirId, _: Span, cmt: &cmt_<'tcx>, mode: ConsumeMode) {
|
||||||
if let Categorization::Local(lid) = cmt.cat {
|
if let Categorization::Local(lid) = cmt.cat {
|
||||||
|
@ -113,11 +125,13 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
|
||||||
fn matched_pat(&mut self, _: &Pat, _: &cmt_<'tcx>, _: MatchMode) {}
|
fn matched_pat(&mut self, _: &Pat, _: &cmt_<'tcx>, _: MatchMode) {}
|
||||||
fn consume_pat(&mut self, consume_pat: &Pat, cmt: &cmt_<'tcx>, _: ConsumeMode) {
|
fn consume_pat(&mut self, consume_pat: &Pat, cmt: &cmt_<'tcx>, _: ConsumeMode) {
|
||||||
let map = &self.cx.tcx.hir();
|
let map = &self.cx.tcx.hir();
|
||||||
if map.is_argument(consume_pat.hir_id) {
|
if is_argument(map, consume_pat.hir_id) {
|
||||||
// Skip closure arguments
|
// Skip closure arguments
|
||||||
if let Some(Node::Expr(..)) = map.find(map.get_parent_node(consume_pat.hir_id)) {
|
let parent_id = map.get_parent_node(consume_pat.hir_id);
|
||||||
|
if let Some(Node::Expr(..)) = map.find(map.get_parent_node(parent_id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) {
|
if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) {
|
||||||
self.set.insert(consume_pat.hir_id);
|
self.set.insert(consume_pat.hir_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,9 @@ declare_clippy_lint! {
|
||||||
/// shorthand.
|
/// shorthand.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,no_run
|
||||||
|
/// # fn b() -> bool { true }
|
||||||
|
/// # fn c() -> bool { true }
|
||||||
/// let a = b() || panic!() || c();
|
/// let a = b() || panic!() || c();
|
||||||
/// // `c()` is dead, `panic!()` is only called if `b()` returns `false`
|
/// // `c()` is dead, `panic!()` is only called if `b()` returns `false`
|
||||||
/// let x = (a, b, c, panic!());
|
/// let x = (a, b, c, panic!());
|
||||||
|
|
|
@ -143,20 +143,20 @@ impl FloatFormat {
|
||||||
fn new(s: &str) -> Self {
|
fn new(s: &str) -> Self {
|
||||||
s.chars()
|
s.chars()
|
||||||
.find_map(|x| match x {
|
.find_map(|x| match x {
|
||||||
'e' => Some(FloatFormat::LowerExp),
|
'e' => Some(Self::LowerExp),
|
||||||
'E' => Some(FloatFormat::UpperExp),
|
'E' => Some(Self::UpperExp),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.unwrap_or(FloatFormat::Normal)
|
.unwrap_or(Self::Normal)
|
||||||
}
|
}
|
||||||
fn format<T>(&self, f: T) -> String
|
fn format<T>(&self, f: T) -> String
|
||||||
where
|
where
|
||||||
T: fmt::UpperExp + fmt::LowerExp + fmt::Display,
|
T: fmt::UpperExp + fmt::LowerExp + fmt::Display,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
FloatFormat::LowerExp => format!("{:e}", f),
|
Self::LowerExp => format!("{:e}", f),
|
||||||
FloatFormat::UpperExp => format!("{:E}", f),
|
Self::UpperExp => format!("{:E}", f),
|
||||||
FloatFormat::Normal => format!("{}", f),
|
Self::Normal => format!("{}", f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,10 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # use std::io::Write;
|
||||||
|
/// # let bar = "furchtbar";
|
||||||
/// // this would be clearer as `eprintln!("foo: {:?}", bar);`
|
/// // this would be clearer as `eprintln!("foo: {:?}", bar);`
|
||||||
/// writeln!(&mut io::stderr(), "foo: {:?}", bar).unwrap();
|
/// writeln!(&mut std::io::stderr(), "foo: {:?}", bar).unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
pub EXPLICIT_WRITE,
|
pub EXPLICIT_WRITE,
|
||||||
complexity,
|
complexity,
|
||||||
|
|
|
@ -26,8 +26,9 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Examples:**
|
/// **Examples:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// format!("foo")
|
/// # let foo = "foo";
|
||||||
/// format!("{}", foo)
|
/// format!("foo");
|
||||||
|
/// format!("{}", foo);
|
||||||
/// ```
|
/// ```
|
||||||
pub USELESS_FORMAT,
|
pub USELESS_FORMAT,
|
||||||
complexity,
|
complexity,
|
||||||
|
|
|
@ -23,8 +23,9 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # struct Color;
|
||||||
/// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) {
|
/// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) {
|
||||||
/// ..
|
/// // ..
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub TOO_MANY_ARGUMENTS,
|
pub TOO_MANY_ARGUMENTS,
|
||||||
|
|
|
@ -17,7 +17,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// x / 1 + 0 * 1 - 0 | 0
|
/// # let x = 1;
|
||||||
|
/// x / 1 + 0 * 1 - 0 | 0;
|
||||||
/// ```
|
/// ```
|
||||||
pub IDENTITY_OP,
|
pub IDENTITY_OP,
|
||||||
complexity,
|
complexity,
|
||||||
|
|
|
@ -17,6 +17,9 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # let v: Vec<usize> = vec![];
|
||||||
|
/// # fn a() {}
|
||||||
|
/// # fn b() {}
|
||||||
/// if !v.is_empty() {
|
/// if !v.is_empty() {
|
||||||
/// a()
|
/// a()
|
||||||
/// } else {
|
/// } else {
|
||||||
|
@ -27,6 +30,9 @@ declare_clippy_lint! {
|
||||||
/// Could be written:
|
/// Could be written:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # let v: Vec<usize> = vec![];
|
||||||
|
/// # fn a() {}
|
||||||
|
/// # fn b() {}
|
||||||
/// if v.is_empty() {
|
/// if v.is_empty() {
|
||||||
/// b()
|
/// b()
|
||||||
/// } else {
|
/// } else {
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
use crate::utils::{in_macro_or_desugar, is_expn_of, snippet_opt, span_lint_and_then};
|
use crate::utils::{
|
||||||
use rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl, HirId, MatchSource};
|
in_macro_or_desugar, match_def_path,
|
||||||
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
paths::{BEGIN_PANIC, BEGIN_PANIC_FMT},
|
||||||
use rustc::{declare_lint_pass, declare_tool_lint};
|
resolve_node, snippet_opt, span_lint_and_then,
|
||||||
|
};
|
||||||
|
use if_chain::if_chain;
|
||||||
|
use rustc::{
|
||||||
|
declare_lint_pass, declare_tool_lint,
|
||||||
|
hir::{intravisit::FnKind, Body, Expr, ExprKind, FnDecl, HirId, MatchSource, StmtKind},
|
||||||
|
lint::{LateContext, LateLintPass, LintArray, LintPass},
|
||||||
|
};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use syntax::source_map::Span;
|
use syntax::source_map::Span;
|
||||||
|
|
||||||
|
@ -35,8 +42,13 @@ declare_clippy_lint! {
|
||||||
|
|
||||||
declare_lint_pass!(ImplicitReturn => [IMPLICIT_RETURN]);
|
declare_lint_pass!(ImplicitReturn => [IMPLICIT_RETURN]);
|
||||||
|
|
||||||
impl ImplicitReturn {
|
static LINT_BREAK: &str = "change `break` to `return` as shown";
|
||||||
fn lint(cx: &LateContext<'_, '_>, outer_span: syntax_pos::Span, inner_span: syntax_pos::Span, msg: &str) {
|
static LINT_RETURN: &str = "add `return` as shown";
|
||||||
|
|
||||||
|
fn lint(cx: &LateContext<'_, '_>, outer_span: Span, inner_span: Span, msg: &str) {
|
||||||
|
let outer_span = outer_span.source_callsite();
|
||||||
|
let inner_span = inner_span.source_callsite();
|
||||||
|
|
||||||
span_lint_and_then(cx, IMPLICIT_RETURN, outer_span, "missing return statement", |db| {
|
span_lint_and_then(cx, IMPLICIT_RETURN, outer_span, "missing return statement", |db| {
|
||||||
if let Some(snippet) = snippet_opt(cx, inner_span) {
|
if let Some(snippet) = snippet_opt(cx, inner_span) {
|
||||||
db.span_suggestion(
|
db.span_suggestion(
|
||||||
|
@ -47,23 +59,24 @@ impl ImplicitReturn {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr_match(cx: &LateContext<'_, '_>, expr: &rustc::hir::Expr) {
|
fn expr_match(cx: &LateContext<'_, '_>, expr: &Expr) {
|
||||||
match &expr.node {
|
match &expr.node {
|
||||||
// loops could be using `break` instead of `return`
|
// loops could be using `break` instead of `return`
|
||||||
ExprKind::Block(block, ..) | ExprKind::Loop(block, ..) => {
|
ExprKind::Block(block, ..) | ExprKind::Loop(block, ..) => {
|
||||||
if let Some(expr) = &block.expr {
|
if let Some(expr) = &block.expr {
|
||||||
Self::expr_match(cx, expr);
|
expr_match(cx, expr);
|
||||||
}
|
}
|
||||||
// only needed in the case of `break` with `;` at the end
|
// only needed in the case of `break` with `;` at the end
|
||||||
else if let Some(stmt) = block.stmts.last() {
|
else if let Some(stmt) = block.stmts.last() {
|
||||||
if let rustc::hir::StmtKind::Semi(expr, ..) = &stmt.node {
|
if_chain! {
|
||||||
|
if let StmtKind::Semi(expr, ..) = &stmt.node;
|
||||||
// make sure it's a break, otherwise we want to skip
|
// make sure it's a break, otherwise we want to skip
|
||||||
if let ExprKind::Break(.., break_expr) = &expr.node {
|
if let ExprKind::Break(.., break_expr) = &expr.node;
|
||||||
if let Some(break_expr) = break_expr {
|
if let Some(break_expr) = break_expr;
|
||||||
Self::lint(cx, expr.span, break_expr.span, "change `break` to `return` as shown");
|
then {
|
||||||
}
|
lint(cx, expr.span, break_expr.span, LINT_BREAK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +84,7 @@ impl ImplicitReturn {
|
||||||
// use `return` instead of `break`
|
// use `return` instead of `break`
|
||||||
ExprKind::Break(.., break_expr) => {
|
ExprKind::Break(.., break_expr) => {
|
||||||
if let Some(break_expr) = break_expr {
|
if let Some(break_expr) = break_expr {
|
||||||
Self::lint(cx, expr.span, break_expr.span, "change `break` to `return` as shown");
|
lint(cx, expr.span, break_expr.span, LINT_BREAK);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ExprKind::Match(.., arms, source) => {
|
ExprKind::Match(.., arms, source) => {
|
||||||
|
@ -84,22 +97,29 @@ impl ImplicitReturn {
|
||||||
|
|
||||||
if check_all_arms {
|
if check_all_arms {
|
||||||
for arm in arms {
|
for arm in arms {
|
||||||
Self::expr_match(cx, &arm.body);
|
expr_match(cx, &arm.body);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Self::expr_match(cx, &arms.first().expect("if let doesn't have a single arm").body);
|
expr_match(cx, &arms.first().expect("if let doesn't have a single arm").body);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// skip if it already has a return statement
|
// skip if it already has a return statement
|
||||||
ExprKind::Ret(..) => (),
|
ExprKind::Ret(..) => (),
|
||||||
// everything else is missing `return`
|
// make sure it's not a call that panics
|
||||||
_ => {
|
ExprKind::Call(expr, ..) => {
|
||||||
// make sure it's not just an unreachable expression
|
if_chain! {
|
||||||
if is_expn_of(expr.span, "unreachable").is_none() {
|
if let ExprKind::Path(qpath) = &expr.node;
|
||||||
Self::lint(cx, expr.span, expr.span, "add `return` as shown")
|
if let Some(path_def_id) = resolve_node(cx, qpath, expr.hir_id).opt_def_id();
|
||||||
|
if match_def_path(cx, path_def_id, &BEGIN_PANIC) ||
|
||||||
|
match_def_path(cx, path_def_id, &BEGIN_PANIC_FMT);
|
||||||
|
then { }
|
||||||
|
else {
|
||||||
|
lint(cx, expr.span, expr.span, LINT_RETURN)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
// everything else is missing `return`
|
||||||
|
_ => lint(cx, expr.span, expr.span, LINT_RETURN),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +139,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitReturn {
|
||||||
// checking return type through MIR, HIR is not able to determine inferred closure return types
|
// checking return type through MIR, HIR is not able to determine inferred closure return types
|
||||||
// make sure it's not a macro
|
// make sure it's not a macro
|
||||||
if !mir.return_ty().is_unit() && !in_macro_or_desugar(span) {
|
if !mir.return_ty().is_unit() && !in_macro_or_desugar(span) {
|
||||||
Self::expr_match(cx, &body.value);
|
expr_match(cx, &body.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ declare_clippy_lint! {
|
||||||
/// **Known problems:** Hopefully none.
|
/// **Known problems:** Hopefully none.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,no_run
|
||||||
/// // Vector
|
/// // Vector
|
||||||
/// let x = vec![0; 5];
|
/// let x = vec![0; 5];
|
||||||
///
|
///
|
||||||
|
@ -94,7 +94,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing {
|
||||||
if let Some(range) = higher::range(cx, index) {
|
if let Some(range) = higher::range(cx, index) {
|
||||||
// Ranged indexes, i.e., &x[n..m], &x[n..], &x[..n] and &x[..]
|
// Ranged indexes, i.e., &x[n..m], &x[n..], &x[..n] and &x[..]
|
||||||
if let ty::Array(_, s) = ty.sty {
|
if let ty::Array(_, s) = ty.sty {
|
||||||
let size: u128 = s.assert_usize(cx.tcx).unwrap().into();
|
let size: u128 = s.eval_usize(cx.tcx, cx.param_env).into();
|
||||||
|
|
||||||
let const_range = to_const_range(cx, range, size);
|
let const_range = to_const_range(cx, range, size);
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// [0..].iter().zip(infinite_iter.take_while(|x| x > 5))
|
/// let infinite_iter = 0..;
|
||||||
|
/// [0..].iter().zip(infinite_iter.take_while(|x| *x > 5));
|
||||||
/// ```
|
/// ```
|
||||||
pub MAYBE_INFINITE_ITER,
|
pub MAYBE_INFINITE_ITER,
|
||||||
pedantic,
|
pedantic,
|
||||||
|
|
154
clippy_lints/src/inherent_to_string.rs
Normal file
154
clippy_lints/src/inherent_to_string.rs
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
use if_chain::if_chain;
|
||||||
|
use rustc::hir::{ImplItem, ImplItemKind};
|
||||||
|
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||||
|
use rustc::{declare_lint_pass, declare_tool_lint};
|
||||||
|
|
||||||
|
use crate::utils::{
|
||||||
|
get_trait_def_id, implements_trait, in_macro_or_desugar, match_type, paths, return_ty, span_help_and_lint,
|
||||||
|
trait_ref_of_method, walk_ptrs_ty,
|
||||||
|
};
|
||||||
|
|
||||||
|
declare_clippy_lint! {
|
||||||
|
/// **What id does:** Checks for the definition of inherent methods with a signature of `to_string(&self) -> String`.
|
||||||
|
///
|
||||||
|
/// **Why is this bad?** This method is also implicitly defined if a type implements the `Display` trait. As the functionality of `Display` is much more versatile, it should be preferred.
|
||||||
|
///
|
||||||
|
/// **Known problems:** None
|
||||||
|
///
|
||||||
|
/// ** Example:**
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// // Bad
|
||||||
|
/// pub struct A;
|
||||||
|
///
|
||||||
|
/// impl A {
|
||||||
|
/// pub fn to_string(&self) -> String {
|
||||||
|
/// "I am A".to_string()
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// // Good
|
||||||
|
/// use std::fmt;
|
||||||
|
///
|
||||||
|
/// pub struct A;
|
||||||
|
///
|
||||||
|
/// impl fmt::Display for A {
|
||||||
|
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
/// write!(f, "I am A")
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub INHERENT_TO_STRING,
|
||||||
|
style,
|
||||||
|
"type implements inherent method `to_string()`, but should instead implement the `Display` trait"
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_clippy_lint! {
|
||||||
|
/// **What id does:** Checks for the definition of inherent methods with a signature of `to_string(&self) -> String` and if the type implementing this method also implements the `Display` trait.
|
||||||
|
///
|
||||||
|
/// **Why is this bad?** This method is also implicitly defined if a type implements the `Display` trait. The less versatile inherent method will then shadow the implementation introduced by `Display`.
|
||||||
|
///
|
||||||
|
/// **Known problems:** None
|
||||||
|
///
|
||||||
|
/// ** Example:**
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// // Bad
|
||||||
|
/// use std::fmt;
|
||||||
|
///
|
||||||
|
/// pub struct A;
|
||||||
|
///
|
||||||
|
/// impl A {
|
||||||
|
/// pub fn to_string(&self) -> String {
|
||||||
|
/// "I am A".to_string()
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// impl fmt::Display for A {
|
||||||
|
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
/// write!(f, "I am A, too")
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// // Good
|
||||||
|
/// use std::fmt;
|
||||||
|
///
|
||||||
|
/// pub struct A;
|
||||||
|
///
|
||||||
|
/// impl fmt::Display for A {
|
||||||
|
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
/// write!(f, "I am A")
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub INHERENT_TO_STRING_SHADOW_DISPLAY,
|
||||||
|
correctness,
|
||||||
|
"type implements inherent method `to_string()`, which gets shadowed by the implementation of the `Display` trait "
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_lint_pass!(InherentToString => [INHERENT_TO_STRING, INHERENT_TO_STRING_SHADOW_DISPLAY]);
|
||||||
|
|
||||||
|
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InherentToString {
|
||||||
|
fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx ImplItem) {
|
||||||
|
if in_macro_or_desugar(impl_item.span) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if_chain! {
|
||||||
|
// Check if item is a method, called to_string and has a parameter 'self'
|
||||||
|
if let ImplItemKind::Method(ref signature, _) = impl_item.node;
|
||||||
|
if impl_item.ident.name.as_str() == "to_string";
|
||||||
|
let decl = &signature.decl;
|
||||||
|
if decl.implicit_self.has_implicit_self();
|
||||||
|
|
||||||
|
// Check if return type is String
|
||||||
|
if match_type(cx, return_ty(cx, impl_item.hir_id), &paths::STRING);
|
||||||
|
|
||||||
|
// Filters instances of to_string which are required by a trait
|
||||||
|
if trait_ref_of_method(cx, impl_item.hir_id).is_none();
|
||||||
|
|
||||||
|
then {
|
||||||
|
show_lint(cx, impl_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_lint(cx: &LateContext<'_, '_>, item: &ImplItem) {
|
||||||
|
let display_trait_id =
|
||||||
|
get_trait_def_id(cx, &["core", "fmt", "Display"]).expect("Failed to get trait ID of `Display`!");
|
||||||
|
|
||||||
|
// Get the real type of 'self'
|
||||||
|
let fn_def_id = cx.tcx.hir().local_def_id(item.hir_id);
|
||||||
|
let self_type = cx.tcx.fn_sig(fn_def_id).input(0);
|
||||||
|
let self_type = walk_ptrs_ty(self_type.skip_binder());
|
||||||
|
|
||||||
|
// Emit either a warning or an error
|
||||||
|
if implements_trait(cx, self_type, display_trait_id, &[]) {
|
||||||
|
span_help_and_lint(
|
||||||
|
cx,
|
||||||
|
INHERENT_TO_STRING_SHADOW_DISPLAY,
|
||||||
|
item.span,
|
||||||
|
&format!(
|
||||||
|
"type `{}` implements inherent method `to_string(&self) -> String` which shadows the implementation of `Display`",
|
||||||
|
self_type.to_string()
|
||||||
|
),
|
||||||
|
&format!("remove the inherent method from type `{}`", self_type.to_string())
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
span_help_and_lint(
|
||||||
|
cx,
|
||||||
|
INHERENT_TO_STRING,
|
||||||
|
item.span,
|
||||||
|
&format!(
|
||||||
|
"implementation of inherent method `to_string(&self) -> String` for type `{}`",
|
||||||
|
self_type.to_string()
|
||||||
|
),
|
||||||
|
&format!("implement trait `Display` for type `{}` instead", self_type.to_string()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,13 +17,17 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// x >= y + 1
|
/// # let x = 1;
|
||||||
|
/// # let y = 1;
|
||||||
|
/// if x >= y + 1 {}
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Could be written:
|
/// Could be written as:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// x > y
|
/// # let x = 1;
|
||||||
|
/// # let y = 1;
|
||||||
|
/// if x > y {}
|
||||||
/// ```
|
/// ```
|
||||||
pub INT_PLUS_ONE,
|
pub INT_PLUS_ONE,
|
||||||
complexity,
|
complexity,
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
use crate::utils::{match_def_path, paths, span_help_and_lint};
|
|
||||||
use if_chain::if_chain;
|
|
||||||
use rustc::hir::*;
|
|
||||||
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
|
||||||
use rustc::ty;
|
|
||||||
use rustc::{declare_lint_pass, declare_tool_lint};
|
|
||||||
|
|
||||||
declare_clippy_lint! {
|
|
||||||
/// **What it does:** Checks for creation of references to zeroed or uninitialized memory.
|
|
||||||
///
|
|
||||||
/// **Why is this bad?** Creation of null references is undefined behavior.
|
|
||||||
///
|
|
||||||
/// **Known problems:** None.
|
|
||||||
///
|
|
||||||
/// **Example:**
|
|
||||||
/// ```no_run
|
|
||||||
/// let bad_ref: &usize = unsafe { std::mem::zeroed() };
|
|
||||||
/// ```
|
|
||||||
pub INVALID_REF,
|
|
||||||
correctness,
|
|
||||||
"creation of invalid reference"
|
|
||||||
}
|
|
||||||
|
|
||||||
const ZERO_REF_SUMMARY: &str = "reference to zeroed memory";
|
|
||||||
const UNINIT_REF_SUMMARY: &str = "reference to uninitialized memory";
|
|
||||||
const HELP: &str = "Creation of a null reference is undefined behavior; \
|
|
||||||
see https://doc.rust-lang.org/reference/behavior-considered-undefined.html";
|
|
||||||
|
|
||||||
declare_lint_pass!(InvalidRef => [INVALID_REF]);
|
|
||||||
|
|
||||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidRef {
|
|
||||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
|
||||||
if_chain! {
|
|
||||||
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::Ref(..) = cx.tables.expr_ty(expr).sty;
|
|
||||||
if let Some(def_id) = cx.tables.qpath_res(qpath, path.hir_id).opt_def_id();
|
|
||||||
then {
|
|
||||||
let msg = if match_def_path(cx, def_id, &paths::MEM_ZEROED) |
|
|
||||||
match_def_path(cx, def_id, &paths::INIT)
|
|
||||||
{
|
|
||||||
ZERO_REF_SUMMARY
|
|
||||||
} else if match_def_path(cx, def_id, &paths::MEM_UNINIT) |
|
|
||||||
match_def_path(cx, def_id, &paths::UNINIT)
|
|
||||||
{
|
|
||||||
UNINIT_REF_SUMMARY
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
span_help_and_lint(cx, INVALID_REF, expr.span, msg, HELP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -244,7 +244,7 @@ fn check_len(
|
||||||
LEN_ZERO,
|
LEN_ZERO,
|
||||||
span,
|
span,
|
||||||
&format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }),
|
&format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }),
|
||||||
"using `is_empty` is clearer and more explicit",
|
&format!("using `{}is_empty` is clearer and more explicit", op),
|
||||||
format!(
|
format!(
|
||||||
"{}{}.is_empty()",
|
"{}{}.is_empty()",
|
||||||
op,
|
op,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// error-pattern:cargo-clippy
|
// error-pattern:cargo-clippy
|
||||||
|
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
|
#![feature(box_patterns)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(slice_patterns)]
|
#![feature(slice_patterns)]
|
||||||
|
@ -9,6 +10,7 @@
|
||||||
#![recursion_limit = "512"]
|
#![recursion_limit = "512"]
|
||||||
#![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)]
|
#![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)]
|
||||||
#![deny(rustc::internal)]
|
#![deny(rustc::internal)]
|
||||||
|
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(concat_idents)]
|
#![feature(concat_idents)]
|
||||||
|
|
||||||
|
@ -98,42 +100,42 @@ macro_rules! declare_clippy_lint {
|
||||||
};
|
};
|
||||||
{ $(#[$attr:meta])* pub $name:tt, complexity, $description:tt } => {
|
{ $(#[$attr:meta])* pub $name:tt, complexity, $description:tt } => {
|
||||||
declare_tool_lint! {
|
declare_tool_lint! {
|
||||||
pub clippy::$name, Warn, $description, report_in_external_macro: true
|
$(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
{ $(#[$attr:meta])* pub $name:tt, perf, $description:tt } => {
|
{ $(#[$attr:meta])* pub $name:tt, perf, $description:tt } => {
|
||||||
declare_tool_lint! {
|
declare_tool_lint! {
|
||||||
pub clippy::$name, Warn, $description, report_in_external_macro: true
|
$(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
{ $(#[$attr:meta])* pub $name:tt, pedantic, $description:tt } => {
|
{ $(#[$attr:meta])* pub $name:tt, pedantic, $description:tt } => {
|
||||||
declare_tool_lint! {
|
declare_tool_lint! {
|
||||||
pub clippy::$name, Allow, $description, report_in_external_macro: true
|
$(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
{ $(#[$attr:meta])* pub $name:tt, restriction, $description:tt } => {
|
{ $(#[$attr:meta])* pub $name:tt, restriction, $description:tt } => {
|
||||||
declare_tool_lint! {
|
declare_tool_lint! {
|
||||||
pub clippy::$name, Allow, $description, report_in_external_macro: true
|
$(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
{ $(#[$attr:meta])* pub $name:tt, cargo, $description:tt } => {
|
{ $(#[$attr:meta])* pub $name:tt, cargo, $description:tt } => {
|
||||||
declare_tool_lint! {
|
declare_tool_lint! {
|
||||||
pub clippy::$name, Allow, $description, report_in_external_macro: true
|
$(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
{ $(#[$attr:meta])* pub $name:tt, nursery, $description:tt } => {
|
{ $(#[$attr:meta])* pub $name:tt, nursery, $description:tt } => {
|
||||||
declare_tool_lint! {
|
declare_tool_lint! {
|
||||||
pub clippy::$name, Allow, $description, report_in_external_macro: true
|
$(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
{ $(#[$attr:meta])* pub $name:tt, internal, $description:tt } => {
|
{ $(#[$attr:meta])* pub $name:tt, internal, $description:tt } => {
|
||||||
declare_tool_lint! {
|
declare_tool_lint! {
|
||||||
pub clippy::$name, Allow, $description, report_in_external_macro: true
|
$(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
{ $(#[$attr:meta])* pub $name:tt, internal_warn, $description:tt } => {
|
{ $(#[$attr:meta])* pub $name:tt, internal_warn, $description:tt } => {
|
||||||
declare_tool_lint! {
|
declare_tool_lint! {
|
||||||
pub clippy::$name, Warn, $description, report_in_external_macro: true
|
$(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -194,10 +196,10 @@ pub mod indexing_slicing;
|
||||||
pub mod infallible_destructuring_match;
|
pub mod infallible_destructuring_match;
|
||||||
pub mod infinite_iter;
|
pub mod infinite_iter;
|
||||||
pub mod inherent_impl;
|
pub mod inherent_impl;
|
||||||
|
pub mod inherent_to_string;
|
||||||
pub mod inline_fn_without_body;
|
pub mod inline_fn_without_body;
|
||||||
pub mod int_plus_one;
|
pub mod int_plus_one;
|
||||||
pub mod integer_division;
|
pub mod integer_division;
|
||||||
pub mod invalid_ref;
|
|
||||||
pub mod items_after_statements;
|
pub mod items_after_statements;
|
||||||
pub mod large_enum_variant;
|
pub mod large_enum_variant;
|
||||||
pub mod len_zero;
|
pub mod len_zero;
|
||||||
|
@ -205,6 +207,7 @@ pub mod let_if_seq;
|
||||||
pub mod lifetimes;
|
pub mod lifetimes;
|
||||||
pub mod literal_representation;
|
pub mod literal_representation;
|
||||||
pub mod loops;
|
pub mod loops;
|
||||||
|
pub mod main_recursion;
|
||||||
pub mod map_clone;
|
pub mod map_clone;
|
||||||
pub mod map_unit_fn;
|
pub mod map_unit_fn;
|
||||||
pub mod matches;
|
pub mod matches;
|
||||||
|
@ -260,6 +263,7 @@ pub mod strings;
|
||||||
pub mod suspicious_trait_impl;
|
pub mod suspicious_trait_impl;
|
||||||
pub mod swap;
|
pub mod swap;
|
||||||
pub mod temporary_assignment;
|
pub mod temporary_assignment;
|
||||||
|
pub mod trait_bounds;
|
||||||
pub mod transmute;
|
pub mod transmute;
|
||||||
pub mod transmuting_null;
|
pub mod transmuting_null;
|
||||||
pub mod trivially_copy_pass_by_ref;
|
pub mod trivially_copy_pass_by_ref;
|
||||||
|
@ -469,6 +473,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||||
reg.register_late_lint_pass(box types::LetUnitValue);
|
reg.register_late_lint_pass(box types::LetUnitValue);
|
||||||
reg.register_late_lint_pass(box types::UnitCmp);
|
reg.register_late_lint_pass(box types::UnitCmp);
|
||||||
reg.register_late_lint_pass(box loops::Loops);
|
reg.register_late_lint_pass(box loops::Loops);
|
||||||
|
reg.register_late_lint_pass(box main_recursion::MainRecursion::default());
|
||||||
reg.register_late_lint_pass(box lifetimes::Lifetimes);
|
reg.register_late_lint_pass(box lifetimes::Lifetimes);
|
||||||
reg.register_late_lint_pass(box entry::HashMapPass);
|
reg.register_late_lint_pass(box entry::HashMapPass);
|
||||||
reg.register_late_lint_pass(box ranges::Ranges);
|
reg.register_late_lint_pass(box ranges::Ranges);
|
||||||
|
@ -552,7 +557,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||||
reg.register_late_lint_pass(box bytecount::ByteCount);
|
reg.register_late_lint_pass(box bytecount::ByteCount);
|
||||||
reg.register_late_lint_pass(box infinite_iter::InfiniteIter);
|
reg.register_late_lint_pass(box infinite_iter::InfiniteIter);
|
||||||
reg.register_late_lint_pass(box inline_fn_without_body::InlineFnWithoutBody);
|
reg.register_late_lint_pass(box inline_fn_without_body::InlineFnWithoutBody);
|
||||||
reg.register_late_lint_pass(box invalid_ref::InvalidRef);
|
|
||||||
reg.register_late_lint_pass(box identity_conversion::IdentityConversion::default());
|
reg.register_late_lint_pass(box identity_conversion::IdentityConversion::default());
|
||||||
reg.register_late_lint_pass(box types::ImplicitHasher);
|
reg.register_late_lint_pass(box types::ImplicitHasher);
|
||||||
reg.register_early_lint_pass(box redundant_static_lifetimes::RedundantStaticLifetimes);
|
reg.register_early_lint_pass(box redundant_static_lifetimes::RedundantStaticLifetimes);
|
||||||
|
@ -584,6 +588,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||||
reg.register_late_lint_pass(box path_buf_push_overwrite::PathBufPushOverwrite);
|
reg.register_late_lint_pass(box path_buf_push_overwrite::PathBufPushOverwrite);
|
||||||
reg.register_late_lint_pass(box checked_conversions::CheckedConversions);
|
reg.register_late_lint_pass(box checked_conversions::CheckedConversions);
|
||||||
reg.register_late_lint_pass(box integer_division::IntegerDivision);
|
reg.register_late_lint_pass(box integer_division::IntegerDivision);
|
||||||
|
reg.register_late_lint_pass(box inherent_to_string::InherentToString);
|
||||||
|
reg.register_late_lint_pass(box trait_bounds::TraitBounds);
|
||||||
|
|
||||||
reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![
|
reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![
|
||||||
arithmetic::FLOAT_ARITHMETIC,
|
arithmetic::FLOAT_ARITHMETIC,
|
||||||
|
@ -666,7 +672,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||||
utils::internal_lints::CLIPPY_LINTS_INTERNAL,
|
utils::internal_lints::CLIPPY_LINTS_INTERNAL,
|
||||||
utils::internal_lints::COMPILER_LINT_FUNCTIONS,
|
utils::internal_lints::COMPILER_LINT_FUNCTIONS,
|
||||||
utils::internal_lints::LINT_WITHOUT_LINT_PASS,
|
utils::internal_lints::LINT_WITHOUT_LINT_PASS,
|
||||||
utils::internal_lints::OUTER_EXPN_INFO,
|
utils::internal_lints::OUTER_EXPN_EXPN_INFO,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
reg.register_lint_group("clippy::all", Some("clippy"), vec![
|
reg.register_lint_group("clippy::all", Some("clippy"), vec![
|
||||||
|
@ -725,9 +731,10 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||||
indexing_slicing::OUT_OF_BOUNDS_INDEXING,
|
indexing_slicing::OUT_OF_BOUNDS_INDEXING,
|
||||||
infallible_destructuring_match::INFALLIBLE_DESTRUCTURING_MATCH,
|
infallible_destructuring_match::INFALLIBLE_DESTRUCTURING_MATCH,
|
||||||
infinite_iter::INFINITE_ITER,
|
infinite_iter::INFINITE_ITER,
|
||||||
|
inherent_to_string::INHERENT_TO_STRING,
|
||||||
|
inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY,
|
||||||
inline_fn_without_body::INLINE_FN_WITHOUT_BODY,
|
inline_fn_without_body::INLINE_FN_WITHOUT_BODY,
|
||||||
int_plus_one::INT_PLUS_ONE,
|
int_plus_one::INT_PLUS_ONE,
|
||||||
invalid_ref::INVALID_REF,
|
|
||||||
large_enum_variant::LARGE_ENUM_VARIANT,
|
large_enum_variant::LARGE_ENUM_VARIANT,
|
||||||
len_zero::LEN_WITHOUT_IS_EMPTY,
|
len_zero::LEN_WITHOUT_IS_EMPTY,
|
||||||
len_zero::LEN_ZERO,
|
len_zero::LEN_ZERO,
|
||||||
|
@ -753,6 +760,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||||
loops::WHILE_IMMUTABLE_CONDITION,
|
loops::WHILE_IMMUTABLE_CONDITION,
|
||||||
loops::WHILE_LET_LOOP,
|
loops::WHILE_LET_LOOP,
|
||||||
loops::WHILE_LET_ON_ITERATOR,
|
loops::WHILE_LET_ON_ITERATOR,
|
||||||
|
main_recursion::MAIN_RECURSION,
|
||||||
map_clone::MAP_CLONE,
|
map_clone::MAP_CLONE,
|
||||||
map_unit_fn::OPTION_MAP_UNIT_FN,
|
map_unit_fn::OPTION_MAP_UNIT_FN,
|
||||||
map_unit_fn::RESULT_MAP_UNIT_FN,
|
map_unit_fn::RESULT_MAP_UNIT_FN,
|
||||||
|
@ -853,6 +861,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||||
swap::ALMOST_SWAPPED,
|
swap::ALMOST_SWAPPED,
|
||||||
swap::MANUAL_SWAP,
|
swap::MANUAL_SWAP,
|
||||||
temporary_assignment::TEMPORARY_ASSIGNMENT,
|
temporary_assignment::TEMPORARY_ASSIGNMENT,
|
||||||
|
trait_bounds::TYPE_REPETITION_IN_BOUNDS,
|
||||||
transmute::CROSSPOINTER_TRANSMUTE,
|
transmute::CROSSPOINTER_TRANSMUTE,
|
||||||
transmute::TRANSMUTE_BYTES_TO_STR,
|
transmute::TRANSMUTE_BYTES_TO_STR,
|
||||||
transmute::TRANSMUTE_INT_TO_BOOL,
|
transmute::TRANSMUTE_INT_TO_BOOL,
|
||||||
|
@ -886,6 +895,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||||
unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME,
|
unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME,
|
||||||
unused_io_amount::UNUSED_IO_AMOUNT,
|
unused_io_amount::UNUSED_IO_AMOUNT,
|
||||||
unused_label::UNUSED_LABEL,
|
unused_label::UNUSED_LABEL,
|
||||||
|
unwrap::PANICKING_UNWRAP,
|
||||||
|
unwrap::UNNECESSARY_UNWRAP,
|
||||||
vec::USELESS_VEC,
|
vec::USELESS_VEC,
|
||||||
write::PRINTLN_EMPTY_STRING,
|
write::PRINTLN_EMPTY_STRING,
|
||||||
write::PRINT_LITERAL,
|
write::PRINT_LITERAL,
|
||||||
|
@ -913,6 +924,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||||
formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING,
|
formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING,
|
||||||
formatting::SUSPICIOUS_ELSE_FORMATTING,
|
formatting::SUSPICIOUS_ELSE_FORMATTING,
|
||||||
infallible_destructuring_match::INFALLIBLE_DESTRUCTURING_MATCH,
|
infallible_destructuring_match::INFALLIBLE_DESTRUCTURING_MATCH,
|
||||||
|
inherent_to_string::INHERENT_TO_STRING,
|
||||||
len_zero::LEN_WITHOUT_IS_EMPTY,
|
len_zero::LEN_WITHOUT_IS_EMPTY,
|
||||||
len_zero::LEN_ZERO,
|
len_zero::LEN_ZERO,
|
||||||
let_if_seq::USELESS_LET_IF_SEQ,
|
let_if_seq::USELESS_LET_IF_SEQ,
|
||||||
|
@ -922,6 +934,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||||
loops::FOR_KV_MAP,
|
loops::FOR_KV_MAP,
|
||||||
loops::NEEDLESS_RANGE_LOOP,
|
loops::NEEDLESS_RANGE_LOOP,
|
||||||
loops::WHILE_LET_ON_ITERATOR,
|
loops::WHILE_LET_ON_ITERATOR,
|
||||||
|
main_recursion::MAIN_RECURSION,
|
||||||
map_clone::MAP_CLONE,
|
map_clone::MAP_CLONE,
|
||||||
matches::MATCH_BOOL,
|
matches::MATCH_BOOL,
|
||||||
matches::MATCH_OVERLAPPING_ARM,
|
matches::MATCH_OVERLAPPING_ARM,
|
||||||
|
@ -1033,6 +1046,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||||
reference::REF_IN_DEREF,
|
reference::REF_IN_DEREF,
|
||||||
swap::MANUAL_SWAP,
|
swap::MANUAL_SWAP,
|
||||||
temporary_assignment::TEMPORARY_ASSIGNMENT,
|
temporary_assignment::TEMPORARY_ASSIGNMENT,
|
||||||
|
trait_bounds::TYPE_REPETITION_IN_BOUNDS,
|
||||||
transmute::CROSSPOINTER_TRANSMUTE,
|
transmute::CROSSPOINTER_TRANSMUTE,
|
||||||
transmute::TRANSMUTE_BYTES_TO_STR,
|
transmute::TRANSMUTE_BYTES_TO_STR,
|
||||||
transmute::TRANSMUTE_INT_TO_BOOL,
|
transmute::TRANSMUTE_INT_TO_BOOL,
|
||||||
|
@ -1050,6 +1064,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||||
types::UNNECESSARY_CAST,
|
types::UNNECESSARY_CAST,
|
||||||
types::VEC_BOX,
|
types::VEC_BOX,
|
||||||
unused_label::UNUSED_LABEL,
|
unused_label::UNUSED_LABEL,
|
||||||
|
unwrap::UNNECESSARY_UNWRAP,
|
||||||
zero_div_zero::ZERO_DIVIDED_BY_ZERO,
|
zero_div_zero::ZERO_DIVIDED_BY_ZERO,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -1075,8 +1090,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||||
functions::NOT_UNSAFE_PTR_ARG_DEREF,
|
functions::NOT_UNSAFE_PTR_ARG_DEREF,
|
||||||
indexing_slicing::OUT_OF_BOUNDS_INDEXING,
|
indexing_slicing::OUT_OF_BOUNDS_INDEXING,
|
||||||
infinite_iter::INFINITE_ITER,
|
infinite_iter::INFINITE_ITER,
|
||||||
|
inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY,
|
||||||
inline_fn_without_body::INLINE_FN_WITHOUT_BODY,
|
inline_fn_without_body::INLINE_FN_WITHOUT_BODY,
|
||||||
invalid_ref::INVALID_REF,
|
|
||||||
literal_representation::MISTYPED_LITERAL_SUFFIXES,
|
literal_representation::MISTYPED_LITERAL_SUFFIXES,
|
||||||
loops::FOR_LOOP_OVER_OPTION,
|
loops::FOR_LOOP_OVER_OPTION,
|
||||||
loops::FOR_LOOP_OVER_RESULT,
|
loops::FOR_LOOP_OVER_RESULT,
|
||||||
|
@ -1110,6 +1125,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||||
types::UNIT_CMP,
|
types::UNIT_CMP,
|
||||||
unicode::ZERO_WIDTH_SPACE,
|
unicode::ZERO_WIDTH_SPACE,
|
||||||
unused_io_amount::UNUSED_IO_AMOUNT,
|
unused_io_amount::UNUSED_IO_AMOUNT,
|
||||||
|
unwrap::PANICKING_UNWRAP,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
reg.register_lint_group("clippy::perf", Some("clippy_perf"), vec![
|
reg.register_lint_group("clippy::perf", Some("clippy_perf"), vec![
|
||||||
|
@ -1146,8 +1162,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||||
needless_borrow::NEEDLESS_BORROW,
|
needless_borrow::NEEDLESS_BORROW,
|
||||||
path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE,
|
path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE,
|
||||||
redundant_clone::REDUNDANT_CLONE,
|
redundant_clone::REDUNDANT_CLONE,
|
||||||
unwrap::PANICKING_UNWRAP,
|
|
||||||
unwrap::UNNECESSARY_UNWRAP,
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ declare_clippy_lint! {
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// fn unused_lifetime<'a>(x: u8) {
|
/// fn unused_lifetime<'a>(x: u8) {
|
||||||
/// ..
|
/// // ..
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub EXTRA_UNUSED_LIFETIMES,
|
pub EXTRA_UNUSED_LIFETIMES,
|
||||||
|
@ -283,6 +283,8 @@ impl<'v, 't> RefVisitor<'v, 't> {
|
||||||
if let Some(ref lt) = *lifetime {
|
if let Some(ref lt) = *lifetime {
|
||||||
if lt.name == LifetimeName::Static {
|
if lt.name == LifetimeName::Static {
|
||||||
self.lts.push(RefLt::Static);
|
self.lts.push(RefLt::Static);
|
||||||
|
} else if let LifetimeName::Param(ParamName::Fresh(_)) = lt.name {
|
||||||
|
// Fresh lifetimes generated should be ignored.
|
||||||
} else if lt.is_elided() {
|
} else if lt.is_elided() {
|
||||||
self.lts.push(RefLt::Unnamed);
|
self.lts.push(RefLt::Unnamed);
|
||||||
} else {
|
} else {
|
||||||
|
@ -346,7 +348,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
|
||||||
},
|
},
|
||||||
TyKind::Def(item, _) => {
|
TyKind::Def(item, _) => {
|
||||||
let map = self.cx.tcx.hir();
|
let map = self.cx.tcx.hir();
|
||||||
if let ItemKind::Existential(ref exist_ty) = map.expect_item(item.id).node {
|
if let ItemKind::OpaqueTy(ref exist_ty) = map.expect_item(item.id).node {
|
||||||
for bound in &exist_ty.bounds {
|
for bound in &exist_ty.bounds {
|
||||||
if let GenericBound::Outlives(_) = *bound {
|
if let GenericBound::Outlives(_) = *bound {
|
||||||
self.record(&None);
|
self.record(&None);
|
||||||
|
|
|
@ -115,8 +115,8 @@ impl Radix {
|
||||||
/// Returns a reasonable digit group size for this radix.
|
/// Returns a reasonable digit group size for this radix.
|
||||||
crate fn suggest_grouping(&self) -> usize {
|
crate fn suggest_grouping(&self) -> usize {
|
||||||
match *self {
|
match *self {
|
||||||
Radix::Binary | Radix::Hexadecimal => 4,
|
Self::Binary | Self::Hexadecimal => 4,
|
||||||
Radix::Octal | Radix::Decimal => 3,
|
Self::Octal | Self::Decimal => 3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -285,7 +285,7 @@ enum WarningType {
|
||||||
impl 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 {
|
match self {
|
||||||
WarningType::MistypedLiteralSuffix => span_lint_and_sugg(
|
Self::MistypedLiteralSuffix => span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
MISTYPED_LITERAL_SUFFIXES,
|
MISTYPED_LITERAL_SUFFIXES,
|
||||||
span,
|
span,
|
||||||
|
@ -294,7 +294,7 @@ impl WarningType {
|
||||||
grouping_hint.to_string(),
|
grouping_hint.to_string(),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
),
|
),
|
||||||
WarningType::UnreadableLiteral => span_lint_and_sugg(
|
Self::UnreadableLiteral => span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
UNREADABLE_LITERAL,
|
UNREADABLE_LITERAL,
|
||||||
span,
|
span,
|
||||||
|
@ -303,7 +303,7 @@ impl WarningType {
|
||||||
grouping_hint.to_owned(),
|
grouping_hint.to_owned(),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
),
|
),
|
||||||
WarningType::LargeDigitGroups => span_lint_and_sugg(
|
Self::LargeDigitGroups => span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
LARGE_DIGIT_GROUPS,
|
LARGE_DIGIT_GROUPS,
|
||||||
span,
|
span,
|
||||||
|
@ -312,7 +312,7 @@ impl WarningType {
|
||||||
grouping_hint.to_owned(),
|
grouping_hint.to_owned(),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
),
|
),
|
||||||
WarningType::InconsistentDigitGrouping => span_lint_and_sugg(
|
Self::InconsistentDigitGrouping => span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
INCONSISTENT_DIGIT_GROUPING,
|
INCONSISTENT_DIGIT_GROUPING,
|
||||||
span,
|
span,
|
||||||
|
@ -321,7 +321,7 @@ impl WarningType {
|
||||||
grouping_hint.to_owned(),
|
grouping_hint.to_owned(),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
),
|
),
|
||||||
WarningType::DecimalRepresentation => span_lint_and_sugg(
|
Self::DecimalRepresentation => span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
DECIMAL_LITERAL_REPRESENTATION,
|
DECIMAL_LITERAL_REPRESENTATION,
|
||||||
span,
|
span,
|
||||||
|
|
|
@ -41,7 +41,9 @@ declare_clippy_lint! {
|
||||||
/// **Known problems:** None.
|
/// **Known problems:** None.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```ignore
|
/// ```rust
|
||||||
|
/// # let src = vec![1];
|
||||||
|
/// # let mut dst = vec![0; 65];
|
||||||
/// for i in 0..src.len() {
|
/// for i in 0..src.len() {
|
||||||
/// dst[i + 64] = src[i];
|
/// dst[i + 64] = src[i];
|
||||||
/// }
|
/// }
|
||||||
|
@ -89,16 +91,18 @@ declare_clippy_lint! {
|
||||||
/// types.
|
/// types.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```ignore
|
/// ```rust
|
||||||
/// // with `y` a `Vec` or slice:
|
/// // with `y` a `Vec` or slice:
|
||||||
|
/// # let y = vec![1];
|
||||||
/// for x in y.iter() {
|
/// for x in y.iter() {
|
||||||
/// ..
|
/// // ..
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
/// can be rewritten to
|
/// can be rewritten to
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # let y = vec![1];
|
||||||
/// for x in &y {
|
/// for x in &y {
|
||||||
/// ..
|
/// // ..
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub EXPLICIT_ITER_LOOP,
|
pub EXPLICIT_ITER_LOOP,
|
||||||
|
@ -115,16 +119,18 @@ declare_clippy_lint! {
|
||||||
/// **Known problems:** None
|
/// **Known problems:** None
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```ignore
|
/// ```rust
|
||||||
|
/// # let y = vec![1];
|
||||||
/// // with `y` a `Vec` or slice:
|
/// // with `y` a `Vec` or slice:
|
||||||
/// for x in y.into_iter() {
|
/// for x in y.into_iter() {
|
||||||
/// ..
|
/// // ..
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
/// can be rewritten to
|
/// can be rewritten to
|
||||||
/// ```ignore
|
/// ```rust
|
||||||
|
/// # let y = vec![1];
|
||||||
/// for x in y {
|
/// for x in y {
|
||||||
/// ..
|
/// // ..
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub EXPLICIT_INTO_ITER_LOOP,
|
pub EXPLICIT_INTO_ITER_LOOP,
|
||||||
|
@ -217,18 +223,19 @@ declare_clippy_lint! {
|
||||||
/// **Known problems:** Sometimes the wrong binding is displayed (#383).
|
/// **Known problems:** Sometimes the wrong binding is displayed (#383).
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,no_run
|
||||||
|
/// # let y = Some(1);
|
||||||
/// loop {
|
/// loop {
|
||||||
/// let x = match y {
|
/// let x = match y {
|
||||||
/// Some(x) => x,
|
/// Some(x) => x,
|
||||||
/// None => break,
|
/// None => break,
|
||||||
/// }
|
/// };
|
||||||
/// // .. do something with x
|
/// // .. do something with x
|
||||||
/// }
|
/// }
|
||||||
/// // is easier written as
|
/// // is easier written as
|
||||||
/// while let Some(x) = y {
|
/// while let Some(x) = y {
|
||||||
/// // .. do something with x
|
/// // .. do something with x
|
||||||
/// }
|
/// };
|
||||||
/// ```
|
/// ```
|
||||||
pub WHILE_LET_LOOP,
|
pub WHILE_LET_LOOP,
|
||||||
complexity,
|
complexity,
|
||||||
|
@ -264,8 +271,9 @@ declare_clippy_lint! {
|
||||||
/// None
|
/// None
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```ignore
|
/// ```rust
|
||||||
/// let len = iterator.collect::<Vec<_>>().len();
|
/// # let iterator = vec![1].into_iter();
|
||||||
|
/// let len = iterator.clone().collect::<Vec<_>>().len();
|
||||||
/// // should be
|
/// // should be
|
||||||
/// let len = iterator.count();
|
/// let len = iterator.count();
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -309,8 +317,11 @@ declare_clippy_lint! {
|
||||||
/// **Known problems:** None.
|
/// **Known problems:** None.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```ignore
|
/// ```rust
|
||||||
/// for i in 0..v.len() { foo(v[i]);
|
/// # let v = vec![1];
|
||||||
|
/// # fn foo(bar: usize) {}
|
||||||
|
/// # fn bar(bar: usize, baz: usize) {}
|
||||||
|
/// for i in 0..v.len() { foo(v[i]); }
|
||||||
/// for i in 0..v.len() { bar(i, v[i]); }
|
/// for i in 0..v.len() { bar(i, v[i]); }
|
||||||
/// ```
|
/// ```
|
||||||
pub EXPLICIT_COUNTER_LOOP,
|
pub EXPLICIT_COUNTER_LOOP,
|
||||||
|
@ -1242,7 +1253,7 @@ fn is_end_eq_array_len<'tcx>(
|
||||||
if let ExprKind::Lit(ref lit) = end.node;
|
if let ExprKind::Lit(ref lit) = end.node;
|
||||||
if let ast::LitKind::Int(end_int, _) = lit.node;
|
if let ast::LitKind::Int(end_int, _) = lit.node;
|
||||||
if let ty::Array(_, arr_len_const) = indexed_ty.sty;
|
if let ty::Array(_, arr_len_const) = indexed_ty.sty;
|
||||||
if let Some(arr_len) = arr_len_const.assert_usize(cx.tcx);
|
if let Some(arr_len) = arr_len_const.try_eval_usize(cx.tcx, cx.param_env);
|
||||||
then {
|
then {
|
||||||
return match limits {
|
return match limits {
|
||||||
ast::RangeLimits::Closed => end_int + 1 >= arr_len.into(),
|
ast::RangeLimits::Closed => end_int + 1 >= arr_len.into(),
|
||||||
|
@ -1364,7 +1375,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr, expr: &Ex
|
||||||
match cx.tables.expr_ty(&args[0]).sty {
|
match cx.tables.expr_ty(&args[0]).sty {
|
||||||
// If the length is greater than 32 no traits are implemented for array and
|
// If the length is greater than 32 no traits are implemented for array and
|
||||||
// therefore we cannot use `&`.
|
// therefore we cannot use `&`.
|
||||||
ty::Array(_, size) if size.assert_usize(cx.tcx).expect("array size") > 32 => (),
|
ty::Array(_, size) if size.eval_usize(cx.tcx, cx.param_env) > 32 => {},
|
||||||
_ => lint_iter_method(cx, args, arg, method_name),
|
_ => lint_iter_method(cx, args, arg, method_name),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
@ -1977,7 +1988,7 @@ fn is_ref_iterable_type(cx: &LateContext<'_, '_>, e: &Expr) -> bool {
|
||||||
fn is_iterable_array<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'_, 'tcx>) -> bool {
|
fn is_iterable_array<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'_, 'tcx>) -> bool {
|
||||||
// IntoIterator is currently only implemented for array sizes <= 32 in rustc
|
// IntoIterator is currently only implemented for array sizes <= 32 in rustc
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::Array(_, n) => (0..=32).contains(&n.assert_usize(cx.tcx).expect("array length")),
|
ty::Array(_, n) => (0..=32).contains(&n.eval_usize(cx.tcx, cx.param_env)),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
62
clippy_lints/src/main_recursion.rs
Normal file
62
clippy_lints/src/main_recursion.rs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
use rustc::hir::{Crate, Expr, ExprKind, QPath};
|
||||||
|
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||||
|
use rustc::{declare_tool_lint, impl_lint_pass};
|
||||||
|
use syntax::symbol::sym;
|
||||||
|
|
||||||
|
use crate::utils::{is_entrypoint_fn, snippet, span_help_and_lint};
|
||||||
|
use if_chain::if_chain;
|
||||||
|
|
||||||
|
declare_clippy_lint! {
|
||||||
|
/// **What it does:** Checks for recursion using the entrypoint.
|
||||||
|
///
|
||||||
|
/// **Why is this bad?** Apart from special setups (which we could detect following attributes like #![no_std]),
|
||||||
|
/// recursing into main() seems like an unintuitive antipattern we should be able to detect.
|
||||||
|
///
|
||||||
|
/// **Known problems:** None.
|
||||||
|
///
|
||||||
|
/// **Example:**
|
||||||
|
/// ```no_run
|
||||||
|
/// fn main() {
|
||||||
|
/// main();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub MAIN_RECURSION,
|
||||||
|
style,
|
||||||
|
"recursion using the entrypoint"
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct MainRecursion {
|
||||||
|
has_no_std_attr: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_lint_pass!(MainRecursion => [MAIN_RECURSION]);
|
||||||
|
|
||||||
|
impl LateLintPass<'_, '_> for MainRecursion {
|
||||||
|
fn check_crate(&mut self, _: &LateContext<'_, '_>, krate: &Crate) {
|
||||||
|
self.has_no_std_attr = krate.attrs.iter().any(|attr| attr.path == sym::no_std);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_expr_post(&mut self, cx: &LateContext<'_, '_>, expr: &Expr) {
|
||||||
|
if self.has_no_std_attr {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if_chain! {
|
||||||
|
if let ExprKind::Call(func, _) = &expr.node;
|
||||||
|
if let ExprKind::Path(path) = &func.node;
|
||||||
|
if let QPath::Resolved(_, path) = &path;
|
||||||
|
if let Some(def_id) = path.res.opt_def_id();
|
||||||
|
if is_entrypoint_fn(cx, def_id);
|
||||||
|
then {
|
||||||
|
span_help_and_lint(
|
||||||
|
cx,
|
||||||
|
MAIN_RECURSION,
|
||||||
|
func.span,
|
||||||
|
&format!("recursing into entrypoint `{}`", snippet(cx, func.span, "main")),
|
||||||
|
"consider using another function for this recursion"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,20 +20,29 @@ declare_clippy_lint! {
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let x: Option<&str> = do_stuff();
|
/// # fn do_stuff() -> Option<String> { Some(String::new()) }
|
||||||
|
/// # fn log_err_msg(foo: String) -> Option<String> { Some(foo) }
|
||||||
|
/// # fn format_msg(foo: String) -> String { String::new() }
|
||||||
|
/// let x: Option<String> = do_stuff();
|
||||||
/// x.map(log_err_msg);
|
/// x.map(log_err_msg);
|
||||||
/// x.map(|msg| log_err_msg(format_msg(msg)))
|
/// # let x: Option<String> = do_stuff();
|
||||||
|
/// x.map(|msg| log_err_msg(format_msg(msg)));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// The correct use would be:
|
/// The correct use would be:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let x: Option<&str> = do_stuff();
|
/// # fn do_stuff() -> Option<String> { Some(String::new()) }
|
||||||
|
/// # fn log_err_msg(foo: String) -> Option<String> { Some(foo) }
|
||||||
|
/// # fn format_msg(foo: String) -> String { String::new() }
|
||||||
|
/// let x: Option<String> = do_stuff();
|
||||||
/// if let Some(msg) = x {
|
/// if let Some(msg) = x {
|
||||||
/// log_err_msg(msg)
|
/// log_err_msg(msg);
|
||||||
/// }
|
/// }
|
||||||
|
///
|
||||||
|
/// # let x: Option<String> = do_stuff();
|
||||||
/// if let Some(msg) = x {
|
/// if let Some(msg) = x {
|
||||||
/// log_err_msg(format_msg(msg))
|
/// log_err_msg(format_msg(msg));
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub OPTION_MAP_UNIT_FN,
|
pub OPTION_MAP_UNIT_FN,
|
||||||
|
@ -53,21 +62,29 @@ declare_clippy_lint! {
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let x: Result<&str, &str> = do_stuff();
|
/// # fn do_stuff() -> Result<String, String> { Ok(String::new()) }
|
||||||
|
/// # fn log_err_msg(foo: String) -> Result<String, String> { Ok(foo) }
|
||||||
|
/// # fn format_msg(foo: String) -> String { String::new() }
|
||||||
|
/// let x: Result<String, String> = do_stuff();
|
||||||
/// x.map(log_err_msg);
|
/// x.map(log_err_msg);
|
||||||
/// x.map(|msg| log_err_msg(format_msg(msg)))
|
/// # let x: Result<String, String> = do_stuff();
|
||||||
|
/// x.map(|msg| log_err_msg(format_msg(msg)));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// The correct use would be:
|
/// The correct use would be:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let x: Result<&str, &str> = do_stuff();
|
/// # fn do_stuff() -> Result<String, String> { Ok(String::new()) }
|
||||||
|
/// # fn log_err_msg(foo: String) -> Result<String, String> { Ok(foo) }
|
||||||
|
/// # fn format_msg(foo: String) -> String { String::new() }
|
||||||
|
/// let x: Result<String, String> = do_stuff();
|
||||||
/// if let Ok(msg) = x {
|
/// if let Ok(msg) = x {
|
||||||
/// log_err_msg(msg)
|
/// log_err_msg(msg);
|
||||||
/// }
|
/// };
|
||||||
|
/// # let x: Result<String, String> = do_stuff();
|
||||||
/// if let Ok(msg) = x {
|
/// if let Ok(msg) = x {
|
||||||
/// log_err_msg(format_msg(msg))
|
/// log_err_msg(format_msg(msg));
|
||||||
/// }
|
/// };
|
||||||
/// ```
|
/// ```
|
||||||
pub RESULT_MAP_UNIT_FN,
|
pub RESULT_MAP_UNIT_FN,
|
||||||
complexity,
|
complexity,
|
||||||
|
|
|
@ -53,19 +53,25 @@ declare_clippy_lint! {
|
||||||
/// Using `match`:
|
/// Using `match`:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # fn bar(foo: &usize) {}
|
||||||
|
/// # let other_ref: usize = 1;
|
||||||
|
/// # let x: Option<&usize> = Some(&1);
|
||||||
/// match x {
|
/// match x {
|
||||||
/// Some(ref foo) => bar(foo),
|
/// Some(ref foo) => bar(foo),
|
||||||
/// _ => bar(other_ref),
|
/// _ => bar(&other_ref),
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Using `if let` with `else`:
|
/// Using `if let` with `else`:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # fn bar(foo: &usize) {}
|
||||||
|
/// # let other_ref: usize = 1;
|
||||||
|
/// # let x: Option<&usize> = Some(&1);
|
||||||
/// if let Some(ref foo) = x {
|
/// if let Some(ref foo) = x {
|
||||||
/// bar(foo);
|
/// bar(foo);
|
||||||
/// } else {
|
/// } else {
|
||||||
/// bar(other_ref);
|
/// bar(&other_ref);
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub SINGLE_MATCH_ELSE,
|
pub SINGLE_MATCH_ELSE,
|
||||||
|
@ -205,6 +211,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # enum Foo { A(usize), B(usize) }
|
||||||
|
/// # let x = Foo::B(1);
|
||||||
/// match x {
|
/// match x {
|
||||||
/// A => {},
|
/// A => {},
|
||||||
/// _ => {},
|
/// _ => {},
|
||||||
|
|
|
@ -14,6 +14,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # use std::mem;
|
||||||
|
/// # use std::rc::Rc;
|
||||||
/// mem::forget(Rc::new(55))
|
/// mem::forget(Rc::new(55))
|
||||||
/// ```
|
/// ```
|
||||||
pub MEM_FORGET,
|
pub MEM_FORGET,
|
||||||
|
|
|
@ -40,8 +40,19 @@ declare_clippy_lint! {
|
||||||
/// **Known problems:** None.
|
/// **Known problems:** None.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
|
///
|
||||||
|
/// Using unwrap on an `Option`:
|
||||||
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// x.unwrap()
|
/// let opt = Some(1);
|
||||||
|
/// opt.unwrap();
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Better:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// let opt = Some(1);
|
||||||
|
/// opt.expect("more helpful message");
|
||||||
/// ```
|
/// ```
|
||||||
pub OPTION_UNWRAP_USED,
|
pub OPTION_UNWRAP_USED,
|
||||||
restriction,
|
restriction,
|
||||||
|
@ -62,8 +73,18 @@ declare_clippy_lint! {
|
||||||
/// **Known problems:** None.
|
/// **Known problems:** None.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
|
/// Using unwrap on an `Option`:
|
||||||
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// x.unwrap()
|
/// let res: Result<usize, ()> = Ok(1);
|
||||||
|
/// res.unwrap();
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Better:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// let res: Result<usize, ()> = Ok(1);
|
||||||
|
/// res.expect("more helpful message");
|
||||||
/// ```
|
/// ```
|
||||||
pub RESULT_UNWRAP_USED,
|
pub RESULT_UNWRAP_USED,
|
||||||
restriction,
|
restriction,
|
||||||
|
@ -141,9 +162,10 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// impl X {
|
/// # struct X;
|
||||||
/// pub fn as_str(self) -> &str {
|
/// impl<'a> X {
|
||||||
/// ..
|
/// pub fn as_str(self) -> &'a str {
|
||||||
|
/// "foo"
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -179,7 +201,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// x.map(|a| a + 1).unwrap_or(0)
|
/// # let x = Some(1);
|
||||||
|
/// x.map(|a| a + 1).unwrap_or(0);
|
||||||
/// ```
|
/// ```
|
||||||
pub OPTION_MAP_UNWRAP_OR,
|
pub OPTION_MAP_UNWRAP_OR,
|
||||||
pedantic,
|
pedantic,
|
||||||
|
@ -196,7 +219,9 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// x.map(|a| a + 1).unwrap_or_else(some_function)
|
/// # let x = Some(1);
|
||||||
|
/// # fn some_function() -> usize { 1 }
|
||||||
|
/// x.map(|a| a + 1).unwrap_or_else(some_function);
|
||||||
/// ```
|
/// ```
|
||||||
pub OPTION_MAP_UNWRAP_OR_ELSE,
|
pub OPTION_MAP_UNWRAP_OR_ELSE,
|
||||||
pedantic,
|
pedantic,
|
||||||
|
@ -213,7 +238,9 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// x.map(|a| a + 1).unwrap_or_else(some_function)
|
/// # let x: Result<usize, ()> = Ok(1);
|
||||||
|
/// # fn some_function(foo: ()) -> usize { 1 }
|
||||||
|
/// x.map(|a| a + 1).unwrap_or_else(some_function);
|
||||||
/// ```
|
/// ```
|
||||||
pub RESULT_MAP_UNWRAP_OR_ELSE,
|
pub RESULT_MAP_UNWRAP_OR_ELSE,
|
||||||
pedantic,
|
pedantic,
|
||||||
|
@ -247,7 +274,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// iter.filter(|x| x == 0).next()
|
/// # let vec = vec![1];
|
||||||
|
/// vec.iter().filter(|x| **x == 0).next();
|
||||||
/// ```
|
/// ```
|
||||||
pub FILTER_NEXT,
|
pub FILTER_NEXT,
|
||||||
complexity,
|
complexity,
|
||||||
|
@ -264,7 +292,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// iter.map(|x| x.iter()).flatten()
|
/// let vec = vec![vec![1]];
|
||||||
|
/// vec.iter().map(|x| x.iter()).flatten();
|
||||||
/// ```
|
/// ```
|
||||||
pub MAP_FLATTEN,
|
pub MAP_FLATTEN,
|
||||||
pedantic,
|
pedantic,
|
||||||
|
@ -283,7 +312,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// iter.filter(|x| x == 0).map(|x| x * 2)
|
/// let vec = vec![1];
|
||||||
|
/// vec.iter().filter(|x| **x == 0).map(|x| *x * 2);
|
||||||
/// ```
|
/// ```
|
||||||
pub FILTER_MAP,
|
pub FILTER_MAP,
|
||||||
pedantic,
|
pedantic,
|
||||||
|
@ -343,7 +373,7 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// (0..3).find(|x| x == 2).map(|x| x * 2);
|
/// (0..3).find(|x| *x == 2).map(|x| x * 2);
|
||||||
/// ```
|
/// ```
|
||||||
/// Can be written as
|
/// Can be written as
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
@ -365,7 +395,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// iter.find(|x| x == 0).is_some()
|
/// # let vec = vec![1];
|
||||||
|
/// vec.iter().find(|x| **x == 0).is_some();
|
||||||
/// ```
|
/// ```
|
||||||
pub SEARCH_IS_SOME,
|
pub SEARCH_IS_SOME,
|
||||||
complexity,
|
complexity,
|
||||||
|
@ -383,7 +414,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// name.chars().next() == Some('_')
|
/// let name = "foo";
|
||||||
|
/// name.chars().next() == Some('_');
|
||||||
/// ```
|
/// ```
|
||||||
pub CHARS_NEXT_CMP,
|
pub CHARS_NEXT_CMP,
|
||||||
complexity,
|
complexity,
|
||||||
|
@ -403,15 +435,18 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// foo.unwrap_or(String::new())
|
/// # let foo = Some(String::new());
|
||||||
|
/// foo.unwrap_or(String::new());
|
||||||
/// ```
|
/// ```
|
||||||
/// this can instead be written:
|
/// this can instead be written:
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// foo.unwrap_or_else(String::new)
|
/// # let foo = Some(String::new());
|
||||||
|
/// foo.unwrap_or_else(String::new);
|
||||||
/// ```
|
/// ```
|
||||||
/// or
|
/// or
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// foo.unwrap_or_default()
|
/// # let foo = Some(String::new());
|
||||||
|
/// foo.unwrap_or_default();
|
||||||
/// ```
|
/// ```
|
||||||
pub OR_FUN_CALL,
|
pub OR_FUN_CALL,
|
||||||
perf,
|
perf,
|
||||||
|
@ -429,15 +464,24 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// foo.expect(&format!("Err {}: {}", err_code, err_msg))
|
/// # let foo = Some(String::new());
|
||||||
|
/// # let err_code = "418";
|
||||||
|
/// # let err_msg = "I'm a teapot";
|
||||||
|
/// foo.expect(&format!("Err {}: {}", err_code, err_msg));
|
||||||
/// ```
|
/// ```
|
||||||
/// or
|
/// or
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// foo.expect(format!("Err {}: {}", err_code, err_msg).as_str())
|
/// # let foo = Some(String::new());
|
||||||
|
/// # let err_code = "418";
|
||||||
|
/// # let err_msg = "I'm a teapot";
|
||||||
|
/// foo.expect(format!("Err {}: {}", err_code, err_msg).as_str());
|
||||||
/// ```
|
/// ```
|
||||||
/// this can instead be written:
|
/// this can instead be written:
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// foo.unwrap_or_else(|_| panic!("Err {}: {}", err_code, err_msg))
|
/// # let foo = Some(String::new());
|
||||||
|
/// # let err_code = "418";
|
||||||
|
/// # let err_msg = "I'm a teapot";
|
||||||
|
/// foo.unwrap_or_else(|| panic!("Err {}: {}", err_code, err_msg));
|
||||||
/// ```
|
/// ```
|
||||||
pub EXPECT_FUN_CALL,
|
pub EXPECT_FUN_CALL,
|
||||||
perf,
|
perf,
|
||||||
|
@ -454,7 +498,7 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// 42u64.clone()
|
/// 42u64.clone();
|
||||||
/// ```
|
/// ```
|
||||||
pub CLONE_ON_COPY,
|
pub CLONE_ON_COPY,
|
||||||
complexity,
|
complexity,
|
||||||
|
@ -472,7 +516,9 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// x.clone()
|
/// # use std::rc::Rc;
|
||||||
|
/// let x = Rc::new(1);
|
||||||
|
/// x.clone();
|
||||||
/// ```
|
/// ```
|
||||||
pub CLONE_ON_REF_PTR,
|
pub CLONE_ON_REF_PTR,
|
||||||
restriction,
|
restriction,
|
||||||
|
@ -728,11 +774,13 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # fn do_stuff(x: &[i32]) {}
|
||||||
/// let x: &[i32] = &[1, 2, 3, 4, 5];
|
/// let x: &[i32] = &[1, 2, 3, 4, 5];
|
||||||
/// do_stuff(x.as_ref());
|
/// do_stuff(x.as_ref());
|
||||||
/// ```
|
/// ```
|
||||||
/// The correct use would be:
|
/// The correct use would be:
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # fn do_stuff(x: &[i32]) {}
|
||||||
/// let x: &[i32] = &[1, 2, 3, 4, 5];
|
/// let x: &[i32] = &[1, 2, 3, 4, 5];
|
||||||
/// do_stuff(x);
|
/// do_stuff(x);
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -911,7 +959,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
|
||||||
["is_some", "position"] => lint_search_is_some(cx, expr, "position", arg_lists[1], arg_lists[0]),
|
["is_some", "position"] => lint_search_is_some(cx, expr, "position", arg_lists[1], arg_lists[0]),
|
||||||
["is_some", "rposition"] => lint_search_is_some(cx, expr, "rposition", arg_lists[1], arg_lists[0]),
|
["is_some", "rposition"] => lint_search_is_some(cx, expr, "rposition", arg_lists[1], arg_lists[0]),
|
||||||
["extend", ..] => lint_extend(cx, expr, arg_lists[0]),
|
["extend", ..] => lint_extend(cx, expr, arg_lists[0]),
|
||||||
["as_ptr", "unwrap"] => lint_cstring_as_ptr(cx, expr, &arg_lists[1][0], &arg_lists[0][0]),
|
["as_ptr", "unwrap"] | ["as_ptr", "expect"] => {
|
||||||
|
lint_cstring_as_ptr(cx, expr, &arg_lists[1][0], &arg_lists[0][0])
|
||||||
|
},
|
||||||
["nth", "iter"] => lint_iter_nth(cx, expr, arg_lists[1], false),
|
["nth", "iter"] => lint_iter_nth(cx, expr, arg_lists[1], false),
|
||||||
["nth", "iter_mut"] => lint_iter_nth(cx, expr, arg_lists[1], true),
|
["nth", "iter_mut"] => lint_iter_nth(cx, expr, arg_lists[1], true),
|
||||||
["next", "skip"] => lint_iter_skip_next(cx, expr),
|
["next", "skip"] => lint_iter_skip_next(cx, expr),
|
||||||
|
@ -1799,7 +1849,7 @@ fn derefs_to_slice<'a, 'tcx>(
|
||||||
ty::Slice(_) => true,
|
ty::Slice(_) => true,
|
||||||
ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()),
|
ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()),
|
||||||
ty::Adt(..) => match_type(cx, ty, &paths::VEC),
|
ty::Adt(..) => match_type(cx, ty, &paths::VEC),
|
||||||
ty::Array(_, size) => size.assert_usize(cx.tcx).expect("array length") < 32,
|
ty::Array(_, size) => size.eval_usize(cx.tcx, cx.param_env) < 32,
|
||||||
ty::Ref(_, inner, _) => may_slice(cx, inner),
|
ty::Ref(_, inner, _) => may_slice(cx, inner),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -2327,13 +2377,20 @@ fn lint_chars_last_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &
|
||||||
fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, _expr: &'tcx hir::Expr, arg: &'tcx hir::Expr) {
|
fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, _expr: &'tcx hir::Expr, arg: &'tcx hir::Expr) {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let hir::ExprKind::Lit(lit) = &arg.node;
|
if let hir::ExprKind::Lit(lit) = &arg.node;
|
||||||
if let ast::LitKind::Str(r, _) = lit.node;
|
if let ast::LitKind::Str(r, style) = lit.node;
|
||||||
if r.as_str().len() == 1;
|
if r.as_str().len() == 1;
|
||||||
then {
|
then {
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
let snip = snippet_with_applicability(cx, arg.span, "..", &mut applicability);
|
let snip = snippet_with_applicability(cx, arg.span, "..", &mut applicability);
|
||||||
let c = &snip[1..snip.len() - 1];
|
let ch = if let ast::StrStyle::Raw(nhash) = style {
|
||||||
let hint = format!("'{}'", if c == "'" { "\\'" } else { c });
|
let nhash = nhash as usize;
|
||||||
|
// for raw string: r##"a"##
|
||||||
|
&snip[(nhash + 2)..(snip.len() - 1 - nhash)]
|
||||||
|
} else {
|
||||||
|
// for regular string: "a"
|
||||||
|
&snip[1..(snip.len() - 1)]
|
||||||
|
};
|
||||||
|
let hint = format!("'{}'", if ch == "'" { "\\'" } else { ch });
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
SINGLE_CHAR_PATTERN,
|
SINGLE_CHAR_PATTERN,
|
||||||
|
@ -2551,14 +2608,14 @@ impl SelfKind {
|
||||||
let is_actually_self = |ty| is_self_ty(ty) || SpanlessEq::new(cx).eq_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) {
|
if is_self(arg) {
|
||||||
match self {
|
match self {
|
||||||
SelfKind::Value => is_actually_self(ty),
|
Self::Value => is_actually_self(ty),
|
||||||
SelfKind::Ref | SelfKind::RefMut => {
|
Self::Ref | Self::RefMut => {
|
||||||
if allow_value_for_ref && is_actually_self(ty) {
|
if allow_value_for_ref && is_actually_self(ty) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
match ty.node {
|
match ty.node {
|
||||||
hir::TyKind::Rptr(_, ref mt_ty) => {
|
hir::TyKind::Rptr(_, ref mt_ty) => {
|
||||||
let mutability_match = if self == SelfKind::Ref {
|
let mutability_match = if self == Self::Ref {
|
||||||
mt_ty.mutbl == hir::MutImmutable
|
mt_ty.mutbl == hir::MutImmutable
|
||||||
} else {
|
} else {
|
||||||
mt_ty.mutbl == hir::MutMutable
|
mt_ty.mutbl == hir::MutMutable
|
||||||
|
@ -2572,20 +2629,20 @@ impl SelfKind {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match self {
|
match self {
|
||||||
SelfKind::Value => false,
|
Self::Value => false,
|
||||||
SelfKind::Ref => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASREF_TRAIT),
|
Self::Ref => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASREF_TRAIT),
|
||||||
SelfKind::RefMut => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASMUT_TRAIT),
|
Self::RefMut => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASMUT_TRAIT),
|
||||||
SelfKind::No => true,
|
Self::No => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn description(self) -> &'static str {
|
fn description(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
SelfKind::Value => "self by value",
|
Self::Value => "self by value",
|
||||||
SelfKind::Ref => "self by reference",
|
Self::Ref => "self by reference",
|
||||||
SelfKind::RefMut => "self by mutable reference",
|
Self::RefMut => "self by mutable reference",
|
||||||
SelfKind::No => "no self",
|
Self::No => "no self",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2655,8 +2712,8 @@ fn single_segment_ty(ty: &hir::Ty) -> Option<&hir::PathSegment> {
|
||||||
impl Convention {
|
impl Convention {
|
||||||
fn check(&self, other: &str) -> bool {
|
fn check(&self, other: &str) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
Convention::Eq(this) => this == other,
|
Self::Eq(this) => this == other,
|
||||||
Convention::StartsWith(this) => other.starts_with(this) && this != other,
|
Self::StartsWith(this) => other.starts_with(this) && this != other,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2664,8 +2721,8 @@ impl Convention {
|
||||||
impl fmt::Display for 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 {
|
match *self {
|
||||||
Convention::Eq(this) => this.fmt(f),
|
Self::Eq(this) => this.fmt(f),
|
||||||
Convention::StartsWith(this) => this.fmt(f).and_then(|_| '*'.fmt(f)),
|
Self::StartsWith(this) => this.fmt(f).and_then(|_| '*'.fmt(f)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2682,11 +2739,11 @@ impl OutType {
|
||||||
fn matches(self, cx: &LateContext<'_, '_>, 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()));
|
let is_unit = |ty: &hir::Ty| SpanlessEq::new(cx).eq_ty_kind(&ty.node, &hir::TyKind::Tup(vec![].into()));
|
||||||
match (self, ty) {
|
match (self, ty) {
|
||||||
(OutType::Unit, &hir::DefaultReturn(_)) => true,
|
(Self::Unit, &hir::DefaultReturn(_)) => true,
|
||||||
(OutType::Unit, &hir::Return(ref ty)) if is_unit(ty) => true,
|
(Self::Unit, &hir::Return(ref ty)) if is_unit(ty) => true,
|
||||||
(OutType::Bool, &hir::Return(ref ty)) if is_bool(ty) => true,
|
(Self::Bool, &hir::Return(ref ty)) if is_bool(ty) => true,
|
||||||
(OutType::Any, &hir::Return(ref ty)) if !is_unit(ty) => true,
|
(Self::Any, &hir::Return(ref ty)) if !is_unit(ty) => true,
|
||||||
(OutType::Ref, &hir::Return(ref ty)) => matches!(ty.node, hir::TyKind::Rptr(_, _)),
|
(Self::Ref, &hir::Return(ref ty)) => matches!(ty.node, hir::TyKind::Rptr(_, _)),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use rustc::ty;
|
||||||
use rustc::{declare_lint_pass, declare_tool_lint};
|
use rustc::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use syntax::ast::LitKind;
|
use syntax::ast::LitKind;
|
||||||
use syntax::source_map::{ExpnFormat, Span};
|
use syntax::source_map::{ExpnKind, Span};
|
||||||
|
|
||||||
use crate::consts::{constant, Constant};
|
use crate::consts::{constant, Constant};
|
||||||
use crate::utils::sugg::Sugg;
|
use crate::utils::sugg::Sugg;
|
||||||
|
@ -101,7 +101,9 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// x.to_owned() == y
|
/// # let x = "foo";
|
||||||
|
/// # let y = String::from("foo");
|
||||||
|
/// if x.to_owned() == y {}
|
||||||
/// ```
|
/// ```
|
||||||
pub CMP_OWNED,
|
pub CMP_OWNED,
|
||||||
perf,
|
perf,
|
||||||
|
@ -184,7 +186,7 @@ declare_clippy_lint! {
|
||||||
/// **Known problems:** None.
|
/// **Known problems:** None.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// f() && g(); // We should write `if f() { g(); }`.
|
/// f() && g(); // We should write `if f() { g(); }`.
|
||||||
/// ```
|
/// ```
|
||||||
pub SHORT_CIRCUIT_STATEMENT,
|
pub SHORT_CIRCUIT_STATEMENT,
|
||||||
|
@ -224,8 +226,9 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// const ONE = 1.00f64;
|
/// let x: f64 = 1.0;
|
||||||
/// x == ONE // where both are floats
|
/// const ONE: f64 = 1.00;
|
||||||
|
/// x == ONE; // where both are floats
|
||||||
/// ```
|
/// ```
|
||||||
pub FLOAT_CMP_CONST,
|
pub FLOAT_CMP_CONST,
|
||||||
restriction,
|
restriction,
|
||||||
|
@ -364,6 +367,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints {
|
||||||
if is_allowed(cx, left) || is_allowed(cx, right) {
|
if is_allowed(cx, left) || is_allowed(cx, right) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allow comparing the results of signum()
|
||||||
|
if is_signum(cx, left) && is_signum(cx, right) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(name) = get_item_name(cx, expr) {
|
if let Some(name) = get_item_name(cx, expr) {
|
||||||
let name = name.as_str();
|
let name = name.as_str();
|
||||||
if name == "eq"
|
if name == "eq"
|
||||||
|
@ -493,6 +502,25 @@ fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return true if `expr` is the result of `signum()` invoked on a float value.
|
||||||
|
fn is_signum(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
|
||||||
|
// The negation of a signum is still a signum
|
||||||
|
if let ExprKind::Unary(UnNeg, ref child_expr) = expr.node {
|
||||||
|
return is_signum(cx, &child_expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if_chain! {
|
||||||
|
if let ExprKind::MethodCall(ref method_name, _, ref expressions) = expr.node;
|
||||||
|
if sym!(signum) == method_name.ident.name;
|
||||||
|
// Check that the receiver of the signum() is a float (expressions[0] is the receiver of
|
||||||
|
// the method call)
|
||||||
|
then {
|
||||||
|
return is_float(cx, &expressions[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
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::Float(_))
|
matches!(walk_ptrs_ty(cx.tables.expr_ty(expr)).sty, ty::Float(_))
|
||||||
}
|
}
|
||||||
|
@ -596,10 +624,14 @@ fn is_used(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
|
||||||
/// Tests whether an expression is in a macro expansion (e.g., something
|
/// Tests whether an expression is in a macro expansion (e.g., something
|
||||||
/// generated by `#[derive(...)]` or the like).
|
/// generated by `#[derive(...)]` or the like).
|
||||||
fn in_attributes_expansion(expr: &Expr) -> bool {
|
fn in_attributes_expansion(expr: &Expr) -> bool {
|
||||||
expr.span
|
use syntax::ext::hygiene::MacroKind;
|
||||||
.ctxt()
|
expr.span.ctxt().outer_expn_info().map_or(false, |info| {
|
||||||
.outer_expn_info()
|
if let ExpnKind::Macro(MacroKind::Attr, _) = info.kind {
|
||||||
.map_or(false, |info| matches!(info.format, ExpnFormat::MacroAttribute(_)))
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests whether `res` is a variable defined outside a macro.
|
/// Tests whether `res` is a variable defined outside a macro.
|
||||||
|
|
|
@ -53,7 +53,7 @@ declare_clippy_lint! {
|
||||||
/// **Known problems:** None.
|
/// **Known problems:** None.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// (|| 42)()
|
/// (|| 42)()
|
||||||
/// ```
|
/// ```
|
||||||
pub REDUNDANT_CLOSURE_CALL,
|
pub REDUNDANT_CLOSURE_CALL,
|
||||||
|
@ -305,7 +305,7 @@ impl EarlyLintPass for MiscEarlyLints {
|
||||||
name makes code comprehension and documentation more difficult",
|
name makes code comprehension and documentation more difficult",
|
||||||
arg_name[1..].to_owned()
|
arg_name[1..].to_owned()
|
||||||
),
|
),
|
||||||
);;
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
registered_names.insert(arg_name, arg.pat.span);
|
registered_names.insert(arg_name, arg.pat.span);
|
||||||
|
|
|
@ -40,17 +40,27 @@ declare_clippy_lint! {
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # struct Foo {
|
||||||
|
/// # random_number: usize,
|
||||||
|
/// # }
|
||||||
|
/// # impl Foo {
|
||||||
/// fn new() -> Self {
|
/// fn new() -> Self {
|
||||||
/// Self { random_number: 42 }
|
/// Self { random_number: 42 }
|
||||||
/// }
|
/// }
|
||||||
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Could be a const fn:
|
/// Could be a const fn:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # struct Foo {
|
||||||
|
/// # random_number: usize,
|
||||||
|
/// # }
|
||||||
|
/// # impl Foo {
|
||||||
/// const fn new() -> Self {
|
/// const fn new() -> Self {
|
||||||
/// Self { random_number: 42 }
|
/// Self { random_number: 42 }
|
||||||
/// }
|
/// }
|
||||||
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub MISSING_CONST_FOR_FN,
|
pub MISSING_CONST_FOR_FN,
|
||||||
nursery,
|
nursery,
|
||||||
|
|
|
@ -146,9 +146,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
|
||||||
hir::ItemKind::Struct(..) => "a struct",
|
hir::ItemKind::Struct(..) => "a struct",
|
||||||
hir::ItemKind::Trait(..) => "a trait",
|
hir::ItemKind::Trait(..) => "a trait",
|
||||||
hir::ItemKind::TraitAlias(..) => "a trait alias",
|
hir::ItemKind::TraitAlias(..) => "a trait alias",
|
||||||
hir::ItemKind::Ty(..) => "a type alias",
|
hir::ItemKind::TyAlias(..) => "a type alias",
|
||||||
hir::ItemKind::Union(..) => "a union",
|
hir::ItemKind::Union(..) => "a union",
|
||||||
hir::ItemKind::Existential(..) => "an existential type",
|
hir::ItemKind::OpaqueTy(..) => "an existential type",
|
||||||
hir::ItemKind::ExternCrate(..)
|
hir::ItemKind::ExternCrate(..)
|
||||||
| hir::ItemKind::ForeignMod(..)
|
| hir::ItemKind::ForeignMod(..)
|
||||||
| hir::ItemKind::GlobalAsm(..)
|
| hir::ItemKind::GlobalAsm(..)
|
||||||
|
@ -184,8 +184,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
|
||||||
let desc = match impl_item.node {
|
let desc = match impl_item.node {
|
||||||
hir::ImplItemKind::Const(..) => "an associated constant",
|
hir::ImplItemKind::Const(..) => "an associated constant",
|
||||||
hir::ImplItemKind::Method(..) => "a method",
|
hir::ImplItemKind::Method(..) => "a method",
|
||||||
hir::ImplItemKind::Type(_) => "an associated type",
|
hir::ImplItemKind::TyAlias(_) => "an associated type",
|
||||||
hir::ImplItemKind::Existential(_) => "an existential type",
|
hir::ImplItemKind::OpaqueTy(_) => "an existential type",
|
||||||
};
|
};
|
||||||
self.check_missing_docs_attrs(cx, &impl_item.attrs, impl_item.span, desc);
|
self.check_missing_docs_attrs(cx, &impl_item.attrs, impl_item.span, desc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// struct Baz;
|
/// struct Baz;
|
||||||
/// impl Baz {
|
/// impl Baz {
|
||||||
/// fn priv() {} // ok
|
/// fn private() {} // ok
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// impl Bar for Baz {
|
/// impl Bar for Baz {
|
||||||
|
@ -42,8 +42,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// pub struct PubBaz;
|
/// pub struct PubBaz;
|
||||||
/// impl PubBaz {
|
/// impl PubBaz {
|
||||||
/// fn priv() {} // ok
|
/// fn private() {} // ok
|
||||||
/// pub not_ptriv() {} // missing #[inline]
|
/// pub fn not_ptrivate() {} // missing #[inline]
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// impl Bar for PubBaz {
|
/// impl Bar for PubBaz {
|
||||||
|
@ -119,9 +119,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline {
|
||||||
| hir::ItemKind::Struct(..)
|
| hir::ItemKind::Struct(..)
|
||||||
| hir::ItemKind::TraitAlias(..)
|
| hir::ItemKind::TraitAlias(..)
|
||||||
| hir::ItemKind::GlobalAsm(..)
|
| hir::ItemKind::GlobalAsm(..)
|
||||||
| hir::ItemKind::Ty(..)
|
| hir::ItemKind::TyAlias(..)
|
||||||
| hir::ItemKind::Union(..)
|
| hir::ItemKind::Union(..)
|
||||||
| hir::ItemKind::Existential(..)
|
| hir::ItemKind::OpaqueTy(..)
|
||||||
| hir::ItemKind::ExternCrate(..)
|
| hir::ItemKind::ExternCrate(..)
|
||||||
| hir::ItemKind::ForeignMod(..)
|
| hir::ItemKind::ForeignMod(..)
|
||||||
| hir::ItemKind::Impl(..)
|
| hir::ItemKind::Impl(..)
|
||||||
|
@ -142,7 +142,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline {
|
||||||
|
|
||||||
let desc = match impl_item.node {
|
let desc = match impl_item.node {
|
||||||
hir::ImplItemKind::Method(..) => "a method",
|
hir::ImplItemKind::Method(..) => "a method",
|
||||||
hir::ImplItemKind::Const(..) | hir::ImplItemKind::Type(_) | hir::ImplItemKind::Existential(_) => return,
|
hir::ImplItemKind::Const(..) | hir::ImplItemKind::TyAlias(_) | hir::ImplItemKind::OpaqueTy(_) => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let def_id = cx.tcx.hir().local_def_id(impl_item.hir_id);
|
let def_id = cx.tcx.hir().local_def_id(impl_item.hir_id);
|
||||||
|
|
|
@ -16,6 +16,7 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # let mut y = 1;
|
||||||
/// let x = &mut &mut y;
|
/// let x = &mut &mut y;
|
||||||
/// ```
|
/// ```
|
||||||
pub MUT_MUT,
|
pub MUT_MUT,
|
||||||
|
|
|
@ -22,6 +22,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # use std::sync::Mutex;
|
||||||
|
/// # let y = 1;
|
||||||
/// let x = Mutex::new(&y);
|
/// let x = Mutex::new(&y);
|
||||||
/// ```
|
/// ```
|
||||||
pub MUTEX_ATOMIC,
|
pub MUTEX_ATOMIC,
|
||||||
|
@ -42,6 +44,7 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # use std::sync::Mutex;
|
||||||
/// let x = Mutex::new(0usize);
|
/// let x = Mutex::new(0usize);
|
||||||
/// ```
|
/// ```
|
||||||
pub MUTEX_INTEGER,
|
pub MUTEX_INTEGER,
|
||||||
|
|
|
@ -24,7 +24,7 @@ declare_clippy_lint! {
|
||||||
/// shorter code.
|
/// shorter code.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// if x {
|
/// if x {
|
||||||
/// false
|
/// false
|
||||||
/// } else {
|
/// } else {
|
||||||
|
@ -46,7 +46,7 @@ declare_clippy_lint! {
|
||||||
/// **Known problems:** None.
|
/// **Known problems:** None.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// if x == true {} // could be `if x { }`
|
/// if x == true {} // could be `if x { }`
|
||||||
/// ```
|
/// ```
|
||||||
pub BOOL_COMPARISON,
|
pub BOOL_COMPARISON,
|
||||||
|
@ -118,13 +118,11 @@ fn parent_node_is_if_expr<'a, 'b>(expr: &Expr, cx: &LateContext<'a, 'b>) -> bool
|
||||||
let parent_id = cx.tcx.hir().get_parent_node(expr.hir_id);
|
let parent_id = cx.tcx.hir().get_parent_node(expr.hir_id);
|
||||||
let parent_node = cx.tcx.hir().get(parent_id);
|
let parent_node = cx.tcx.hir().get(parent_id);
|
||||||
|
|
||||||
if let rustc::hir::Node::Expr(e) = parent_node {
|
match parent_node {
|
||||||
if higher::if_block(&e).is_some() {
|
rustc::hir::Node::Expr(e) => higher::if_block(&e).is_some(),
|
||||||
return true;
|
rustc::hir::Node::Arm(e) => higher::if_block(&e.body).is_some(),
|
||||||
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_lint_pass!(BoolComparison => [BOOL_COMPARISON]);
|
declare_lint_pass!(BoolComparison => [BOOL_COMPARISON]);
|
||||||
|
|
|
@ -18,7 +18,7 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Known problems:** It seems that the `&ref` pattern is sometimes useful.
|
/// **Known problems:** It seems that the `&ref` pattern is sometimes useful.
|
||||||
/// For instance in the following snippet:
|
/// For instance in the following snippet:
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// enum Animal {
|
/// enum Animal {
|
||||||
/// Cat(u64),
|
/// Cat(u64),
|
||||||
/// Dog(u64),
|
/// Dog(u64),
|
||||||
|
@ -26,8 +26,7 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// fn foo(a: &Animal, b: &Animal) {
|
/// fn foo(a: &Animal, b: &Animal) {
|
||||||
/// match (a, b) {
|
/// match (a, b) {
|
||||||
/// (&Animal::Cat(v), k) | (k, &Animal::Cat(v)) => (), // lifetime
|
/// (&Animal::Cat(v), k) | (k, &Animal::Cat(v)) => (), // lifetime mismatch error
|
||||||
/// mismatch error
|
|
||||||
/// (&Animal::Dog(ref c), &Animal::Dog(_)) => ()
|
/// (&Animal::Dog(ref c), &Animal::Dog(_)) => ()
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
|
|
|
@ -57,6 +57,9 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # fn condition() -> bool { false }
|
||||||
|
/// # fn update_condition() {}
|
||||||
|
/// # let x = false;
|
||||||
/// while condition() {
|
/// while condition() {
|
||||||
/// update_condition();
|
/// update_condition();
|
||||||
/// if x {
|
/// if x {
|
||||||
|
@ -71,6 +74,9 @@ declare_clippy_lint! {
|
||||||
/// Could be rewritten as
|
/// Could be rewritten as
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # fn condition() -> bool { false }
|
||||||
|
/// # fn update_condition() {}
|
||||||
|
/// # let x = false;
|
||||||
/// while condition() {
|
/// while condition() {
|
||||||
/// update_condition();
|
/// update_condition();
|
||||||
/// if x {
|
/// if x {
|
||||||
|
@ -83,22 +89,26 @@ declare_clippy_lint! {
|
||||||
/// As another example, the following code
|
/// As another example, the following code
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # fn waiting() -> bool { false }
|
||||||
/// loop {
|
/// loop {
|
||||||
/// if waiting() {
|
/// if waiting() {
|
||||||
/// continue;
|
/// continue;
|
||||||
/// } else {
|
/// } else {
|
||||||
/// // Do something useful
|
/// // Do something useful
|
||||||
/// }
|
/// }
|
||||||
|
/// # break;
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
/// Could be rewritten as
|
/// Could be rewritten as
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # fn waiting() -> bool { false }
|
||||||
/// loop {
|
/// loop {
|
||||||
/// if waiting() {
|
/// if waiting() {
|
||||||
/// continue;
|
/// continue;
|
||||||
/// }
|
/// }
|
||||||
/// // Do something useful
|
/// // Do something useful
|
||||||
|
/// # break;
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub NEEDLESS_CONTINUE,
|
pub NEEDLESS_CONTINUE,
|
||||||
|
|
|
@ -40,6 +40,9 @@ declare_clippy_lint! {
|
||||||
/// fn foo(v: Vec<i32>) {
|
/// fn foo(v: Vec<i32>) {
|
||||||
/// assert_eq!(v.len(), 42);
|
/// assert_eq!(v.len(), 42);
|
||||||
/// }
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
/// // should be
|
/// // should be
|
||||||
/// fn foo(v: &[i32]) {
|
/// fn foo(v: &[i32]) {
|
||||||
/// assert_eq!(v.len(), 42);
|
/// assert_eq!(v.len(), 42);
|
||||||
|
@ -193,7 +196,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
|
||||||
|
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if !is_self(arg);
|
if !is_self(arg);
|
||||||
if !ty.is_mutable_pointer();
|
if !ty.is_mutable_ptr();
|
||||||
if !is_copy(cx, ty);
|
if !is_copy(cx, ty);
|
||||||
if !whitelisted_traits.iter().any(|&t| implements_trait(cx, ty, t, &[]));
|
if !whitelisted_traits.iter().any(|&t| implements_trait(cx, ty, t, &[]));
|
||||||
if !implements_borrow_trait;
|
if !implements_borrow_trait;
|
||||||
|
|
|
@ -15,11 +15,17 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # struct Point {
|
||||||
|
/// # x: i32,
|
||||||
|
/// # y: i32,
|
||||||
|
/// # z: i32,
|
||||||
|
/// # }
|
||||||
|
/// # let zero_point = Point { x: 0, y: 0, z: 0 };
|
||||||
/// Point {
|
/// Point {
|
||||||
/// x: 1,
|
/// x: 1,
|
||||||
/// y: 0,
|
/// y: 1,
|
||||||
/// ..zero_point
|
/// ..zero_point
|
||||||
/// }
|
/// };
|
||||||
/// ```
|
/// ```
|
||||||
pub NEEDLESS_UPDATE,
|
pub NEEDLESS_UPDATE,
|
||||||
complexity,
|
complexity,
|
||||||
|
|
|
@ -34,7 +34,7 @@ declare_clippy_lint! {
|
||||||
/// **Known problems:** None.
|
/// **Known problems:** None.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// compute_array()[0];
|
/// compute_array()[0];
|
||||||
/// ```
|
/// ```
|
||||||
pub UNNECESSARY_OPERATION,
|
pub UNNECESSARY_OPERATION,
|
||||||
|
|
|
@ -84,6 +84,7 @@ declare_clippy_lint! {
|
||||||
"referencing const with interior mutability"
|
"referencing const with interior mutability"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
enum Source {
|
enum Source {
|
||||||
Item { item: Span },
|
Item { item: Span },
|
||||||
|
@ -94,12 +95,12 @@ enum Source {
|
||||||
impl Source {
|
impl Source {
|
||||||
fn lint(&self) -> (&'static Lint, &'static str, Span) {
|
fn lint(&self) -> (&'static Lint, &'static str, Span) {
|
||||||
match self {
|
match self {
|
||||||
Source::Item { item } | Source::Assoc { item, .. } => (
|
Self::Item { item } | Self::Assoc { item, .. } => (
|
||||||
DECLARE_INTERIOR_MUTABLE_CONST,
|
DECLARE_INTERIOR_MUTABLE_CONST,
|
||||||
"a const item should never be interior mutable",
|
"a const item should never be interior mutable",
|
||||||
*item,
|
*item,
|
||||||
),
|
),
|
||||||
Source::Expr { expr } => (
|
Self::Expr { expr } => (
|
||||||
BORROW_INTERIOR_MUTABLE_CONST,
|
BORROW_INTERIOR_MUTABLE_CONST,
|
||||||
"a const item with interior mutability should not be borrowed",
|
"a const item with interior mutability should not be borrowed",
|
||||||
*expr,
|
*expr,
|
||||||
|
|
|
@ -127,7 +127,7 @@ fn check_open_options(cx: &LateContext<'_, '_>, options: &[(OpenOption, Argument
|
||||||
} else {
|
} else {
|
||||||
create = true
|
create = true
|
||||||
}
|
}
|
||||||
create_arg = create_arg || (arg == Argument::True);;
|
create_arg = create_arg || (arg == Argument::True);
|
||||||
},
|
},
|
||||||
(OpenOption::Append, arg) => {
|
(OpenOption::Append, arg) => {
|
||||||
if append {
|
if append {
|
||||||
|
@ -140,7 +140,7 @@ fn check_open_options(cx: &LateContext<'_, '_>, options: &[(OpenOption, Argument
|
||||||
} else {
|
} else {
|
||||||
append = true
|
append = true
|
||||||
}
|
}
|
||||||
append_arg = append_arg || (arg == Argument::True);;
|
append_arg = append_arg || (arg == Argument::True);
|
||||||
},
|
},
|
||||||
(OpenOption::Truncate, arg) => {
|
(OpenOption::Truncate, arg) => {
|
||||||
if truncate {
|
if truncate {
|
||||||
|
@ -166,7 +166,7 @@ fn check_open_options(cx: &LateContext<'_, '_>, options: &[(OpenOption, Argument
|
||||||
} else {
|
} else {
|
||||||
read = true
|
read = true
|
||||||
}
|
}
|
||||||
read_arg = read_arg || (arg == Argument::True);;
|
read_arg = read_arg || (arg == Argument::True);
|
||||||
},
|
},
|
||||||
(OpenOption::Write, arg) => {
|
(OpenOption::Write, arg) => {
|
||||||
if write {
|
if write {
|
||||||
|
@ -179,7 +179,7 @@ fn check_open_options(cx: &LateContext<'_, '_>, options: &[(OpenOption, Argument
|
||||||
} else {
|
} else {
|
||||||
write = true
|
write = true
|
||||||
}
|
}
|
||||||
write_arg = write_arg || (arg == Argument::True);;
|
write_arg = write_arg || (arg == Argument::True);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,9 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// a + b < a
|
/// # let a = 1;
|
||||||
|
/// # let b = 2;
|
||||||
|
/// a + b < a;
|
||||||
/// ```
|
/// ```
|
||||||
pub OVERFLOW_CHECK_CONDITIONAL,
|
pub OVERFLOW_CHECK_CONDITIONAL,
|
||||||
complexity,
|
complexity,
|
||||||
|
|
|
@ -19,7 +19,7 @@ declare_clippy_lint! {
|
||||||
/// struct Foo;
|
/// struct Foo;
|
||||||
///
|
///
|
||||||
/// impl PartialEq for Foo {
|
/// impl PartialEq for Foo {
|
||||||
/// fn eq(&self, other: &Foo) -> bool { ... }
|
/// fn eq(&self, other: &Foo) -> bool { true }
|
||||||
/// fn ne(&self, other: &Foo) -> bool { !(self == other) }
|
/// fn ne(&self, other: &Foo) -> bool { !(self == other) }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -133,8 +133,8 @@ enum Method {
|
||||||
impl Method {
|
impl Method {
|
||||||
fn suggestion(self) -> &'static str {
|
fn suggestion(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Method::Offset => "add",
|
Self::Offset => "add",
|
||||||
Method::WrappingOffset => "wrapping_add",
|
Self::WrappingOffset => "wrapping_add",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,8 +142,8 @@ impl Method {
|
||||||
impl fmt::Display for Method {
|
impl fmt::Display for Method {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Method::Offset => write!(f, "offset"),
|
Self::Offset => write!(f, "offset"),
|
||||||
Method::WrappingOffset => write!(f, "wrapping_offset"),
|
Self::WrappingOffset => write!(f, "wrapping_offset"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// x.iter().zip(0..x.len())
|
/// # let x = vec![1];
|
||||||
|
/// x.iter().zip(0..x.len());
|
||||||
/// ```
|
/// ```
|
||||||
pub RANGE_ZIP_WITH_LEN,
|
pub RANGE_ZIP_WITH_LEN,
|
||||||
complexity,
|
complexity,
|
||||||
|
@ -60,7 +61,7 @@ declare_clippy_lint! {
|
||||||
/// I.e., `let _ = (f()+1)..(f()+1)` results in `let _ = ((f()+1)..=f())`.
|
/// I.e., `let _ = (f()+1)..(f()+1)` results in `let _ = ((f()+1)..=f())`.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// for x..(y+1) { .. }
|
/// for x..(y+1) { .. }
|
||||||
/// ```
|
/// ```
|
||||||
pub RANGE_PLUS_ONE,
|
pub RANGE_PLUS_ONE,
|
||||||
|
@ -78,7 +79,7 @@ declare_clippy_lint! {
|
||||||
/// **Known problems:** None.
|
/// **Known problems:** None.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// for x..=(y-1) { .. }
|
/// for x..=(y-1) { .. }
|
||||||
/// ```
|
/// ```
|
||||||
pub RANGE_MINUS_ONE,
|
pub RANGE_MINUS_ONE,
|
||||||
|
|
|
@ -40,6 +40,7 @@ declare_clippy_lint! {
|
||||||
/// * False-positive if there is a borrow preventing the value from moving out.
|
/// * False-positive if there is a borrow preventing the value from moving out.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # fn foo(x: String) {}
|
||||||
/// let x = String::new();
|
/// let x = String::new();
|
||||||
///
|
///
|
||||||
/// let y = &x;
|
/// let y = &x;
|
||||||
|
@ -49,15 +50,22 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # use std::path::Path;
|
||||||
|
/// # #[derive(Clone)]
|
||||||
|
/// # struct Foo;
|
||||||
|
/// # impl Foo {
|
||||||
|
/// # fn new() -> Self { Foo {} }
|
||||||
|
/// # }
|
||||||
|
/// # fn call(x: Foo) {}
|
||||||
/// {
|
/// {
|
||||||
/// let x = Foo::new();
|
/// let x = Foo::new();
|
||||||
/// call(x.clone());
|
/// call(x.clone());
|
||||||
/// call(x.clone()); // this can just pass `x`
|
/// call(x.clone()); // this can just pass `x`
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// ["lorem", "ipsum"].join(" ").to_string()
|
/// ["lorem", "ipsum"].join(" ").to_string();
|
||||||
///
|
///
|
||||||
/// Path::new("/a/b").join("c").to_path_buf()
|
/// Path::new("/a/b").join("c").to_path_buf();
|
||||||
/// ```
|
/// ```
|
||||||
pub REDUNDANT_CLONE,
|
pub REDUNDANT_CLONE,
|
||||||
nursery,
|
nursery,
|
||||||
|
@ -132,7 +140,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone {
|
||||||
let pred_arg = if_chain! {
|
let pred_arg = if_chain! {
|
||||||
if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, Some(res))) =
|
if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, Some(res))) =
|
||||||
is_call_with_ref_arg(cx, mir, &pred_terminator.kind);
|
is_call_with_ref_arg(cx, mir, &pred_terminator.kind);
|
||||||
if *res == mir::Place::Base(mir::PlaceBase::Local(cloned));
|
if res.base == mir::PlaceBase::Local(cloned);
|
||||||
if match_def_path(cx, pred_fn_def_id, &paths::DEREF_TRAIT_METHOD);
|
if match_def_path(cx, pred_fn_def_id, &paths::DEREF_TRAIT_METHOD);
|
||||||
if match_type(cx, pred_arg_ty, &paths::PATH_BUF)
|
if match_type(cx, pred_arg_ty, &paths::PATH_BUF)
|
||||||
|| match_type(cx, pred_arg_ty, &paths::OS_STRING);
|
|| match_type(cx, pred_arg_ty, &paths::OS_STRING);
|
||||||
|
@ -218,7 +226,7 @@ fn is_call_with_ref_arg<'tcx>(
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let TerminatorKind::Call { func, args, destination, .. } = kind;
|
if let TerminatorKind::Call { func, args, destination, .. } = kind;
|
||||||
if args.len() == 1;
|
if args.len() == 1;
|
||||||
if let mir::Operand::Move(mir::Place::Base(mir::PlaceBase::Local(local))) = &args[0];
|
if let mir::Operand::Move(mir::Place { base: mir::PlaceBase::Local(local), .. }) = &args[0];
|
||||||
if let ty::FnDef(def_id, _) = func.ty(&*mir, cx.tcx).sty;
|
if let ty::FnDef(def_id, _) = func.ty(&*mir, cx.tcx).sty;
|
||||||
if let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(&*mir, cx.tcx));
|
if let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(&*mir, cx.tcx));
|
||||||
if !is_copy(cx, inner_ty);
|
if !is_copy(cx, inner_ty);
|
||||||
|
@ -244,7 +252,14 @@ fn find_stmt_assigns_to<'a, 'tcx: 'a>(
|
||||||
stmts
|
stmts
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|stmt| {
|
.find_map(|stmt| {
|
||||||
if let mir::StatementKind::Assign(mir::Place::Base(mir::PlaceBase::Local(local)), v) = &stmt.kind {
|
if let mir::StatementKind::Assign(
|
||||||
|
mir::Place {
|
||||||
|
base: mir::PlaceBase::Local(local),
|
||||||
|
..
|
||||||
|
},
|
||||||
|
v,
|
||||||
|
) = &stmt.kind
|
||||||
|
{
|
||||||
if *local == to {
|
if *local == to {
|
||||||
return Some(v);
|
return Some(v);
|
||||||
}
|
}
|
||||||
|
@ -271,28 +286,34 @@ fn find_stmt_assigns_to<'a, 'tcx: 'a>(
|
||||||
fn base_local_and_movability<'tcx>(
|
fn base_local_and_movability<'tcx>(
|
||||||
cx: &LateContext<'_, 'tcx>,
|
cx: &LateContext<'_, 'tcx>,
|
||||||
mir: &mir::Body<'tcx>,
|
mir: &mir::Body<'tcx>,
|
||||||
mut place: &mir::Place<'tcx>,
|
place: &mir::Place<'tcx>,
|
||||||
) -> Option<(mir::Local, CannotMoveOut)> {
|
) -> Option<(mir::Local, CannotMoveOut)> {
|
||||||
use rustc::mir::Place::*;
|
use rustc::mir::Place;
|
||||||
use rustc::mir::PlaceBase;
|
use rustc::mir::PlaceBase;
|
||||||
|
use rustc::mir::PlaceRef;
|
||||||
|
use rustc::mir::Projection;
|
||||||
|
|
||||||
// Dereference. You cannot move things out from a borrowed value.
|
// Dereference. You cannot move things out from a borrowed value.
|
||||||
let mut deref = false;
|
let mut deref = false;
|
||||||
// Accessing a field of an ADT that has `Drop`. Moving the field out will cause E0509.
|
// Accessing a field of an ADT that has `Drop`. Moving the field out will cause E0509.
|
||||||
let mut field = false;
|
let mut field = false;
|
||||||
|
|
||||||
loop {
|
let PlaceRef {
|
||||||
match place {
|
base: place_base,
|
||||||
Base(PlaceBase::Local(local)) => return Some((*local, deref || field)),
|
mut projection,
|
||||||
Projection(proj) => {
|
} = place.as_ref();
|
||||||
place = &proj.base;
|
if let PlaceBase::Local(local) = place_base {
|
||||||
deref = deref || matches!(proj.elem, mir::ProjectionElem::Deref);
|
while let Some(box Projection { base, elem }) = projection {
|
||||||
if !field && matches!(proj.elem, mir::ProjectionElem::Field(..)) {
|
projection = base;
|
||||||
field = has_drop(cx, place.ty(&mir.local_decls, cx.tcx).ty);
|
deref = matches!(elem, mir::ProjectionElem::Deref);
|
||||||
}
|
field = !field
|
||||||
},
|
&& matches!(elem, mir::ProjectionElem::Field(..))
|
||||||
_ => return None,
|
&& has_drop(cx, Place::ty_from(place_base, projection, &mir.local_decls, cx.tcx).ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some((*local, deref || field))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,8 @@ impl EarlyLintPass for RedundantStaticLifetimes {
|
||||||
if !in_macro_or_desugar(item.span) {
|
if !in_macro_or_desugar(item.span) {
|
||||||
if let ItemKind::Const(ref var_type, _) = item.node {
|
if let ItemKind::Const(ref var_type, _) = item.node {
|
||||||
self.visit_type(var_type, cx, "Constants have by default a `'static` lifetime");
|
self.visit_type(var_type, cx, "Constants have by default a `'static` lifetime");
|
||||||
// Don't check associated consts because `'static` cannot be elided on those (issue #2438)
|
// Don't check associated consts because `'static` cannot be elided on those (issue
|
||||||
|
// #2438)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let ItemKind::Static(ref var_type, _, _) = item.node {
|
if let ItemKind::Static(ref var_type, _, _) = item.node {
|
||||||
|
|
|
@ -15,7 +15,7 @@ declare_clippy_lint! {
|
||||||
/// the suggested fix for `x = **&&y` is `x = *&y`, which is still incorrect.
|
/// the suggested fix for `x = **&&y` is `x = *&y`, which is still incorrect.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// let a = f(*&mut b);
|
/// let a = f(*&mut b);
|
||||||
/// let c = *&d;
|
/// let c = *&d;
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -64,8 +64,8 @@ declare_clippy_lint! {
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// struct Point(u32, u32);
|
/// struct Point(u32, u32);
|
||||||
/// let point = Foo(30, 20);
|
/// let point = Point(30, 20);
|
||||||
/// let x = (&point).x;
|
/// let x = (&point).0;
|
||||||
/// ```
|
/// ```
|
||||||
pub REF_IN_DEREF,
|
pub REF_IN_DEREF,
|
||||||
complexity,
|
complexity,
|
||||||
|
|
|
@ -16,12 +16,14 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # use core::sync::atomic::{ATOMIC_ISIZE_INIT, AtomicIsize};
|
||||||
/// static FOO: AtomicIsize = ATOMIC_ISIZE_INIT;
|
/// static FOO: AtomicIsize = ATOMIC_ISIZE_INIT;
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Could be written:
|
/// Could be written:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # use core::sync::atomic::AtomicIsize;
|
||||||
/// static FOO: AtomicIsize = AtomicIsize::new(0);
|
/// static FOO: AtomicIsize = AtomicIsize::new(0);
|
||||||
/// ```
|
/// ```
|
||||||
pub REPLACE_CONSTS,
|
pub REPLACE_CONSTS,
|
||||||
|
|
|
@ -86,7 +86,7 @@ declare_clippy_lint! {
|
||||||
#[derive(PartialEq, Eq, Copy, Clone)]
|
#[derive(PartialEq, Eq, Copy, Clone)]
|
||||||
enum RetReplacement {
|
enum RetReplacement {
|
||||||
Empty,
|
Empty,
|
||||||
Unit,
|
Block,
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_lint_pass!(Return => [NEEDLESS_RETURN, LET_AND_RETURN, UNUSED_UNIT]);
|
declare_lint_pass!(Return => [NEEDLESS_RETURN, LET_AND_RETURN, UNUSED_UNIT]);
|
||||||
|
@ -139,7 +139,7 @@ impl Return {
|
||||||
// a match expr, check all arms
|
// a match expr, check all arms
|
||||||
ast::ExprKind::Match(_, ref arms) => {
|
ast::ExprKind::Match(_, ref arms) => {
|
||||||
for arm in arms {
|
for arm in arms {
|
||||||
self.check_final_expr(cx, &arm.body, Some(arm.body.span), RetReplacement::Unit);
|
self.check_final_expr(cx, &arm.body, Some(arm.body.span), RetReplacement::Block);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -176,12 +176,12 @@ impl Return {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
RetReplacement::Unit => {
|
RetReplacement::Block => {
|
||||||
span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded return statement", |db| {
|
span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded return statement", |db| {
|
||||||
db.span_suggestion(
|
db.span_suggestion(
|
||||||
ret_span,
|
ret_span,
|
||||||
"replace `return` with the unit type",
|
"replace `return` with an empty block",
|
||||||
"()".to_string(),
|
"{}".to_string(),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -317,7 +317,7 @@ fn attr_is_cfg(attr: &ast::Attribute) -> bool {
|
||||||
|
|
||||||
// get the def site
|
// get the def site
|
||||||
fn get_def(span: Span) -> Option<Span> {
|
fn get_def(span: Span) -> Option<Span> {
|
||||||
span.ctxt().outer_expn_info().and_then(|info| info.def_site)
|
span.ctxt().outer_expn_info().and_then(|info| Some(info.def_site))
|
||||||
}
|
}
|
||||||
|
|
||||||
// is this expr a `()` unit?
|
// is this expr a `()` unit?
|
||||||
|
|
|
@ -20,6 +20,7 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # let x = 1;
|
||||||
/// let x = &x;
|
/// let x = &x;
|
||||||
/// ```
|
/// ```
|
||||||
pub SHADOW_SAME,
|
pub SHADOW_SAME,
|
||||||
|
@ -41,10 +42,12 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// let x = 2;
|
||||||
/// let x = x + 1;
|
/// let x = x + 1;
|
||||||
/// ```
|
/// ```
|
||||||
/// use different variable name:
|
/// use different variable name:
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// let x = 2;
|
||||||
/// let y = x + 1;
|
/// let y = x + 1;
|
||||||
/// ```
|
/// ```
|
||||||
pub SHADOW_REUSE,
|
pub SHADOW_REUSE,
|
||||||
|
@ -67,6 +70,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # let y = 1;
|
||||||
|
/// # let z = 2;
|
||||||
/// let x = y;
|
/// let x = y;
|
||||||
/// let x = z; // shadows the earlier binding
|
/// let x = z; // shadows the earlier binding
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -19,6 +19,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # use core::iter::repeat;
|
||||||
|
/// # let len = 4;
|
||||||
/// let mut vec1 = Vec::with_capacity(len);
|
/// let mut vec1 = Vec::with_capacity(len);
|
||||||
/// vec1.resize(len, 0);
|
/// vec1.resize(len, 0);
|
||||||
///
|
///
|
||||||
|
|
|
@ -48,7 +48,7 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let x = "Hello".to_owned();
|
/// let x = "Hello".to_owned();
|
||||||
/// x + ", World"
|
/// x + ", World";
|
||||||
/// ```
|
/// ```
|
||||||
pub STRING_ADD,
|
pub STRING_ADD,
|
||||||
restriction,
|
restriction,
|
||||||
|
@ -138,6 +138,9 @@ fn is_add(cx: &LateContext<'_, '_>, src: &Expr, target: &Expr) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Max length a b"foo" string can take
|
||||||
|
const MAX_LENGTH_BYTE_STRING_LIT: usize = 32;
|
||||||
|
|
||||||
declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES]);
|
declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES]);
|
||||||
|
|
||||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes {
|
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes {
|
||||||
|
@ -173,6 +176,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes {
|
||||||
);
|
);
|
||||||
} else if callsite == expanded
|
} else if callsite == expanded
|
||||||
&& lit_content.as_str().chars().all(|c| c.is_ascii())
|
&& lit_content.as_str().chars().all(|c| c.is_ascii())
|
||||||
|
&& lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT
|
||||||
&& !in_macro_or_desugar(args[0].span)
|
&& !in_macro_or_desugar(args[0].span)
|
||||||
{
|
{
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
|
|
|
@ -20,12 +20,17 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// let mut a = 42;
|
||||||
|
/// let mut b = 1337;
|
||||||
|
///
|
||||||
/// let t = b;
|
/// let t = b;
|
||||||
/// b = a;
|
/// b = a;
|
||||||
/// a = t;
|
/// a = t;
|
||||||
/// ```
|
/// ```
|
||||||
/// Use std::mem::swap():
|
/// Use std::mem::swap():
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// let mut a = 1;
|
||||||
|
/// let mut b = 2;
|
||||||
/// std::mem::swap(&mut a, &mut b);
|
/// std::mem::swap(&mut a, &mut b);
|
||||||
/// ```
|
/// ```
|
||||||
pub MANUAL_SWAP,
|
pub MANUAL_SWAP,
|
||||||
|
|
77
clippy_lints/src/trait_bounds.rs
Normal file
77
clippy_lints/src/trait_bounds.rs
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
use crate::utils::{in_macro, snippet, span_help_and_lint, SpanlessHash};
|
||||||
|
use rustc::hir::*;
|
||||||
|
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||||
|
use rustc::{declare_tool_lint, impl_lint_pass};
|
||||||
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct TraitBounds;
|
||||||
|
|
||||||
|
declare_clippy_lint! {
|
||||||
|
/// **What it does:** This lint warns about unnecessary type repetitions in trait bounds
|
||||||
|
///
|
||||||
|
/// **Why is this bad?** Repeating the type for every bound makes the code
|
||||||
|
/// less readable than combining the bounds
|
||||||
|
///
|
||||||
|
/// **Example:**
|
||||||
|
/// ```rust
|
||||||
|
/// pub fn foo<T>(t: T) where T: Copy, T: Clone {}
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Could be written as:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// pub fn foo<T>(t: T) where T: Copy + Clone {}
|
||||||
|
/// ```
|
||||||
|
pub TYPE_REPETITION_IN_BOUNDS,
|
||||||
|
complexity,
|
||||||
|
"Types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`"
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_lint_pass!(TraitBounds => [TYPE_REPETITION_IN_BOUNDS]);
|
||||||
|
|
||||||
|
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TraitBounds {
|
||||||
|
fn check_generics(&mut self, cx: &LateContext<'a, 'tcx>, gen: &'tcx Generics) {
|
||||||
|
if in_macro(gen.span) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let hash = |ty| -> u64 {
|
||||||
|
let mut hasher = SpanlessHash::new(cx, cx.tables);
|
||||||
|
hasher.hash_ty(ty);
|
||||||
|
hasher.finish()
|
||||||
|
};
|
||||||
|
let mut map = FxHashMap::default();
|
||||||
|
for bound in &gen.where_clause.predicates {
|
||||||
|
if let WherePredicate::BoundPredicate(ref p) = bound {
|
||||||
|
let h = hash(&p.bounded_ty);
|
||||||
|
if let Some(ref v) = map.insert(h, p.bounds.iter().collect::<Vec<_>>()) {
|
||||||
|
let mut hint_string = format!(
|
||||||
|
"consider combining the bounds: `{}:",
|
||||||
|
snippet(cx, p.bounded_ty.span, "_")
|
||||||
|
);
|
||||||
|
for b in v.iter() {
|
||||||
|
if let GenericBound::Trait(ref poly_trait_ref, _) = b {
|
||||||
|
let path = &poly_trait_ref.trait_ref.path;
|
||||||
|
hint_string.push_str(&format!(" {} +", path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for b in p.bounds.iter() {
|
||||||
|
if let GenericBound::Trait(ref poly_trait_ref, _) = b {
|
||||||
|
let path = &poly_trait_ref.trait_ref.path;
|
||||||
|
hint_string.push_str(&format!(" {} +", path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hint_string.truncate(hint_string.len() - 2);
|
||||||
|
hint_string.push('`');
|
||||||
|
span_help_and_lint(
|
||||||
|
cx,
|
||||||
|
TYPE_REPETITION_IN_BOUNDS,
|
||||||
|
p.span,
|
||||||
|
"this type has already been used as a bound predicate",
|
||||||
|
&hint_string,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,8 +36,8 @@ declare_clippy_lint! {
|
||||||
/// **Known problems:** None.
|
/// **Known problems:** None.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// core::intrinsics::transmute(t) // where the result type is the same as `t`'s
|
/// core::intrinsics::transmute(t); // where the result type is the same as `t`'s
|
||||||
/// ```
|
/// ```
|
||||||
pub USELESS_TRANSMUTE,
|
pub USELESS_TRANSMUTE,
|
||||||
complexity,
|
complexity,
|
||||||
|
@ -53,7 +53,7 @@ declare_clippy_lint! {
|
||||||
/// **Known problems:** None.
|
/// **Known problems:** None.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// core::intrinsics::transmute(t) // where the result type is the same as
|
/// core::intrinsics::transmute(t) // where the result type is the same as
|
||||||
/// // `*t` or `&t`'s
|
/// // `*t` or `&t`'s
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -70,8 +70,10 @@ declare_clippy_lint! {
|
||||||
/// **Known problems:** None.
|
/// **Known problems:** None.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
|
/// unsafe {
|
||||||
/// let _: &T = std::mem::transmute(p); // where p: *const T
|
/// let _: &T = std::mem::transmute(p); // where p: *const T
|
||||||
|
/// }
|
||||||
///
|
///
|
||||||
/// // can be written:
|
/// // can be written:
|
||||||
/// let _: &T = &*p;
|
/// let _: &T = &*p;
|
||||||
|
@ -99,7 +101,10 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// let x = 1_u32;
|
||||||
|
/// unsafe {
|
||||||
/// let _: char = std::mem::transmute(x); // where x: u32
|
/// let _: char = std::mem::transmute(x); // where x: u32
|
||||||
|
/// }
|
||||||
///
|
///
|
||||||
/// // should be:
|
/// // should be:
|
||||||
/// let _ = std::char::from_u32(x).unwrap();
|
/// let _ = std::char::from_u32(x).unwrap();
|
||||||
|
@ -127,7 +132,10 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// let b: &[u8] = &[1_u8, 2_u8];
|
||||||
|
/// unsafe {
|
||||||
/// let _: &str = std::mem::transmute(b); // where b: &[u8]
|
/// let _: &str = std::mem::transmute(b); // where b: &[u8]
|
||||||
|
/// }
|
||||||
///
|
///
|
||||||
/// // should be:
|
/// // should be:
|
||||||
/// let _ = std::str::from_utf8(b).unwrap();
|
/// let _ = std::str::from_utf8(b).unwrap();
|
||||||
|
@ -146,7 +154,10 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// let x = 1_u8;
|
||||||
|
/// unsafe {
|
||||||
/// let _: bool = std::mem::transmute(x); // where x: u8
|
/// let _: bool = std::mem::transmute(x); // where x: u8
|
||||||
|
/// }
|
||||||
///
|
///
|
||||||
/// // should be:
|
/// // should be:
|
||||||
/// let _: bool = x != 0;
|
/// let _: bool = x != 0;
|
||||||
|
@ -166,10 +177,12 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let _: f32 = std::mem::transmute(x); // where x: u32
|
/// unsafe {
|
||||||
|
/// let _: f32 = std::mem::transmute(1_u32); // where x: u32
|
||||||
|
/// }
|
||||||
///
|
///
|
||||||
/// // should be:
|
/// // should be:
|
||||||
/// let _: f32 = f32::from_bits(x);
|
/// let _: f32 = f32::from_bits(1_u32);
|
||||||
/// ```
|
/// ```
|
||||||
pub TRANSMUTE_INT_TO_FLOAT,
|
pub TRANSMUTE_INT_TO_FLOAT,
|
||||||
complexity,
|
complexity,
|
||||||
|
@ -195,7 +208,7 @@ declare_clippy_lint! {
|
||||||
/// let _: &f32 = std::mem::transmute(&1u32);
|
/// let _: &f32 = std::mem::transmute(&1u32);
|
||||||
/// }
|
/// }
|
||||||
/// // These can be respectively written:
|
/// // These can be respectively written:
|
||||||
/// let _ = ptr as *const f32
|
/// let _ = ptr as *const f32;
|
||||||
/// let _ = unsafe{ &*(&1u32 as *const u32 as *const f32) };
|
/// let _ = unsafe{ &*(&1u32 as *const u32 as *const f32) };
|
||||||
/// ```
|
/// ```
|
||||||
pub TRANSMUTE_PTR_TO_PTR,
|
pub TRANSMUTE_PTR_TO_PTR,
|
||||||
|
|
|
@ -39,14 +39,15 @@ declare_clippy_lint! {
|
||||||
/// each other.
|
/// each other.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// fn foo(v: &u32) {
|
/// // Bad
|
||||||
/// assert_eq!(v, 42);
|
/// fn foo(v: &u32) {}
|
||||||
/// }
|
/// ```
|
||||||
/// // should be
|
///
|
||||||
/// fn foo(v: u32) {
|
/// ```rust
|
||||||
/// assert_eq!(v, 42);
|
/// // Better
|
||||||
/// }
|
/// fn foo(v: u32) {}
|
||||||
/// ```
|
/// ```
|
||||||
pub TRIVIALLY_COPY_PASS_BY_REF,
|
pub TRIVIALLY_COPY_PASS_BY_REF,
|
||||||
perf,
|
perf,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::utils::{match_qpath, paths, snippet, span_lint_and_sugg};
|
use crate::utils::{in_macro_or_desugar, match_qpath, paths, snippet, snippet_with_macro_callsite, span_lint_and_sugg};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||||
|
@ -67,10 +67,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TryErr {
|
||||||
|
|
||||||
then {
|
then {
|
||||||
let err_type = cx.tables.expr_ty(err_arg);
|
let err_type = cx.tables.expr_ty(err_arg);
|
||||||
let suggestion = if err_type == return_type {
|
let origin_snippet = if in_macro_or_desugar(err_arg.span) {
|
||||||
format!("return Err({})", snippet(cx, err_arg.span, "_"))
|
snippet_with_macro_callsite(cx, err_arg.span, "_")
|
||||||
} else {
|
} else {
|
||||||
format!("return Err({}.into())", snippet(cx, err_arg.span, "_"))
|
snippet(cx, err_arg.span, "_")
|
||||||
|
};
|
||||||
|
let suggestion = if err_type == return_type {
|
||||||
|
format!("return Err({})", origin_snippet)
|
||||||
|
} else {
|
||||||
|
format!("return Err({}.into())", origin_snippet)
|
||||||
};
|
};
|
||||||
|
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
|
|
|
@ -25,7 +25,7 @@ use crate::utils::paths;
|
||||||
use crate::utils::{
|
use crate::utils::{
|
||||||
clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro_or_desugar, int_bits, last_path_segment,
|
clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro_or_desugar, int_bits, last_path_segment,
|
||||||
match_def_path, match_path, multispan_sugg, same_tys, sext, snippet, snippet_opt, snippet_with_applicability,
|
match_def_path, match_path, multispan_sugg, same_tys, sext, snippet, snippet_opt, snippet_with_applicability,
|
||||||
span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext,
|
snippet_with_macro_callsite, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext,
|
||||||
};
|
};
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
|
@ -133,7 +133,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let x = LinkedList::new();
|
/// # use std::collections::LinkedList;
|
||||||
|
/// let x: LinkedList<usize> = LinkedList::new();
|
||||||
/// ```
|
/// ```
|
||||||
pub LINKEDLIST,
|
pub LINKEDLIST,
|
||||||
pedantic,
|
pedantic,
|
||||||
|
@ -467,16 +468,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnitValue {
|
||||||
if higher::is_from_for_desugar(local) {
|
if higher::is_from_for_desugar(local) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
span_lint(
|
span_lint_and_then(cx, LET_UNIT_VALUE, stmt.span, "this let-binding has unit value", |db| {
|
||||||
cx,
|
if let Some(expr) = &local.init {
|
||||||
LET_UNIT_VALUE,
|
let snip = snippet_with_macro_callsite(cx, expr.span, "()");
|
||||||
|
db.span_suggestion(
|
||||||
stmt.span,
|
stmt.span,
|
||||||
&format!(
|
"omit the `let` binding",
|
||||||
"this let-binding has unit value. Consider omitting `let {} =`",
|
format!("{};", snip),
|
||||||
snippet(cx, local.pat.span, "..")
|
Applicability::MachineApplicable, // snippet
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -557,7 +560,7 @@ declare_clippy_lint! {
|
||||||
/// **Known problems:** None.
|
/// **Known problems:** None.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// foo({
|
/// foo({
|
||||||
/// let a = bar();
|
/// let a = bar();
|
||||||
/// baz(a);
|
/// baz(a);
|
||||||
|
@ -621,9 +624,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_questionmark_desugar_marked_call(expr: &Expr) -> bool {
|
fn is_questionmark_desugar_marked_call(expr: &Expr) -> bool {
|
||||||
use syntax_pos::hygiene::CompilerDesugaringKind;
|
use syntax_pos::hygiene::DesugaringKind;
|
||||||
if let ExprKind::Call(ref callee, _) = expr.node {
|
if let ExprKind::Call(ref callee, _) = expr.node {
|
||||||
callee.span.is_compiler_desugaring(CompilerDesugaringKind::QuestionMark)
|
callee.span.is_desugaring(DesugaringKind::QuestionMark)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -660,8 +663,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let x = u64::MAX;
|
/// let x = std::u64::MAX;
|
||||||
/// x as f64
|
/// x as f64;
|
||||||
/// ```
|
/// ```
|
||||||
pub CAST_PRECISION_LOSS,
|
pub CAST_PRECISION_LOSS,
|
||||||
pedantic,
|
pedantic,
|
||||||
|
@ -682,7 +685,7 @@ declare_clippy_lint! {
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let y: i8 = -1;
|
/// let y: i8 = -1;
|
||||||
/// y as u128 // will return 18446744073709551615
|
/// y as u128; // will return 18446744073709551615
|
||||||
/// ```
|
/// ```
|
||||||
pub CAST_SIGN_LOSS,
|
pub CAST_SIGN_LOSS,
|
||||||
pedantic,
|
pedantic,
|
||||||
|
@ -690,7 +693,7 @@ declare_clippy_lint! {
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// **What it does:** Checks for on casts between numerical types that may
|
/// **What it does:** Checks for casts between numerical types that may
|
||||||
/// truncate large values. This is expected behavior, so the cast is `Allow` by
|
/// truncate large values. This is expected behavior, so the cast is `Allow` by
|
||||||
/// default.
|
/// default.
|
||||||
///
|
///
|
||||||
|
@ -727,7 +730,7 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// u32::MAX as i32 // will yield a value of `-1`
|
/// std::u32::MAX as i32; // will yield a value of `-1`
|
||||||
/// ```
|
/// ```
|
||||||
pub CAST_POSSIBLE_WRAP,
|
pub CAST_POSSIBLE_WRAP,
|
||||||
pedantic,
|
pedantic,
|
||||||
|
@ -735,7 +738,7 @@ declare_clippy_lint! {
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// **What it does:** Checks for on casts between numerical types that may
|
/// **What it does:** Checks for casts between numerical types that may
|
||||||
/// be replaced by safe conversion functions.
|
/// be replaced by safe conversion functions.
|
||||||
///
|
///
|
||||||
/// **Why is this bad?** Rust's `as` keyword will perform many kinds of
|
/// **Why is this bad?** Rust's `as` keyword will perform many kinds of
|
||||||
|
@ -775,7 +778,7 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let _ = 2i32 as i32
|
/// let _ = 2i32 as i32;
|
||||||
/// ```
|
/// ```
|
||||||
pub UNNECESSARY_CAST,
|
pub UNNECESSARY_CAST,
|
||||||
complexity,
|
complexity,
|
||||||
|
@ -789,7 +792,8 @@ declare_clippy_lint! {
|
||||||
/// **Why is this bad?** Dereferencing the resulting pointer may be undefined
|
/// **Why is this bad?** Dereferencing the resulting pointer may be undefined
|
||||||
/// behavior.
|
/// behavior.
|
||||||
///
|
///
|
||||||
/// **Known problems:** None.
|
/// **Known problems:** Using `std::ptr::read_unaligned` and `std::ptr::write_unaligned` or similar
|
||||||
|
/// on the resulting pointer is fine.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
@ -1210,17 +1214,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Casts {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let ty::RawPtr(from_ptr_ty) = &cast_from.sty;
|
if let ty::RawPtr(from_ptr_ty) = &cast_from.sty;
|
||||||
if let ty::RawPtr(to_ptr_ty) = &cast_to.sty;
|
if let ty::RawPtr(to_ptr_ty) = &cast_to.sty;
|
||||||
if let Some(from_align) = cx.layout_of(from_ptr_ty.ty).ok().map(|a| a.align.abi);
|
if let Ok(from_layout) = cx.layout_of(from_ptr_ty.ty);
|
||||||
if let Some(to_align) = cx.layout_of(to_ptr_ty.ty).ok().map(|a| a.align.abi);
|
if let Ok(to_layout) = cx.layout_of(to_ptr_ty.ty);
|
||||||
if from_align < to_align;
|
if from_layout.align.abi < to_layout.align.abi;
|
||||||
// with c_void, we inherently need to trust the user
|
// with c_void, we inherently need to trust the user
|
||||||
if !is_c_void(cx, from_ptr_ty.ty);
|
if !is_c_void(cx, from_ptr_ty.ty);
|
||||||
|
// when casting from a ZST, we don't know enough to properly lint
|
||||||
|
if !from_layout.is_zst();
|
||||||
then {
|
then {
|
||||||
span_lint(
|
span_lint(
|
||||||
cx,
|
cx,
|
||||||
CAST_PTR_ALIGNMENT,
|
CAST_PTR_ALIGNMENT,
|
||||||
expr.span,
|
expr.span,
|
||||||
&format!("casting from `{}` to a more-strictly-aligned pointer (`{}`)", cast_from, cast_to)
|
&format!(
|
||||||
|
"casting from `{}` to a more-strictly-aligned pointer (`{}`) ({} < {} bytes)",
|
||||||
|
cast_from,
|
||||||
|
cast_to,
|
||||||
|
from_layout.align.abi.bytes(),
|
||||||
|
to_layout.align.abi.bytes(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1242,7 +1254,7 @@ fn lint_fn_to_numeric_cast(
|
||||||
}
|
}
|
||||||
match cast_from.sty {
|
match cast_from.sty {
|
||||||
ty::FnDef(..) | ty::FnPtr(_) => {
|
ty::FnDef(..) | ty::FnPtr(_) => {
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MaybeIncorrect;
|
||||||
let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability);
|
let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability);
|
||||||
|
|
||||||
let to_nbits = int_ty_to_nbits(cast_to, cx.tcx);
|
let to_nbits = int_ty_to_nbits(cast_to, cx.tcx);
|
||||||
|
@ -1286,6 +1298,7 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # use std::rc::Rc;
|
||||||
/// struct Foo {
|
/// struct Foo {
|
||||||
/// inner: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>>,
|
/// inner: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>>,
|
||||||
/// }
|
/// }
|
||||||
|
@ -1344,7 +1357,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexity {
|
||||||
|
|
||||||
fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) {
|
fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) {
|
||||||
match item.node {
|
match item.node {
|
||||||
ImplItemKind::Const(ref ty, _) | ImplItemKind::Type(ref ty) => self.check_type(cx, ty),
|
ImplItemKind::Const(ref ty, _) | ImplItemKind::TyAlias(ref ty) => self.check_type(cx, ty),
|
||||||
// methods are covered by check_fn
|
// methods are covered by check_fn
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
@ -1449,13 +1462,13 @@ declare_clippy_lint! {
|
||||||
/// **Known problems:** None.
|
/// **Known problems:** None.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// 'x' as u8
|
/// 'x' as u8
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// A better version, using the byte literal:
|
/// A better version, using the byte literal:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// b'x'
|
/// b'x'
|
||||||
/// ```
|
/// ```
|
||||||
pub CHAR_LIT_AS_U8,
|
pub CHAR_LIT_AS_U8,
|
||||||
|
@ -1679,7 +1692,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let x : u8 = ...; (x as u32) > 300
|
/// let x: u8 = 1;
|
||||||
|
/// (x as u32) > 300;
|
||||||
/// ```
|
/// ```
|
||||||
pub INVALID_UPCAST_COMPARISONS,
|
pub INVALID_UPCAST_COMPARISONS,
|
||||||
pedantic,
|
pedantic,
|
||||||
|
@ -1716,10 +1730,10 @@ impl PartialEq for FullInt {
|
||||||
impl PartialOrd for FullInt {
|
impl PartialOrd for FullInt {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
Some(match (self, other) {
|
Some(match (self, other) {
|
||||||
(&FullInt::S(s), &FullInt::S(o)) => s.cmp(&o),
|
(&Self::S(s), &Self::S(o)) => s.cmp(&o),
|
||||||
(&FullInt::U(s), &FullInt::U(o)) => s.cmp(&o),
|
(&Self::U(s), &Self::U(o)) => s.cmp(&o),
|
||||||
(&FullInt::S(s), &FullInt::U(o)) => Self::cmp_s_u(s, o),
|
(&Self::S(s), &Self::U(o)) => Self::cmp_s_u(s, o),
|
||||||
(&FullInt::U(s), &FullInt::S(o)) => Self::cmp_s_u(o, s).reverse(),
|
(&Self::U(s), &Self::S(o)) => Self::cmp_s_u(o, s).reverse(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1914,12 +1928,21 @@ declare_clippy_lint! {
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use std::collections::HashMap;
|
/// # use std::collections::HashMap;
|
||||||
/// # use std::hash::Hash;
|
/// # use std::hash::{Hash, BuildHasher};
|
||||||
/// # trait Serialize {};
|
/// # trait Serialize {};
|
||||||
/// impl<K: Hash + Eq, V> Serialize for HashMap<K, V> { }
|
/// impl<K: Hash + Eq, V> Serialize for HashMap<K, V> { }
|
||||||
///
|
///
|
||||||
/// pub fn foo(map: &mut HashMap<i32, i32>) { }
|
/// pub fn foo(map: &mut HashMap<i32, i32>) { }
|
||||||
/// ```
|
/// ```
|
||||||
|
/// could be rewritten as
|
||||||
|
/// ```rust
|
||||||
|
/// # use std::collections::HashMap;
|
||||||
|
/// # use std::hash::{Hash, BuildHasher};
|
||||||
|
/// # trait Serialize {};
|
||||||
|
/// impl<K: Hash + Eq, V, S: BuildHasher> Serialize for HashMap<K, V, S> { }
|
||||||
|
///
|
||||||
|
/// pub fn foo<S: BuildHasher>(map: &mut HashMap<i32, i32, S>) { }
|
||||||
|
/// ```
|
||||||
pub IMPLICIT_HASHER,
|
pub IMPLICIT_HASHER,
|
||||||
style,
|
style,
|
||||||
"missing generalization over different hashers"
|
"missing generalization over different hashers"
|
||||||
|
@ -2029,6 +2052,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher {
|
||||||
vis.visit_ty(ty);
|
vis.visit_ty(ty);
|
||||||
|
|
||||||
for target in &vis.found {
|
for target in &vis.found {
|
||||||
|
if in_external_macro(cx.sess(), generics.span) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let generics_suggestion_span = generics.span.substitute_dummy({
|
let generics_suggestion_span = generics.span.substitute_dummy({
|
||||||
let pos = snippet_opt(cx, item.span.until(body.arguments[0].pat.span))
|
let pos = snippet_opt(cx, item.span.until(body.arguments[0].pat.span))
|
||||||
.and_then(|snip| {
|
.and_then(|snip| {
|
||||||
|
|
|
@ -14,10 +14,12 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Why is this bad?** Using `if let` or `match` is more idiomatic.
|
/// **Why is this bad?** Using `if let` or `match` is more idiomatic.
|
||||||
///
|
///
|
||||||
/// **Known problems:** Limitations of the borrow checker might make unwrap() necessary sometimes?
|
/// **Known problems:** None
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # let option = Some(0);
|
||||||
|
/// # fn do_something_with(_x: usize) {}
|
||||||
/// if option.is_some() {
|
/// if option.is_some() {
|
||||||
/// do_something_with(option.unwrap())
|
/// do_something_with(option.unwrap())
|
||||||
/// }
|
/// }
|
||||||
|
@ -26,12 +28,14 @@ declare_clippy_lint! {
|
||||||
/// Could be written:
|
/// Could be written:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # let option = Some(0);
|
||||||
|
/// # fn do_something_with(_x: usize) {}
|
||||||
/// if let Some(value) = option {
|
/// if let Some(value) = option {
|
||||||
/// do_something_with(value)
|
/// do_something_with(value)
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub UNNECESSARY_UNWRAP,
|
pub UNNECESSARY_UNWRAP,
|
||||||
nursery,
|
complexity,
|
||||||
"checks for calls of unwrap[_err]() that cannot fail"
|
"checks for calls of unwrap[_err]() that cannot fail"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +49,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # let option = Some(0);
|
||||||
|
/// # fn do_something_with(_x: usize) {}
|
||||||
/// if option.is_none() {
|
/// if option.is_none() {
|
||||||
/// do_something_with(option.unwrap())
|
/// do_something_with(option.unwrap())
|
||||||
/// }
|
/// }
|
||||||
|
@ -52,7 +58,7 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// This code will always panic. The if condition should probably be inverted.
|
/// This code will always panic. The if condition should probably be inverted.
|
||||||
pub PANICKING_UNWRAP,
|
pub PANICKING_UNWRAP,
|
||||||
nursery,
|
correctness,
|
||||||
"checks for calls of unwrap[_err]() that will always fail"
|
"checks for calls of unwrap[_err]() that will always fail"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,9 +51,11 @@ declare_lint_pass!(UseSelf => [USE_SELF]);
|
||||||
|
|
||||||
const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element";
|
const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element";
|
||||||
|
|
||||||
fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path) {
|
fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path, last_segment: Option<&PathSegment>) {
|
||||||
|
let last_segment = last_segment.unwrap_or_else(|| path.segments.last().expect(SEGMENTS_MSG));
|
||||||
|
|
||||||
// Path segments only include actual path, no methods or fields.
|
// Path segments only include actual path, no methods or fields.
|
||||||
let last_path_span = path.segments.last().expect(SEGMENTS_MSG).ident.span;
|
let last_path_span = last_segment.ident.span;
|
||||||
// Only take path up to the end of last_path_span.
|
// Only take path up to the end of last_path_span.
|
||||||
let span = path.span.with_hi(last_path_span.hi());
|
let span = path.span.with_hi(last_path_span.hi());
|
||||||
|
|
||||||
|
@ -80,22 +82,18 @@ impl<'a, 'tcx> Visitor<'tcx> for TraitImplTyVisitor<'a, 'tcx> {
|
||||||
let trait_ty = self.trait_type_walker.next();
|
let trait_ty = self.trait_type_walker.next();
|
||||||
let impl_ty = self.impl_type_walker.next();
|
let impl_ty = self.impl_type_walker.next();
|
||||||
|
|
||||||
if let TyKind::Path(QPath::Resolved(_, path)) = &t.node {
|
if_chain! {
|
||||||
|
if let TyKind::Path(QPath::Resolved(_, path)) = &t.node;
|
||||||
|
|
||||||
// The implementation and trait types don't match which means that
|
// The implementation and trait types don't match which means that
|
||||||
// the concrete type was specified by the implementation
|
// the concrete type was specified by the implementation
|
||||||
if impl_ty != trait_ty {
|
if impl_ty != trait_ty;
|
||||||
if let Some(impl_ty) = impl_ty {
|
if let Some(impl_ty) = impl_ty;
|
||||||
if self.item_type == impl_ty {
|
if self.item_type == impl_ty;
|
||||||
let is_self_ty = if let def::Res::SelfTy(..) = path.res {
|
then {
|
||||||
true
|
match path.res {
|
||||||
} else {
|
def::Res::SelfTy(..) => {},
|
||||||
false
|
_ => span_use_self_lint(self.cx, path, None)
|
||||||
};
|
|
||||||
|
|
||||||
if !is_self_ty {
|
|
||||||
span_use_self_lint(self.cx, path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,15 +218,34 @@ struct UseSelfVisitor<'a, 'tcx> {
|
||||||
|
|
||||||
impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> {
|
||||||
fn visit_path(&mut self, path: &'tcx Path, _id: HirId) {
|
fn visit_path(&mut self, path: &'tcx Path, _id: HirId) {
|
||||||
|
if path.segments.len() >= 2 {
|
||||||
|
let last_but_one = &path.segments[path.segments.len() - 2];
|
||||||
|
if last_but_one.ident.name != kw::SelfUpper {
|
||||||
|
let enum_def_id = match path.res {
|
||||||
|
Res::Def(DefKind::Variant, variant_def_id) => self.cx.tcx.parent(variant_def_id),
|
||||||
|
Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), ctor_def_id) => {
|
||||||
|
let variant_def_id = self.cx.tcx.parent(ctor_def_id);
|
||||||
|
variant_def_id.and_then(|def_id| self.cx.tcx.parent(def_id))
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.item_path.res.opt_def_id() == enum_def_id {
|
||||||
|
span_use_self_lint(self.cx, path, Some(last_but_one));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if path.segments.last().expect(SEGMENTS_MSG).ident.name != kw::SelfUpper {
|
if path.segments.last().expect(SEGMENTS_MSG).ident.name != kw::SelfUpper {
|
||||||
if self.item_path.res == path.res {
|
if self.item_path.res == path.res {
|
||||||
span_use_self_lint(self.cx, path);
|
span_use_self_lint(self.cx, path, None);
|
||||||
} else if let Res::Def(DefKind::Ctor(def::CtorOf::Struct, CtorKind::Fn), ctor_did) = path.res {
|
} else if let Res::Def(DefKind::Ctor(def::CtorOf::Struct, CtorKind::Fn), ctor_def_id) = path.res {
|
||||||
if self.item_path.res.opt_def_id() == self.cx.tcx.parent(ctor_did) {
|
if self.item_path.res.opt_def_id() == self.cx.tcx.parent(ctor_def_id) {
|
||||||
span_use_self_lint(self.cx, path);
|
span_use_self_lint(self.cx, path, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
walk_path(self, path);
|
walk_path(self, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ declare_clippy_lint! {
|
||||||
/// **What it does:** Generates clippy code that detects the offending pattern
|
/// **What it does:** Generates clippy code that detects the offending pattern
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// // ./tests/ui/my_lint.rs
|
/// // ./tests/ui/my_lint.rs
|
||||||
/// fn foo() {
|
/// fn foo() {
|
||||||
/// // detect the following pattern
|
/// // detect the following pattern
|
||||||
|
@ -24,13 +24,14 @@ declare_clippy_lint! {
|
||||||
/// // but ignore everything from here on
|
/// // but ignore everything from here on
|
||||||
/// #![clippy::author = "ignore"]
|
/// #![clippy::author = "ignore"]
|
||||||
/// }
|
/// }
|
||||||
|
/// ()
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Running `TESTNAME=ui/my_lint cargo uitest` will produce
|
/// Running `TESTNAME=ui/my_lint cargo uitest` will produce
|
||||||
/// a `./tests/ui/new_lint.stdout` file with the generated code:
|
/// a `./tests/ui/new_lint.stdout` file with the generated code:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// // ./tests/ui/new_lint.stdout
|
/// // ./tests/ui/new_lint.stdout
|
||||||
/// if_chain! {
|
/// if_chain! {
|
||||||
/// if let ExprKind::If(ref cond, ref then, None) = item.node,
|
/// if let ExprKind::If(ref cond, ref then, None) = item.node,
|
||||||
|
|
|
@ -44,15 +44,15 @@ pub enum Error {
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||||
match *self {
|
match *self {
|
||||||
Error::Io(ref err) => err.fmt(f),
|
Self::Io(ref err) => err.fmt(f),
|
||||||
Error::Toml(ref err) => err.fmt(f),
|
Self::Toml(ref err) => err.fmt(f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<io::Error> for Error {
|
impl From<io::Error> for Error {
|
||||||
fn from(e: io::Error) -> Self {
|
fn from(e: io::Error) -> Self {
|
||||||
Error::Io(e)
|
Self::Io(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -438,9 +438,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||||
self.hash_expr(fun);
|
self.hash_expr(fun);
|
||||||
self.hash_exprs(args);
|
self.hash_exprs(args);
|
||||||
},
|
},
|
||||||
ExprKind::Cast(ref e, ref _ty) | ExprKind::Type(ref e, ref _ty) => {
|
ExprKind::Cast(ref e, ref ty) | ExprKind::Type(ref e, ref ty) => {
|
||||||
self.hash_expr(e);
|
self.hash_expr(e);
|
||||||
// TODO: _ty
|
self.hash_ty(ty);
|
||||||
},
|
},
|
||||||
ExprKind::Closure(cap, _, eid, _, _) => {
|
ExprKind::Closure(cap, _, eid, _, _) => {
|
||||||
match cap {
|
match cap {
|
||||||
|
@ -512,7 +512,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||||
self.hash_expr(e);
|
self.hash_expr(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ExprKind::Tup(ref v) | ExprKind::Array(ref v) => {
|
ExprKind::Tup(ref tup) => {
|
||||||
|
self.hash_exprs(tup);
|
||||||
|
},
|
||||||
|
ExprKind::Array(ref v) => {
|
||||||
self.hash_exprs(v);
|
self.hash_exprs(v);
|
||||||
},
|
},
|
||||||
ExprKind::Unary(lop, ref le) => {
|
ExprKind::Unary(lop, ref le) => {
|
||||||
|
@ -574,4 +577,100 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn hash_lifetime(&mut self, lifetime: &Lifetime) {
|
||||||
|
std::mem::discriminant(&lifetime.name).hash(&mut self.s);
|
||||||
|
if let LifetimeName::Param(ref name) = lifetime.name {
|
||||||
|
std::mem::discriminant(name).hash(&mut self.s);
|
||||||
|
match name {
|
||||||
|
ParamName::Plain(ref ident) => {
|
||||||
|
ident.name.hash(&mut self.s);
|
||||||
|
},
|
||||||
|
ParamName::Fresh(ref size) => {
|
||||||
|
size.hash(&mut self.s);
|
||||||
|
},
|
||||||
|
ParamName::Error => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hash_ty(&mut self, ty: &Ty) {
|
||||||
|
self.hash_tykind(&ty.node);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hash_tykind(&mut self, ty: &TyKind) {
|
||||||
|
std::mem::discriminant(ty).hash(&mut self.s);
|
||||||
|
match ty {
|
||||||
|
TyKind::Slice(ty) => {
|
||||||
|
self.hash_ty(ty);
|
||||||
|
},
|
||||||
|
TyKind::Array(ty, anon_const) => {
|
||||||
|
self.hash_ty(ty);
|
||||||
|
self.hash_expr(&self.cx.tcx.hir().body(anon_const.body).value);
|
||||||
|
},
|
||||||
|
TyKind::Ptr(mut_ty) => {
|
||||||
|
self.hash_ty(&mut_ty.ty);
|
||||||
|
mut_ty.mutbl.hash(&mut self.s);
|
||||||
|
},
|
||||||
|
TyKind::Rptr(lifetime, mut_ty) => {
|
||||||
|
self.hash_lifetime(lifetime);
|
||||||
|
self.hash_ty(&mut_ty.ty);
|
||||||
|
mut_ty.mutbl.hash(&mut self.s);
|
||||||
|
},
|
||||||
|
TyKind::BareFn(bfn) => {
|
||||||
|
bfn.unsafety.hash(&mut self.s);
|
||||||
|
bfn.abi.hash(&mut self.s);
|
||||||
|
for arg in &bfn.decl.inputs {
|
||||||
|
self.hash_ty(&arg);
|
||||||
|
}
|
||||||
|
match bfn.decl.output {
|
||||||
|
FunctionRetTy::DefaultReturn(_) => {
|
||||||
|
().hash(&mut self.s);
|
||||||
|
},
|
||||||
|
FunctionRetTy::Return(ref ty) => {
|
||||||
|
self.hash_ty(ty);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
bfn.decl.c_variadic.hash(&mut self.s);
|
||||||
|
},
|
||||||
|
TyKind::Tup(ty_list) => {
|
||||||
|
for ty in ty_list {
|
||||||
|
self.hash_ty(ty);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
TyKind::Path(qpath) => match qpath {
|
||||||
|
QPath::Resolved(ref maybe_ty, ref path) => {
|
||||||
|
if let Some(ref ty) = maybe_ty {
|
||||||
|
self.hash_ty(ty);
|
||||||
|
}
|
||||||
|
for segment in &path.segments {
|
||||||
|
segment.ident.name.hash(&mut self.s);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
QPath::TypeRelative(ref ty, ref segment) => {
|
||||||
|
self.hash_ty(ty);
|
||||||
|
segment.ident.name.hash(&mut self.s);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TyKind::Def(_, arg_list) => {
|
||||||
|
for arg in arg_list {
|
||||||
|
match arg {
|
||||||
|
GenericArg::Lifetime(ref l) => self.hash_lifetime(l),
|
||||||
|
GenericArg::Type(ref ty) => self.hash_ty(&ty),
|
||||||
|
GenericArg::Const(ref ca) => {
|
||||||
|
self.hash_expr(&self.cx.tcx.hir().body(ca.value.body).value);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
TyKind::TraitObject(_, lifetime) => {
|
||||||
|
self.hash_lifetime(lifetime);
|
||||||
|
},
|
||||||
|
TyKind::Typeof(anon_const) => {
|
||||||
|
self.hash_expr(&self.cx.tcx.hir().body(anon_const.body).value);
|
||||||
|
},
|
||||||
|
TyKind::CVarArgs(lifetime) => self.hash_lifetime(lifetime),
|
||||||
|
TyKind::Err | TyKind::Infer | TyKind::Never => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,14 +13,14 @@ declare_clippy_lint! {
|
||||||
/// attribute
|
/// attribute
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// #[clippy::dump]
|
/// #[clippy::dump]
|
||||||
/// extern crate foo;
|
/// extern crate foo;
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// prints
|
/// prints
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```text
|
||||||
/// item `foo`
|
/// item `foo`
|
||||||
/// visibility inherited from outer item
|
/// visibility inherited from outer item
|
||||||
/// extern crate dylib source: "/path/to/foo.so"
|
/// extern crate dylib source: "/path/to/foo.so"
|
||||||
|
@ -63,8 +63,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DeepCodeInspector {
|
||||||
print_expr(cx, &cx.tcx.hir().body(body_id).value, 1);
|
print_expr(cx, &cx.tcx.hir().body(body_id).value, 1);
|
||||||
},
|
},
|
||||||
hir::ImplItemKind::Method(..) => println!("method"),
|
hir::ImplItemKind::Method(..) => println!("method"),
|
||||||
hir::ImplItemKind::Type(_) => println!("associated type"),
|
hir::ImplItemKind::TyAlias(_) => println!("associated type"),
|
||||||
hir::ImplItemKind::Existential(_) => println!("existential type"),
|
hir::ImplItemKind::OpaqueTy(_) => println!("existential type"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx
|
// fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx
|
||||||
|
@ -360,10 +360,10 @@ fn print_item(cx: &LateContext<'_, '_>, item: &hir::Item) {
|
||||||
hir::ItemKind::Mod(..) => println!("module"),
|
hir::ItemKind::Mod(..) => println!("module"),
|
||||||
hir::ItemKind::ForeignMod(ref fm) => println!("foreign module with abi: {}", fm.abi),
|
hir::ItemKind::ForeignMod(ref fm) => println!("foreign module with abi: {}", fm.abi),
|
||||||
hir::ItemKind::GlobalAsm(ref asm) => println!("global asm: {:?}", asm),
|
hir::ItemKind::GlobalAsm(ref asm) => println!("global asm: {:?}", asm),
|
||||||
hir::ItemKind::Ty(..) => {
|
hir::ItemKind::TyAlias(..) => {
|
||||||
println!("type alias for {:?}", cx.tcx.type_of(did));
|
println!("type alias for {:?}", cx.tcx.type_of(did));
|
||||||
},
|
},
|
||||||
hir::ItemKind::Existential(..) => {
|
hir::ItemKind::OpaqueTy(..) => {
|
||||||
println!("existential type with real type {:?}", cx.tcx.type_of(did));
|
println!("existential type with real type {:?}", cx.tcx.type_of(did));
|
||||||
},
|
},
|
||||||
hir::ItemKind::Enum(..) => {
|
hir::ItemKind::Enum(..) => {
|
||||||
|
|
|
@ -38,7 +38,7 @@ declare_clippy_lint! {
|
||||||
/// `declare_lint_pass!`, `impl_lint_pass!`, and `lint_array!` macros.
|
/// `declare_lint_pass!`, `impl_lint_pass!`, and `lint_array!` macros.
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// declare_lint! { pub LINT_1, ... }
|
/// declare_lint! { pub LINT_1, ... }
|
||||||
/// declare_lint! { pub LINT_2, ... }
|
/// declare_lint! { pub LINT_2, ... }
|
||||||
/// declare_lint! { pub FORGOTTEN_LINT, ... }
|
/// declare_lint! { pub FORGOTTEN_LINT, ... }
|
||||||
|
@ -62,12 +62,12 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// Bad:
|
/// Bad:
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// cx.span_lint(LINT_NAME, "message");
|
/// cx.span_lint(LINT_NAME, "message");
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Good:
|
/// Good:
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// utils::span_lint(cx, LINT_NAME, "message");
|
/// utils::span_lint(cx, LINT_NAME, "message");
|
||||||
/// ```
|
/// ```
|
||||||
pub COMPILER_LINT_FUNCTIONS,
|
pub COMPILER_LINT_FUNCTIONS,
|
||||||
|
@ -85,17 +85,17 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// Bad:
|
/// Bad:
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// expr.span.ctxt().outer().expn_info()
|
/// expr.span.ctxt().outer().expn_info()
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Good:
|
/// Good:
|
||||||
/// ```rust
|
/// ```rust,ignore
|
||||||
/// expr.span.ctxt().outer_expn_info()
|
/// expr.span.ctxt().outer_expn_info()
|
||||||
/// ```
|
/// ```
|
||||||
pub OUTER_EXPN_INFO,
|
pub OUTER_EXPN_EXPN_INFO,
|
||||||
internal,
|
internal,
|
||||||
"using `cx.outer().expn_info()` instead of `cx.outer_expn_info()`"
|
"using `cx.outer_expn().expn_info()` instead of `cx.outer_expn_info()`"
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]);
|
declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]);
|
||||||
|
@ -280,7 +280,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CompilerLintFunctions {
|
||||||
|
|
||||||
pub struct OuterExpnInfoPass;
|
pub struct OuterExpnInfoPass;
|
||||||
|
|
||||||
impl_lint_pass!(OuterExpnInfoPass => [OUTER_EXPN_INFO]);
|
impl_lint_pass!(OuterExpnInfoPass => [OUTER_EXPN_EXPN_INFO]);
|
||||||
|
|
||||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OuterExpnInfoPass {
|
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OuterExpnInfoPass {
|
||||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
|
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
|
||||||
|
@ -288,7 +288,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OuterExpnInfoPass {
|
||||||
let method_names: Vec<LocalInternedString> = method_names.iter().map(|s| s.as_str()).collect();
|
let method_names: Vec<LocalInternedString> = method_names.iter().map(|s| s.as_str()).collect();
|
||||||
let method_names: Vec<&str> = method_names.iter().map(std::convert::AsRef::as_ref).collect();
|
let method_names: Vec<&str> = method_names.iter().map(std::convert::AsRef::as_ref).collect();
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let ["expn_info", "outer"] = method_names.as_slice();
|
if let ["expn_info", "outer_expn"] = method_names.as_slice();
|
||||||
let args = arg_lists[1];
|
let args = arg_lists[1];
|
||||||
if args.len() == 1;
|
if args.len() == 1;
|
||||||
let self_arg = &args[0];
|
let self_arg = &args[0];
|
||||||
|
@ -297,9 +297,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OuterExpnInfoPass {
|
||||||
then {
|
then {
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
OUTER_EXPN_INFO,
|
OUTER_EXPN_EXPN_INFO,
|
||||||
expr.span.trim_start(self_arg.span).unwrap_or(expr.span),
|
expr.span.trim_start(self_arg.span).unwrap_or(expr.span),
|
||||||
"usage of `outer().expn_info()`",
|
"usage of `outer_expn().expn_info()`",
|
||||||
"try",
|
"try",
|
||||||
".outer_expn_info()".to_string(),
|
".outer_expn_info()".to_string(),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
|
|
|
@ -43,7 +43,7 @@ use rustc_errors::Applicability;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use syntax::ast::{self, LitKind};
|
use syntax::ast::{self, LitKind};
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax::ext::hygiene::ExpnFormat;
|
use syntax::ext::hygiene::ExpnKind;
|
||||||
use syntax::source_map::{Span, DUMMY_SP};
|
use syntax::source_map::{Span, DUMMY_SP};
|
||||||
use syntax::symbol::{kw, Symbol};
|
use syntax::symbol::{kw, Symbol};
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ pub fn in_macro_or_desugar(span: Span) -> bool {
|
||||||
/// Returns `true` if this `expn_info` was expanded by any macro.
|
/// Returns `true` if this `expn_info` was expanded by any macro.
|
||||||
pub fn in_macro(span: Span) -> bool {
|
pub fn in_macro(span: Span) -> bool {
|
||||||
if let Some(info) = span.ctxt().outer_expn_info() {
|
if let Some(info) = span.ctxt().outer_expn_info() {
|
||||||
if let ExpnFormat::CompilerDesugaring(..) = info.format {
|
if let ExpnKind::Desugaring(..) = info.kind {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
|
@ -686,7 +686,7 @@ pub fn is_adjusted(cx: &LateContext<'_, '_>, e: &Expr) -> bool {
|
||||||
/// See also `is_direct_expn_of`.
|
/// See also `is_direct_expn_of`.
|
||||||
pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
|
pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
|
||||||
loop {
|
loop {
|
||||||
let span_name_span = span.ctxt().outer_expn_info().map(|ei| (ei.format.name(), ei.call_site));
|
let span_name_span = span.ctxt().outer_expn_info().map(|ei| (ei.kind.descr(), ei.call_site));
|
||||||
|
|
||||||
match span_name_span {
|
match span_name_span {
|
||||||
Some((mac_name, new_span)) if mac_name.as_str() == name => return Some(new_span),
|
Some((mac_name, new_span)) if mac_name.as_str() == name => return Some(new_span),
|
||||||
|
@ -706,7 +706,7 @@ pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
|
||||||
/// `bar!` by
|
/// `bar!` by
|
||||||
/// `is_direct_expn_of`.
|
/// `is_direct_expn_of`.
|
||||||
pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> {
|
pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> {
|
||||||
let span_name_span = span.ctxt().outer_expn_info().map(|ei| (ei.format.name(), ei.call_site));
|
let span_name_span = span.ctxt().outer_expn_info().map(|ei| (ei.kind.descr(), ei.call_site));
|
||||||
|
|
||||||
match span_name_span {
|
match span_name_span {
|
||||||
Some((mac_name, new_span)) if mac_name.as_str() == name => Some(new_span),
|
Some((mac_name, new_span)) if mac_name.as_str() == name => Some(new_span),
|
||||||
|
|
|
@ -37,7 +37,6 @@ pub const HASHMAP_ENTRY: [&str; 5] = ["std", "collections", "hash", "map", "Entr
|
||||||
pub const HASHSET: [&str; 5] = ["std", "collections", "hash", "set", "HashSet"];
|
pub const HASHSET: [&str; 5] = ["std", "collections", "hash", "set", "HashSet"];
|
||||||
pub const INDEX: [&str; 3] = ["core", "ops", "Index"];
|
pub const INDEX: [&str; 3] = ["core", "ops", "Index"];
|
||||||
pub const INDEX_MUT: [&str; 3] = ["core", "ops", "IndexMut"];
|
pub const INDEX_MUT: [&str; 3] = ["core", "ops", "IndexMut"];
|
||||||
pub const INIT: [&str; 4] = ["core", "intrinsics", "", "init"];
|
|
||||||
pub const INTO: [&str; 3] = ["core", "convert", "Into"];
|
pub const INTO: [&str; 3] = ["core", "convert", "Into"];
|
||||||
pub const INTO_ITERATOR: [&str; 5] = ["core", "iter", "traits", "collect", "IntoIterator"];
|
pub const INTO_ITERATOR: [&str; 5] = ["core", "iter", "traits", "collect", "IntoIterator"];
|
||||||
pub const IO_READ: [&str; 3] = ["std", "io", "Read"];
|
pub const IO_READ: [&str; 3] = ["std", "io", "Read"];
|
||||||
|
@ -50,8 +49,6 @@ pub const LINT_PASS: [&str; 3] = ["rustc", "lint", "LintPass"];
|
||||||
pub const MEM_DISCRIMINANT: [&str; 3] = ["core", "mem", "discriminant"];
|
pub const MEM_DISCRIMINANT: [&str; 3] = ["core", "mem", "discriminant"];
|
||||||
pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"];
|
pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"];
|
||||||
pub const MEM_REPLACE: [&str; 3] = ["core", "mem", "replace"];
|
pub const MEM_REPLACE: [&str; 3] = ["core", "mem", "replace"];
|
||||||
pub const MEM_UNINIT: [&str; 3] = ["core", "mem", "uninitialized"];
|
|
||||||
pub const MEM_ZEROED: [&str; 3] = ["core", "mem", "zeroed"];
|
|
||||||
pub const MUTEX: [&str; 4] = ["std", "sync", "mutex", "Mutex"];
|
pub const MUTEX: [&str; 4] = ["std", "sync", "mutex", "Mutex"];
|
||||||
pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"];
|
pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"];
|
||||||
pub const OPS_MODULE: [&str; 2] = ["core", "ops"];
|
pub const OPS_MODULE: [&str; 2] = ["core", "ops"];
|
||||||
|
@ -109,7 +106,6 @@ pub const TO_STRING_METHOD: [&str; 4] = ["alloc", "string", "ToString", "to_stri
|
||||||
pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"];
|
pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"];
|
||||||
pub const TRY_FROM_ERROR: [&str; 4] = ["std", "ops", "Try", "from_error"];
|
pub const TRY_FROM_ERROR: [&str; 4] = ["std", "ops", "Try", "from_error"];
|
||||||
pub const TRY_INTO_RESULT: [&str; 4] = ["std", "ops", "Try", "into_result"];
|
pub const TRY_INTO_RESULT: [&str; 4] = ["std", "ops", "Try", "into_result"];
|
||||||
pub const UNINIT: [&str; 4] = ["core", "intrinsics", "", "uninit"];
|
|
||||||
pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"];
|
pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"];
|
||||||
pub const VEC_DEQUE: [&str; 4] = ["alloc", "collections", "vec_deque", "VecDeque"];
|
pub const VEC_DEQUE: [&str; 4] = ["alloc", "collections", "vec_deque", "VecDeque"];
|
||||||
pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"];
|
pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"];
|
||||||
|
|
|
@ -77,6 +77,7 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # let foo = "bar";
|
||||||
/// println!("{:?}", foo);
|
/// println!("{:?}", foo);
|
||||||
/// ```
|
/// ```
|
||||||
pub USE_DEBUG,
|
pub USE_DEBUG,
|
||||||
|
@ -364,7 +365,9 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O
|
||||||
align: AlignUnknown,
|
align: AlignUnknown,
|
||||||
flags: 0,
|
flags: 0,
|
||||||
precision: CountImplied,
|
precision: CountImplied,
|
||||||
|
precision_span: None,
|
||||||
width: CountImplied,
|
width: CountImplied,
|
||||||
|
width_span: None,
|
||||||
ty: "",
|
ty: "",
|
||||||
};
|
};
|
||||||
if !parser.eat(&token::Comma) {
|
if !parser.eat(&token::Comma) {
|
||||||
|
|
|
@ -15,7 +15,7 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// **Example:**
|
/// **Example:**
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// 0.0f32 / 0.0
|
/// 0.0f32 / 0.0;
|
||||||
/// ```
|
/// ```
|
||||||
pub ZERO_DIVIDED_BY_ZERO,
|
pub ZERO_DIVIDED_BY_ZERO,
|
||||||
complexity,
|
complexity,
|
||||||
|
|
|
@ -345,16 +345,18 @@ list][lint_list].
|
||||||
|
|
||||||
### Running rustfmt
|
### Running rustfmt
|
||||||
|
|
||||||
[Rustfmt](https://github.com/rust-lang/rustfmt) is a tool for formatting Rust code according
|
[Rustfmt](https://github.com/rust-lang/rustfmt) is a tool for formatting Rust
|
||||||
to style guidelines. Your code has to be formatted by `rustfmt` before a PR can be merged.
|
code according to style guidelines. Your code has to be formatted by `rustfmt`
|
||||||
|
before a PR can be merged. Clippy uses nightly `rustfmt` in the CI.
|
||||||
|
|
||||||
It can be installed via `rustup`:
|
It can be installed via `rustup`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
rustup component add rustfmt
|
rustup component add rustfmt --toolchain=nightly
|
||||||
```
|
```
|
||||||
|
|
||||||
Use `cargo fmt --all` to format the whole codebase.
|
Use `./util/dev fmt` to format the whole codebase. Make sure that `rustfmt` is
|
||||||
|
installed for the nightly toolchain.
|
||||||
|
|
||||||
### Debugging
|
### Debugging
|
||||||
|
|
||||||
|
@ -366,12 +368,14 @@ output in the `stdout` part.
|
||||||
|
|
||||||
Before submitting your PR make sure you followed all of the basic requirements:
|
Before submitting your PR make sure you followed all of the basic requirements:
|
||||||
|
|
||||||
|
<!-- Sync this with `.github/PULL_REQUEST_TEMPLATE` -->
|
||||||
|
|
||||||
- [ ] Followed [lint naming conventions][lint_naming]
|
- [ ] Followed [lint naming conventions][lint_naming]
|
||||||
- [ ] Added passing UI tests (including committed `.stderr` file)
|
- [ ] Added passing UI tests (including committed `.stderr` file)
|
||||||
- [ ] `cargo test` passes locally
|
- [ ] `cargo test` passes locally
|
||||||
- [ ] Executed `util/dev update_lints`
|
- [ ] Executed `./util/dev update_lints`
|
||||||
- [ ] Added lint documentation
|
- [ ] Added lint documentation
|
||||||
- [ ] Run `cargo fmt`
|
- [ ] Run `./util/dev fmt`
|
||||||
|
|
||||||
### Cheatsheet
|
### Cheatsheet
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue