Merge remote-tracking branch 'upstream/master' into clippy-fix

This commit is contained in:
Jane Lusby 2020-04-15 08:24:13 -07:00
commit 0441525690
256 changed files with 2953 additions and 2085 deletions

4
.gitattributes vendored
View File

@ -1,5 +1,3 @@
[attr]rust text eol=lf whitespace=tab-in-indent,trailing-space,tabwidth=4
* text=auto eol=lf * text=auto eol=lf
*.rs rust *.rs text eol=lf whitespace=tab-in-indent,trailing-space,tabwidth=4
*.fixed linguist-language=Rust *.fixed linguist-language=Rust

10
.github/deploy.sh vendored
View File

@ -17,6 +17,11 @@ if [[ -n $TAG_NAME ]]; then
ln -s "$TAG_NAME" out/stable ln -s "$TAG_NAME" out/stable
fi fi
if [[ $BETA = "true" ]]; then
echo "Update documentation for the beta release"
cp -r out/master out/beta
fi
# Generate version index that is shown as root index page # Generate version index that is shown as root index page
cp util/gh-pages/versions.html out/index.html cp util/gh-pages/versions.html out/index.html
@ -35,12 +40,15 @@ fi
if [[ -n $TAG_NAME ]]; then if [[ -n $TAG_NAME ]]; then
# Add the new dir # Add the new dir
git add $TAG_NAME git add "$TAG_NAME"
# Update the symlink # Update the symlink
git add stable git add stable
# Update versions file # Update versions file
git add versions.json git add versions.json
git commit -m "Add documentation for ${TAG_NAME} release: ${SHA}" git commit -m "Add documentation for ${TAG_NAME} release: ${SHA}"
elif [[ $BETA = "true" ]]; then
git add beta
git commit -m "Automatic deploy to GitHub Pages (beta): ${SHA}"
else else
git add . git add .
git commit -m "Automatic deploy to GitHub Pages: ${SHA}" git commit -m "Automatic deploy to GitHub Pages: ${SHA}"

View File

@ -234,7 +234,8 @@ jobs:
- 'rust-lang/cargo' - 'rust-lang/cargo'
- 'rust-lang/rls' - 'rust-lang/rls'
- 'rust-lang/chalk' - 'rust-lang/chalk'
- 'rust-lang/rustfmt' # FIXME: Disabled until https://github.com/rust-lang/rust/issues/71077 is fixed
# - 'rust-lang/rustfmt'
- 'Marwes/combine' - 'Marwes/combine'
- 'Geal/nom' - 'Geal/nom'
- 'rust-lang/stdarch' - 'rust-lang/stdarch'

View File

@ -38,8 +38,8 @@ jobs:
run: cargo build --features deny-warnings run: cargo build --features deny-warnings
working-directory: clippy_dev working-directory: clippy_dev
- name: Test limit-stderr-length - name: Test limit_stderr_length
run: cargo dev --limit-stderr-length run: cargo dev limit_stderr_length
- name: Test update_lints - name: Test update_lints
run: cargo dev update_lints --check run: cargo dev update_lints --check

View File

@ -4,6 +4,7 @@ on:
push: push:
branches: branches:
- master - master
- beta
tags: tags:
- rust-1.** - rust-1.**
@ -34,6 +35,9 @@ jobs:
run: | run: |
TAG=$(basename ${{ github.ref }}) TAG=$(basename ${{ github.ref }})
echo "::set-env name=TAG_NAME::$TAG" echo "::set-env name=TAG_NAME::$TAG"
- name: Set beta to true
if: github.ref == 'refs/heads/beta'
run: echo "::set-env name=BETA::true"
- name: Deploy - name: Deploy
run: | run: |
eval "$(ssh-agent -s)" eval "$(ssh-agent -s)"

View File

@ -1271,6 +1271,7 @@ Released 2018-09-13
[`float_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_arithmetic [`float_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_arithmetic
[`float_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp [`float_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp
[`float_cmp_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp_const [`float_cmp_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp_const
[`fn_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_address_comparisons
[`fn_params_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools [`fn_params_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools
[`fn_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast [`fn_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast
[`fn_to_numeric_cast_with_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_with_truncation [`fn_to_numeric_cast_with_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_with_truncation
@ -1432,6 +1433,7 @@ Released 2018-09-13
[`range_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_plus_one [`range_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_plus_one
[`range_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_step_by_zero [`range_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_step_by_zero
[`range_zip_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_zip_with_len [`range_zip_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_zip_with_len
[`redundant_allocation`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation
[`redundant_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone [`redundant_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone
[`redundant_closure`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure [`redundant_closure`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
[`redundant_closure_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_call [`redundant_closure_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_call
@ -1446,6 +1448,7 @@ Released 2018-09-13
[`replace_consts`]: https://rust-lang.github.io/rust-clippy/master/index.html#replace_consts [`replace_consts`]: https://rust-lang.github.io/rust-clippy/master/index.html#replace_consts
[`rest_pat_in_fully_bound_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#rest_pat_in_fully_bound_structs [`rest_pat_in_fully_bound_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#rest_pat_in_fully_bound_structs
[`result_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_expect_used [`result_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_expect_used
[`result_map_or_into_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_or_into_option
[`result_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unit_fn [`result_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unit_fn
[`result_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else [`result_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else
[`result_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unwrap_used [`result_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unwrap_used
@ -1540,6 +1543,7 @@ Released 2018-09-13
[`vec_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#vec_box [`vec_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#vec_box
[`verbose_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask [`verbose_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask
[`verbose_file_reads`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_file_reads [`verbose_file_reads`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_file_reads
[`vtable_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#vtable_address_comparisons
[`while_immutable_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_immutable_condition [`while_immutable_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_immutable_condition
[`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop [`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop
[`while_let_on_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator [`while_let_on_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator

View File

@ -36,7 +36,8 @@ High level approach:
### Finding something to fix/improve ### Finding something to fix/improve
All issues on Clippy are mentored, if you want help with a bug just ask @Manishearth, @llogiq, @mcarton or @oli-obk. All issues on Clippy are mentored, if you want help with a bug just ask
@Manishearth, @flip1995, @phansch or @yaahc.
Some issues are easier than others. The [`good first issue`] label can be used to find the easy issues. Some issues are easier than others. The [`good first issue`] label can be used to find the easy issues.
If you want to work on an issue, please leave a comment so that we can assign it to you! If you want to work on an issue, please leave a comment so that we can assign it to you!
@ -70,7 +71,7 @@ an AST expression). `match_def_path()` in Clippy's `utils` module can also be us
[`T-AST`]: https://github.com/rust-lang/rust-clippy/labels/T-AST [`T-AST`]: https://github.com/rust-lang/rust-clippy/labels/T-AST
[`T-middle`]: https://github.com/rust-lang/rust-clippy/labels/T-middle [`T-middle`]: https://github.com/rust-lang/rust-clippy/labels/T-middle
[`E-medium`]: https://github.com/rust-lang/rust-clippy/labels/E-medium [`E-medium`]: https://github.com/rust-lang/rust-clippy/labels/E-medium
[`ty`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty [`ty`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty
[nodes in the AST docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/ [nodes in the AST docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/
[deep-nesting]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/mem_forget.rs#L29-L43 [deep-nesting]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/mem_forget.rs#L29-L43
[if_chain]: https://docs.rs/if_chain/*/if_chain [if_chain]: https://docs.rs/if_chain/*/if_chain
@ -78,8 +79,7 @@ an AST expression). `match_def_path()` in Clippy's `utils` module can also be us
## Writing code ## Writing code
Have a look at the [docs for writing lints][adding_lints] for more details. [Llogiq's blog post on lints] Have a look at the [docs for writing lints][adding_lints] for more details.
is also a nice primer to lint-writing, though it does get into advanced stuff and may be a bit outdated.
If you want to add a new lint or change existing ones apart from bugfixing, it's If you want to add a new lint or change existing ones apart from bugfixing, it's
also a good idea to give the [stability guarantees][rfc_stability] and also a good idea to give the [stability guarantees][rfc_stability] and
@ -87,7 +87,6 @@ also a good idea to give the [stability guarantees][rfc_stability] and
quick read. quick read.
[adding_lints]: https://github.com/rust-lang/rust-clippy/blob/master/doc/adding_lints.md [adding_lints]: https://github.com/rust-lang/rust-clippy/blob/master/doc/adding_lints.md
[Llogiq's blog post on lints]: https://llogiq.github.io/2015/06/04/workflows.html
[clippy_rfc]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md [clippy_rfc]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md
[rfc_stability]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#stability-guarantees [rfc_stability]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#stability-guarantees
[rfc_lint_cats]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#lint-audit-and-categories [rfc_lint_cats]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#lint-audit-and-categories
@ -223,7 +222,7 @@ You can find the Clippy bors queue [here][homu_queue].
If you have @bors permissions, you can find an overview of the available If you have @bors permissions, you can find an overview of the available
commands [here][homu_instructions]. commands [here][homu_instructions].
[triage]: https://forge.rust-lang.org/triage-procedure.html [triage]: https://forge.rust-lang.org/release/triage-procedure.html
[l-crash]: https://github.com/rust-lang/rust-clippy/labels/L-crash%20%3Aboom%3A [l-crash]: https://github.com/rust-lang/rust-clippy/labels/L-crash%20%3Aboom%3A
[l-bug]: https://github.com/rust-lang/rust-clippy/labels/L-bug%20%3Abeetle%3A [l-bug]: https://github.com/rust-lang/rust-clippy/labels/L-bug%20%3Abeetle%3A
[homu]: https://github.com/rust-lang/homu [homu]: https://github.com/rust-lang/homu

View File

@ -42,7 +42,7 @@ lazy_static = "1.0"
[dev-dependencies] [dev-dependencies]
cargo_metadata = "0.9.0" cargo_metadata = "0.9.0"
compiletest_rs = { version = "0.4.0", features = ["tmp"] } compiletest_rs = { version = "0.5.0", features = ["tmp"] }
tester = "0.7" tester = "0.7"
lazy_static = "1.0" lazy_static = "1.0"
clippy-mini-macro-test = { version = "0.2", path = "mini-macro" } clippy-mini-macro-test = { version = "0.2", path = "mini-macro" }

View File

@ -5,7 +5,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 362 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) [There are over 350 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:
@ -90,14 +90,6 @@ Note that this is still experimental and only supported on the nightly channel:
cargo fix -Z unstable-options --clippy cargo fix -Z unstable-options --clippy
``` ```
#### Running only a single lint
If you care only about the warnings of a single lint and want to ignore everything else, you
can first deny all the clippy lints and then explicitly enable the lint(s) you care about:
````
cargo clippy -- -Aclippy::all -Wclippy::useless_format
````
### 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
@ -183,6 +175,8 @@ If you do not want to include your lint levels in your code, you can globally en
flags to Clippy during the run: `cargo clippy -- -A clippy::lint_name` will run Clippy with `lint_name` disabled and flags to Clippy during the run: `cargo clippy -- -A clippy::lint_name` will run Clippy with `lint_name` disabled and
`cargo clippy -- -W clippy::lint_name` will run it with that enabled. This also works with lint groups. For example you `cargo clippy -- -W clippy::lint_name` will run it with that enabled. This also works with lint groups. For example you
can run Clippy with warnings for all lints enabled: `cargo clippy -- -W clippy::pedantic` can run Clippy with warnings for all lints enabled: `cargo clippy -- -W clippy::pedantic`
If you care only about a single lint, you can allow all others and then explicitly reenable
the lint(s) you are interested in: `cargo clippy -- -Aclippy::all -Wclippy::useless_format -Wclippy::...`
## Contributing ## Contributing

View File

@ -7,7 +7,7 @@ edition = "2018"
[dependencies] [dependencies]
bytecount = "0.6" bytecount = "0.6"
clap = "2.33" clap = "2.33"
itertools = "0.8" itertools = "0.9"
regex = "1" regex = "1"
lazy_static = "1.0" lazy_static = "1.0"
shell-escape = "0.1" shell-escape = "0.1"

View File

@ -1,4 +1,4 @@
use clippy_dev::clippy_project_root; use crate::clippy_project_root;
use shell_escape::escape; use shell_escape::escape;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::io; use std::io;

View File

@ -9,6 +9,11 @@ use std::fs;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use walkdir::WalkDir; use walkdir::WalkDir;
pub mod fmt;
pub mod new_lint;
pub mod stderr_length_check;
pub mod update_lints;
lazy_static! { lazy_static! {
static ref DEC_CLIPPY_LINT_RE: Regex = Regex::new( static ref DEC_CLIPPY_LINT_RE: Regex = Regex::new(
r#"(?x) r#"(?x)
@ -57,13 +62,25 @@ impl Lint {
} }
/// Returns all non-deprecated lints and non-internal lints /// Returns all non-deprecated lints and non-internal lints
pub fn usable_lints(lints: impl Iterator<Item = Self>) -> impl Iterator<Item = Self> { #[must_use]
lints.filter(|l| l.deprecation.is_none() && !l.is_internal()) pub fn usable_lints(lints: &[Self]) -> Vec<Self> {
lints
.iter()
.filter(|l| l.deprecation.is_none() && !l.group.starts_with("internal"))
.cloned()
.collect()
} }
/// Returns all internal lints (not `internal_warn` lints) /// Returns all internal lints (not `internal_warn` lints)
pub fn internal_lints(lints: impl Iterator<Item = Self>) -> impl Iterator<Item = Self> { #[must_use]
lints.filter(|l| l.group == "internal") pub fn internal_lints(lints: &[Self]) -> Vec<Self> {
lints.iter().filter(|l| l.group == "internal").cloned().collect()
}
/// Returns all deprecated lints
#[must_use]
pub fn deprecated_lints(lints: &[Self]) -> Vec<Self> {
lints.iter().filter(|l| l.deprecation.is_some()).cloned().collect()
} }
/// Returns the lints in a `HashMap`, grouped by the different lint groups /// Returns the lints in a `HashMap`, grouped by the different lint groups
@ -71,96 +88,63 @@ impl Lint {
pub fn by_lint_group(lints: impl Iterator<Item = Self>) -> HashMap<String, Vec<Self>> { pub fn by_lint_group(lints: impl Iterator<Item = Self>) -> HashMap<String, Vec<Self>> {
lints.map(|lint| (lint.group.to_string(), lint)).into_group_map() lints.map(|lint| (lint.group.to_string(), lint)).into_group_map()
} }
#[must_use]
pub fn is_internal(&self) -> bool {
self.group.starts_with("internal")
}
} }
/// Generates the Vec items for `register_lint_group` calls in `clippy_lints/src/lib.rs`. /// Generates the Vec items for `register_lint_group` calls in `clippy_lints/src/lib.rs`.
#[must_use] #[must_use]
pub fn gen_lint_group_list(lints: Vec<Lint>) -> Vec<String> { pub fn gen_lint_group_list<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> {
lints lints
.into_iter() .map(|l| format!(" LintId::of(&{}::{}),", l.module, l.name.to_uppercase()))
.filter_map(|l| {
if l.deprecation.is_some() {
None
} else {
Some(format!(" LintId::of(&{}::{}),", l.module, l.name.to_uppercase()))
}
})
.sorted() .sorted()
.collect::<Vec<String>>() .collect::<Vec<String>>()
} }
/// Generates the `pub mod module_name` list in `clippy_lints/src/lib.rs`. /// Generates the `pub mod module_name` list in `clippy_lints/src/lib.rs`.
#[must_use] #[must_use]
pub fn gen_modules_list(lints: Vec<Lint>) -> Vec<String> { pub fn gen_modules_list<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> {
lints lints
.into_iter() .map(|l| &l.module)
.filter_map(|l| {
if l.is_internal() || l.deprecation.is_some() {
None
} else {
Some(l.module)
}
})
.unique() .unique()
.map(|module| format!("pub mod {};", module)) .map(|module| format!("mod {};", module))
.sorted() .sorted()
.collect::<Vec<String>>() .collect::<Vec<String>>()
} }
/// Generates the list of lint links at the bottom of the README /// Generates the list of lint links at the bottom of the README
#[must_use] #[must_use]
pub fn gen_changelog_lint_list(lints: Vec<Lint>) -> Vec<String> { pub fn gen_changelog_lint_list<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> {
let mut lint_list_sorted: Vec<Lint> = lints; lints
lint_list_sorted.sort_by_key(|l| l.name.clone()); .sorted_by_key(|l| &l.name)
lint_list_sorted .map(|l| format!("[`{}`]: {}#{}", l.name, DOCS_LINK, l.name))
.iter()
.filter_map(|l| {
if l.is_internal() {
None
} else {
Some(format!("[`{}`]: {}#{}", l.name, DOCS_LINK, l.name))
}
})
.collect() .collect()
} }
/// Generates the `register_removed` code in `./clippy_lints/src/lib.rs`. /// Generates the `register_removed` code in `./clippy_lints/src/lib.rs`.
#[must_use] #[must_use]
pub fn gen_deprecated(lints: &[Lint]) -> Vec<String> { pub fn gen_deprecated<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> {
lints lints
.iter() .flat_map(|l| {
.filter_map(|l| { l.deprecation
l.clone().deprecation.map(|depr_text| { .clone()
vec![ .map(|depr_text| {
" store.register_removed(".to_string(), vec![
format!(" \"clippy::{}\",", l.name), " store.register_removed(".to_string(),
format!(" \"{}\",", depr_text), format!(" \"clippy::{}\",", l.name),
" );".to_string(), format!(" \"{}\",", depr_text),
] " );".to_string(),
}) ]
})
.expect("only deprecated lints should be passed")
}) })
.flatten()
.collect::<Vec<String>>() .collect::<Vec<String>>()
} }
#[must_use] #[must_use]
pub fn gen_register_lint_list(lints: &[Lint]) -> Vec<String> { pub fn gen_register_lint_list<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> {
let pre = " store.register_lints(&[".to_string(); let pre = " store.register_lints(&[".to_string();
let post = " ]);".to_string(); let post = " ]);".to_string();
let mut inner = lints let mut inner = lints
.iter() .map(|l| format!(" &{}::{},", l.module, l.name.to_uppercase()))
.filter_map(|l| {
if !l.is_internal() && l.deprecation.is_none() {
Some(format!(" &{}::{},", l.module, l.name.to_uppercase()))
} else {
None
}
})
.sorted() .sorted()
.collect::<Vec<String>>(); .collect::<Vec<String>>();
inner.insert(0, pre); inner.insert(0, pre);
@ -434,7 +418,7 @@ fn test_usable_lints() {
None, None,
"module_name", "module_name",
)]; )];
assert_eq!(expected, Lint::usable_lints(lints.into_iter()).collect::<Vec<Lint>>()); assert_eq!(expected, Lint::usable_lints(&lints));
} }
#[test] #[test]
@ -464,13 +448,12 @@ fn test_gen_changelog_lint_list() {
let lints = vec![ let lints = vec![
Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"), Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"),
Lint::new("incorrect_internal", "internal_style", "abc", None, "module_name"),
]; ];
let expected = vec![ let expected = vec![
format!("[`should_assert_eq`]: {}#should_assert_eq", DOCS_LINK.to_string()), format!("[`should_assert_eq`]: {}#should_assert_eq", DOCS_LINK.to_string()),
format!("[`should_assert_eq2`]: {}#should_assert_eq2", DOCS_LINK.to_string()), format!("[`should_assert_eq2`]: {}#should_assert_eq2", DOCS_LINK.to_string()),
]; ];
assert_eq!(expected, gen_changelog_lint_list(lints)); assert_eq!(expected, gen_changelog_lint_list(lints.iter()));
} }
#[test] #[test]
@ -490,7 +473,6 @@ fn test_gen_deprecated() {
Some("will be removed"), Some("will be removed"),
"module_name", "module_name",
), ),
Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"),
]; ];
let expected: Vec<String> = vec![ let expected: Vec<String> = vec![
" store.register_removed(", " store.register_removed(",
@ -505,22 +487,24 @@ fn test_gen_deprecated() {
.into_iter() .into_iter()
.map(String::from) .map(String::from)
.collect(); .collect();
assert_eq!(expected, gen_deprecated(&lints)); assert_eq!(expected, gen_deprecated(lints.iter()));
}
#[test]
#[should_panic]
fn test_gen_deprecated_fail() {
let lints = vec![Lint::new("should_assert_eq2", "group2", "abc", None, "module_name")];
let _ = gen_deprecated(lints.iter());
} }
#[test] #[test]
fn test_gen_modules_list() { fn test_gen_modules_list() {
let lints = vec![ let lints = vec![
Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
Lint::new("should_assert_eq2", "group2", "abc", Some("abc"), "deprecated"),
Lint::new("incorrect_stuff", "group3", "abc", None, "another_module"), Lint::new("incorrect_stuff", "group3", "abc", None, "another_module"),
Lint::new("incorrect_internal", "internal_style", "abc", None, "module_name"),
]; ];
let expected = vec![ let expected = vec!["mod another_module;".to_string(), "mod module_name;".to_string()];
"pub mod another_module;".to_string(), assert_eq!(expected, gen_modules_list(lints.iter()));
"pub mod module_name;".to_string(),
];
assert_eq!(expected, gen_modules_list(lints));
} }
#[test] #[test]
@ -528,7 +512,6 @@ fn test_gen_lint_group_list() {
let lints = vec![ let lints = vec![
Lint::new("abc", "group1", "abc", None, "module_name"), Lint::new("abc", "group1", "abc", None, "module_name"),
Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
Lint::new("should_assert_eq2", "group2", "abc", Some("abc"), "deprecated"),
Lint::new("internal", "internal_style", "abc", None, "module_name"), Lint::new("internal", "internal_style", "abc", None, "module_name"),
]; ];
let expected = vec![ let expected = vec![
@ -536,5 +519,5 @@ fn test_gen_lint_group_list() {
" LintId::of(&module_name::INTERNAL),".to_string(), " LintId::of(&module_name::INTERNAL),".to_string(),
" LintId::of(&module_name::SHOULD_ASSERT_EQ),".to_string(), " LintId::of(&module_name::SHOULD_ASSERT_EQ),".to_string(),
]; ];
assert_eq!(expected, gen_lint_group_list(lints)); assert_eq!(expected, gen_lint_group_list(lints.iter()));
} }

View File

@ -1,21 +1,7 @@
#![cfg_attr(feature = "deny-warnings", deny(warnings))] #![cfg_attr(feature = "deny-warnings", deny(warnings))]
use clap::{App, Arg, SubCommand}; use clap::{App, Arg, SubCommand};
use clippy_dev::{ use clippy_dev::{fmt, new_lint, stderr_length_check, update_lints};
gather_all, gen_changelog_lint_list, gen_deprecated, gen_lint_group_list, gen_modules_list, gen_register_lint_list,
replace_region_in_file, Lint, DOCS_LINK,
};
use std::path::Path;
mod fmt;
mod new_lint;
mod stderr_length_check;
#[derive(Clone, Copy, PartialEq)]
enum UpdateMode {
Check,
Change,
}
fn main() { fn main() {
let matches = App::new("Clippy developer tooling") let matches = App::new("Clippy developer tooling")
@ -97,28 +83,23 @@ fn main() {
.takes_value(true), .takes_value(true),
), ),
) )
.arg( .subcommand(
Arg::with_name("limit-stderr-length") SubCommand::with_name("limit_stderr_length")
.long("limit-stderr-length") .about("Ensures that stderr files do not grow longer than a certain amount of lines."),
.help("Ensures that stderr files do not grow longer than a certain amount of lines."),
) )
.get_matches(); .get_matches();
if matches.is_present("limit-stderr-length") {
stderr_length_check::check();
}
match matches.subcommand() { match matches.subcommand() {
("fmt", Some(matches)) => { ("fmt", Some(matches)) => {
fmt::run(matches.is_present("check"), matches.is_present("verbose")); fmt::run(matches.is_present("check"), matches.is_present("verbose"));
}, },
("update_lints", Some(matches)) => { ("update_lints", Some(matches)) => {
if matches.is_present("print-only") { if matches.is_present("print-only") {
print_lints(); update_lints::print_lints();
} else if matches.is_present("check") { } else if matches.is_present("check") {
update_lints(UpdateMode::Check); update_lints::run(update_lints::UpdateMode::Check);
} else { } else {
update_lints(UpdateMode::Change); update_lints::run(update_lints::UpdateMode::Change);
} }
}, },
("new_lint", Some(matches)) => { ("new_lint", Some(matches)) => {
@ -127,168 +108,13 @@ fn main() {
matches.value_of("name"), matches.value_of("name"),
matches.value_of("category"), matches.value_of("category"),
) { ) {
Ok(_) => update_lints(UpdateMode::Change), Ok(_) => update_lints::run(update_lints::UpdateMode::Change),
Err(e) => eprintln!("Unable to create lint: {}", e), Err(e) => eprintln!("Unable to create lint: {}", e),
} }
}, },
("limit_stderr_length", _) => {
stderr_length_check::check();
},
_ => {}, _ => {},
} }
} }
fn print_lints() {
let lint_list = gather_all();
let usable_lints: Vec<Lint> = Lint::usable_lints(lint_list).collect();
let usable_lint_count = usable_lints.len();
let grouped_by_lint_group = Lint::by_lint_group(usable_lints.into_iter());
for (lint_group, mut lints) in grouped_by_lint_group {
if lint_group == "Deprecated" {
continue;
}
println!("\n## {}", lint_group);
lints.sort_by_key(|l| l.name.clone());
for lint in lints {
println!(
"* [{}]({}#{}) ({})",
lint.name,
clippy_dev::DOCS_LINK,
lint.name,
lint.desc
);
}
}
println!("there are {} lints", usable_lint_count);
}
#[allow(clippy::too_many_lines)]
fn update_lints(update_mode: UpdateMode) {
let lint_list: Vec<Lint> = gather_all().collect();
let internal_lints = Lint::internal_lints(lint_list.clone().into_iter());
let usable_lints: Vec<Lint> = Lint::usable_lints(lint_list.clone().into_iter()).collect();
let usable_lint_count = usable_lints.len();
let mut sorted_usable_lints = usable_lints.clone();
sorted_usable_lints.sort_by_key(|lint| lint.name.clone());
let mut file_change = replace_region_in_file(
Path::new("src/lintlist/mod.rs"),
"begin lint list",
"end lint list",
false,
update_mode == UpdateMode::Change,
|| {
format!(
"pub const ALL_LINTS: [Lint; {}] = {:#?};",
sorted_usable_lints.len(),
sorted_usable_lints
)
.lines()
.map(ToString::to_string)
.collect::<Vec<_>>()
},
)
.changed;
file_change |= replace_region_in_file(
Path::new("README.md"),
&format!(r#"\[There are \d+ lints included in this crate!\]\({}\)"#, DOCS_LINK),
"",
true,
update_mode == UpdateMode::Change,
|| {
vec![format!(
"[There are {} lints included in this crate!]({})",
usable_lint_count, DOCS_LINK
)]
},
)
.changed;
file_change |= replace_region_in_file(
Path::new("CHANGELOG.md"),
"<!-- begin autogenerated links to lint list -->",
"<!-- end autogenerated links to lint list -->",
false,
update_mode == UpdateMode::Change,
|| gen_changelog_lint_list(lint_list.clone()),
)
.changed;
file_change |= replace_region_in_file(
Path::new("clippy_lints/src/lib.rs"),
"begin deprecated lints",
"end deprecated lints",
false,
update_mode == UpdateMode::Change,
|| gen_deprecated(&lint_list),
)
.changed;
file_change |= replace_region_in_file(
Path::new("clippy_lints/src/lib.rs"),
"begin register lints",
"end register lints",
false,
update_mode == UpdateMode::Change,
|| gen_register_lint_list(&lint_list),
)
.changed;
file_change |= replace_region_in_file(
Path::new("clippy_lints/src/lib.rs"),
"begin lints modules",
"end lints modules",
false,
update_mode == UpdateMode::Change,
|| gen_modules_list(lint_list.clone()),
)
.changed;
// Generate lists of lints in the clippy::all lint group
file_change |= replace_region_in_file(
Path::new("clippy_lints/src/lib.rs"),
r#"store.register_group\(true, "clippy::all""#,
r#"\]\);"#,
false,
update_mode == UpdateMode::Change,
|| {
// clippy::all should only include the following lint groups:
let all_group_lints = usable_lints
.clone()
.into_iter()
.filter(|l| {
l.group == "correctness" || l.group == "style" || l.group == "complexity" || l.group == "perf"
})
.collect();
gen_lint_group_list(all_group_lints)
},
)
.changed;
// Generate the list of lints for all other lint groups
for (lint_group, lints) in Lint::by_lint_group(usable_lints.into_iter().chain(internal_lints)) {
file_change |= replace_region_in_file(
Path::new("clippy_lints/src/lib.rs"),
&format!("store.register_group\\(true, \"clippy::{}\"", lint_group),
r#"\]\);"#,
false,
update_mode == UpdateMode::Change,
|| gen_lint_group_list(lints.clone()),
)
.changed;
}
if update_mode == UpdateMode::Check && file_change {
println!(
"Not all lints defined properly. \
Please run `cargo dev update_lints` to make sure all lints are defined properly."
);
std::process::exit(1);
}
}

View File

@ -1,10 +1,15 @@
use clippy_dev::clippy_project_root; use crate::clippy_project_root;
use std::fs::{File, OpenOptions}; use std::fs::{File, OpenOptions};
use std::io; use std::io;
use std::io::prelude::*; use std::io::prelude::*;
use std::io::ErrorKind; use std::io::ErrorKind;
use std::path::Path; use std::path::Path;
/// Creates files required to implement and test a new lint and runs `update_lints`.
///
/// # Errors
///
/// This function errors, if the files couldn't be created
pub fn create(pass: Option<&str>, lint_name: Option<&str>, category: Option<&str>) -> Result<(), io::Error> { pub fn create(pass: Option<&str>, lint_name: Option<&str>, category: Option<&str>) -> Result<(), io::Error> {
let pass = pass.expect("`pass` argument is validated by clap"); let pass = pass.expect("`pass` argument is validated by clap");
let lint_name = lint_name.expect("`name` argument is validated by clap"); let lint_name = lint_name.expect("`name` argument is validated by clap");

View File

@ -1,11 +1,9 @@
use crate::clippy_project_root;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::fs; use std::fs;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use walkdir::WalkDir; use walkdir::WalkDir;
use clippy_dev::clippy_project_root;
// 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.

View File

@ -0,0 +1,162 @@
use crate::{
gather_all, gen_changelog_lint_list, gen_deprecated, gen_lint_group_list, gen_modules_list, gen_register_lint_list,
replace_region_in_file, Lint, DOCS_LINK,
};
use std::path::Path;
#[derive(Clone, Copy, PartialEq)]
pub enum UpdateMode {
Check,
Change,
}
#[allow(clippy::too_many_lines)]
pub fn run(update_mode: UpdateMode) {
let lint_list: Vec<Lint> = gather_all().collect();
let internal_lints = Lint::internal_lints(&lint_list);
let deprecated_lints = Lint::deprecated_lints(&lint_list);
let usable_lints = Lint::usable_lints(&lint_list);
let mut sorted_usable_lints = usable_lints.clone();
sorted_usable_lints.sort_by_key(|lint| lint.name.clone());
let usable_lint_count = round_to_fifty(usable_lints.len());
let mut file_change = replace_region_in_file(
Path::new("src/lintlist/mod.rs"),
"begin lint list",
"end lint list",
false,
update_mode == UpdateMode::Change,
|| {
format!("pub static ref ALL_LINTS: Vec<Lint> = vec!{:#?};", sorted_usable_lints)
.lines()
.map(ToString::to_string)
.collect::<Vec<_>>()
},
)
.changed;
file_change |= replace_region_in_file(
Path::new("README.md"),
&format!(
r#"\[There are over \d+ lints included in this crate!\]\({}\)"#,
DOCS_LINK
),
"",
true,
update_mode == UpdateMode::Change,
|| {
vec![format!(
"[There are over {} lints included in this crate!]({})",
usable_lint_count, DOCS_LINK
)]
},
)
.changed;
file_change |= replace_region_in_file(
Path::new("CHANGELOG.md"),
"<!-- begin autogenerated links to lint list -->",
"<!-- end autogenerated links to lint list -->",
false,
update_mode == UpdateMode::Change,
|| gen_changelog_lint_list(usable_lints.iter().chain(deprecated_lints.iter())),
)
.changed;
file_change |= replace_region_in_file(
Path::new("clippy_lints/src/lib.rs"),
"begin deprecated lints",
"end deprecated lints",
false,
update_mode == UpdateMode::Change,
|| gen_deprecated(deprecated_lints.iter()),
)
.changed;
file_change |= replace_region_in_file(
Path::new("clippy_lints/src/lib.rs"),
"begin register lints",
"end register lints",
false,
update_mode == UpdateMode::Change,
|| gen_register_lint_list(usable_lints.iter().chain(internal_lints.iter())),
)
.changed;
file_change |= replace_region_in_file(
Path::new("clippy_lints/src/lib.rs"),
"begin lints modules",
"end lints modules",
false,
update_mode == UpdateMode::Change,
|| gen_modules_list(usable_lints.iter()),
)
.changed;
// Generate lists of lints in the clippy::all lint group
file_change |= replace_region_in_file(
Path::new("clippy_lints/src/lib.rs"),
r#"store.register_group\(true, "clippy::all""#,
r#"\]\);"#,
false,
update_mode == UpdateMode::Change,
|| {
// clippy::all should only include the following lint groups:
let all_group_lints = usable_lints.iter().filter(|l| {
l.group == "correctness" || l.group == "style" || l.group == "complexity" || l.group == "perf"
});
gen_lint_group_list(all_group_lints)
},
)
.changed;
// Generate the list of lints for all other lint groups
for (lint_group, lints) in Lint::by_lint_group(usable_lints.into_iter().chain(internal_lints)) {
file_change |= replace_region_in_file(
Path::new("clippy_lints/src/lib.rs"),
&format!("store.register_group\\(true, \"clippy::{}\"", lint_group),
r#"\]\);"#,
false,
update_mode == UpdateMode::Change,
|| gen_lint_group_list(lints.iter()),
)
.changed;
}
if update_mode == UpdateMode::Check && file_change {
println!(
"Not all lints defined properly. \
Please run `cargo dev update_lints` to make sure all lints are defined properly."
);
std::process::exit(1);
}
}
pub fn print_lints() {
let lint_list: Vec<Lint> = gather_all().collect();
let usable_lints = Lint::usable_lints(&lint_list);
let usable_lint_count = usable_lints.len();
let grouped_by_lint_group = Lint::by_lint_group(usable_lints.into_iter());
for (lint_group, mut lints) in grouped_by_lint_group {
if lint_group == "Deprecated" {
continue;
}
println!("\n## {}", lint_group);
lints.sort_by_key(|l| l.name.clone());
for lint in lints {
println!("* [{}]({}#{}) ({})", lint.name, DOCS_LINK, lint.name, lint.desc);
}
}
println!("there are {} lints", usable_lint_count);
}
fn round_to_fifty(count: usize) -> usize {
count / 50 * 50
}

View File

@ -1,6 +1,6 @@
use rustc::lint::in_external_macro;
use rustc_ast::ast::{Expr, ExprKind}; use rustc_ast::ast::{Expr, ExprKind};
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use crate::utils::span_lint_and_help; use crate::utils::span_lint_and_help;

View File

@ -3,11 +3,11 @@ use crate::utils::{
}; };
use crate::utils::{higher, sugg}; use crate::utils::{higher, sugg};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::hir::map::Map;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! { declare_clippy_lint! {
@ -77,7 +77,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
}, },
hir::ExprKind::Assign(assignee, e, _) => { hir::ExprKind::Assign(assignee, e, _) => {
if let hir::ExprKind::Binary(op, l, r) = &e.kind { if let hir::ExprKind::Binary(op, l, r) = &e.kind {
#[allow(clippy::cognitive_complexity)]
let lint = |assignee: &hir::Expr<'_>, rhs: &hir::Expr<'_>| { let lint = |assignee: &hir::Expr<'_>, rhs: &hir::Expr<'_>| {
let ty = cx.tables.expr_ty(assignee); let ty = cx.tables.expr_ty(assignee);
let rty = cx.tables.expr_ty(rhs); let rty = cx.tables.expr_ty(rhs);

View File

@ -1,9 +1,9 @@
use crate::utils::{match_def_path, span_lint_and_help}; use crate::utils::{match_def_path, span_lint_and_help};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::{Expr, ExprKind}; use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! { declare_clippy_lint! {

View File

@ -6,8 +6,6 @@ use crate::utils::{
span_lint_and_then, without_block_comments, span_lint_and_then, without_block_comments,
}; };
use if_chain::if_chain; use if_chain::if_chain;
use rustc::lint::in_external_macro;
use rustc::ty;
use rustc_ast::ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem}; use rustc_ast::ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
use rustc_ast::util::lev_distance::find_best_match_for_name; use rustc_ast::util::lev_distance::find_best_match_for_name;
use rustc_errors::Applicability; use rustc_errors::Applicability;
@ -15,6 +13,8 @@ use rustc_hir::{
Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind, Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind,
}; };
use rustc_lint::{CheckLintNameResult, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_lint::{CheckLintNameResult, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;

View File

@ -87,7 +87,7 @@ declare_clippy_lint! {
/// **Example:** /// **Example:**
/// ```rust /// ```rust
/// # let x = 1; /// # let x = 1;
/// if x & 0x1111 == 0 { } /// if x & 0b1111 == 0 { }
/// ``` /// ```
pub VERBOSE_BIT_MASK, pub VERBOSE_BIT_MASK,
style, style,

View File

@ -1,10 +1,10 @@
use crate::utils::{differing_macro_contexts, higher, snippet_block_with_applicability, span_lint, span_lint_and_sugg}; use crate::utils::{differing_macro_contexts, higher, snippet_block_with_applicability, span_lint, span_lint_and_sugg};
use rustc::hir::map::Map;
use rustc::lint::in_external_macro;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc_hir::{BlockCheckMode, Expr, ExprKind}; use rustc_hir::{BlockCheckMode, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::map::Map;
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! { declare_clippy_lint! {

View File

@ -1,14 +1,14 @@
use crate::utils::{ use crate::utils::{
get_trait_def_id, implements_trait, in_macro, match_type, paths, snippet_opt, span_lint_and_sugg, get_trait_def_id, implements_trait, in_macro, is_type_diagnostic_item, paths, snippet_opt, span_lint_and_sugg,
span_lint_and_then, SpanlessEq, span_lint_and_then, SpanlessEq,
}; };
use if_chain::if_chain; use if_chain::if_chain;
use rustc::hir::map::Map;
use rustc_ast::ast::LitKind; use rustc_ast::ast::LitKind;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor};
use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, UnOp}; use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, UnOp};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
@ -249,7 +249,9 @@ fn simplify_not(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<String> {
}, },
ExprKind::MethodCall(path, _, args) if args.len() == 1 => { ExprKind::MethodCall(path, _, args) if args.len() == 1 => {
let type_of_receiver = cx.tables.expr_ty(&args[0]); let type_of_receiver = cx.tables.expr_ty(&args[0]);
if !match_type(cx, type_of_receiver, &paths::OPTION) && !match_type(cx, type_of_receiver, &paths::RESULT) { if !is_type_diagnostic_item(cx, type_of_receiver, sym!(option_type))
&& !is_type_diagnostic_item(cx, type_of_receiver, sym!(result_type))
{
return None; return None;
} }
METHODS_WITH_NEGATION METHODS_WITH_NEGATION

View File

@ -3,11 +3,11 @@ use crate::utils::{
span_lint_and_sugg, walk_ptrs_ty, span_lint_and_sugg, walk_ptrs_ty,
}; };
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty;
use rustc_ast::ast::{Name, UintTy}; use rustc_ast::ast::{Name, UintTy};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, UnOp}; use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! { declare_clippy_lint! {

View File

@ -1,11 +1,11 @@
//! lint on manually implemented checked conversions that could be transformed into `try_from` //! lint on manually implemented checked conversions that could be transformed into `try_from`
use if_chain::if_chain; use if_chain::if_chain;
use rustc::lint::in_external_macro;
use rustc_ast::ast::LitKind; use rustc_ast::ast::LitKind;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, QPath, TyKind}; use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, QPath, TyKind};
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use crate::utils::{snippet_with_applicability, span_lint_and_sugg, SpanlessEq}; use crate::utils::{snippet_with_applicability, span_lint_and_sugg, SpanlessEq};
@ -21,7 +21,7 @@ declare_clippy_lint! {
/// ```rust /// ```rust
/// # let foo: u32 = 5; /// # let foo: u32 = 5;
/// # let _ = /// # let _ =
/// foo <= i32::max_value() as u32 /// foo <= i32::MAX as u32
/// # ; /// # ;
/// ``` /// ```
/// ///
@ -179,7 +179,7 @@ impl ConversionType {
} }
} }
/// Check for `expr <= (to_type::max_value() as from_type)` /// Check for `expr <= (to_type::MAX as from_type)`
fn check_upper_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> { fn check_upper_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> {
if_chain! { if_chain! {
if let ExprKind::Binary(ref op, ref left, ref right) = &expr.kind; if let ExprKind::Binary(ref op, ref left, ref right) = &expr.kind;
@ -194,7 +194,7 @@ fn check_upper_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> {
} }
} }
/// Check for `expr >= 0|(to_type::min_value() as from_type)` /// Check for `expr >= 0|(to_type::MIN as from_type)`
fn check_lower_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> { fn check_lower_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> {
fn check_function<'a>(candidate: &'a Expr<'a>, check: &'a Expr<'a>) -> Option<Conversion<'a>> { fn check_function<'a>(candidate: &'a Expr<'a>, check: &'a Expr<'a>) -> Option<Conversion<'a>> {
(check_lower_bound_zero(candidate, check)).or_else(|| (check_lower_bound_min(candidate, check))) (check_lower_bound_zero(candidate, check)).or_else(|| (check_lower_bound_min(candidate, check)))
@ -222,7 +222,7 @@ fn check_lower_bound_zero<'a>(candidate: &'a Expr<'_>, check: &'a Expr<'_>) -> O
} }
} }
/// Check for `expr >= (to_type::min_value() as from_type)` /// Check for `expr >= (to_type::MIN as from_type)`
fn check_lower_bound_min<'a>(candidate: &'a Expr<'_>, check: &'a Expr<'_>) -> Option<Conversion<'a>> { fn check_lower_bound_min<'a>(candidate: &'a Expr<'_>, check: &'a Expr<'_>) -> Option<Conversion<'a>> {
if let Some((from, to)) = get_types_from_cast(check, MIN_VALUE, SINTS) { if let Some((from, to)) = get_types_from_cast(check, MIN_VALUE, SINTS) {
Conversion::try_new(candidate, from, to) Conversion::try_new(candidate, from, to)

View File

@ -1,15 +1,15 @@
//! calculate cognitive complexity and warn about overly complex functions //! calculate cognitive complexity and warn about overly complex functions
use rustc::hir::map::Map;
use rustc_ast::ast::Attribute; use rustc_ast::ast::Attribute;
use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor};
use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId}; use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId};
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::map::Map;
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
use rustc_span::BytePos; use rustc_span::BytePos;
use crate::utils::{match_type, paths, snippet_opt, span_lint_and_help, LimitStack}; use crate::utils::{is_type_diagnostic_item, snippet_opt, span_lint_and_help, LimitStack};
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for methods with high cognitive complexity. /// **What it does:** Checks for methods with high cognitive complexity.
@ -22,7 +22,7 @@ declare_clippy_lint! {
/// ///
/// **Example:** No. You'll see it when you get the warning. /// **Example:** No. You'll see it when you get the warning.
pub COGNITIVE_COMPLEXITY, pub COGNITIVE_COMPLEXITY,
complexity, nursery,
"functions that should be split up into multiple functions" "functions that should be split up into multiple functions"
} }
@ -61,7 +61,7 @@ impl CognitiveComplexity {
helper.visit_expr(expr); helper.visit_expr(expr);
let CCHelper { cc, returns } = helper; let CCHelper { cc, returns } = helper;
let ret_ty = cx.tables.node_type(expr.hir_id); let ret_ty = cx.tables.node_type(expr.hir_id);
let ret_adjust = if match_type(cx, ret_ty, &paths::RESULT) { let ret_adjust = if is_type_diagnostic_item(cx, ret_ty, sym!(result_type)) {
returns returns
} else { } else {
#[allow(clippy::integer_division)] #[allow(clippy::integer_division)]

View File

@ -2,14 +2,14 @@
use crate::utils::{clip, higher, sext, unsext}; use crate::utils::{clip, higher, sext, unsext};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty::subst::{Subst, SubstsRef};
use rustc::ty::{self, Ty, TyCtxt};
use rustc::{bug, span_bug};
use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, QPath, UnOp}; use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, QPath, UnOp};
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_middle::ty::subst::{Subst, SubstsRef};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
use std::cmp::Ordering::{self, Equal}; use std::cmp::Ordering::{self, Equal};
use std::convert::TryInto; use std::convert::TryInto;
@ -268,6 +268,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
} }
} }
}, },
ExprKind::Index(ref arr, ref index) => self.index(arr, index),
// TODO: add other expressions. // TODO: add other expressions.
_ => None, _ => None,
} }
@ -333,7 +334,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
.tcx .tcx
.const_eval_resolve(self.param_env, def_id, substs, None, None) .const_eval_resolve(self.param_env, def_id, substs, None, None)
.ok() .ok()
.map(|val| rustc::ty::Const::from_value(self.lcx.tcx, val, ty))?; .map(|val| rustc_middle::ty::Const::from_value(self.lcx.tcx, val, ty))?;
let result = miri_to_const(&result); let result = miri_to_const(&result);
if result.is_some() { if result.is_some() {
self.needed_resolution = true; self.needed_resolution = true;
@ -345,6 +346,31 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
} }
} }
fn index(&mut self, lhs: &'_ Expr<'_>, index: &'_ Expr<'_>) -> Option<Constant> {
let lhs = self.expr(lhs);
let index = self.expr(index);
match (lhs, index) {
(Some(Constant::Vec(vec)), Some(Constant::Int(index))) => match vec[index as usize] {
Constant::F32(x) => Some(Constant::F32(x)),
Constant::F64(x) => Some(Constant::F64(x)),
_ => None,
},
(Some(Constant::Vec(vec)), _) => {
if !vec.is_empty() && vec.iter().all(|x| *x == vec[0]) {
match vec[0] {
Constant::F32(x) => Some(Constant::F32(x)),
Constant::F64(x) => Some(Constant::F64(x)),
_ => None,
}
} else {
None
}
},
_ => None,
}
}
/// A block can only yield a constant if it only has one constant expression. /// A block can only yield a constant if it only has one constant expression.
fn block(&mut self, block: &Block<'_>) -> Option<Constant> { fn block(&mut self, block: &Block<'_>) -> Option<Constant> {
if block.stmts.is_empty() { if block.stmts.is_empty() {
@ -460,7 +486,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
} }
pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> { pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> {
use rustc::mir::interpret::{ConstValue, Scalar}; use rustc_middle::mir::interpret::{ConstValue, Scalar};
match result.val { match result.val {
ty::ConstKind::Value(ConstValue::Scalar(Scalar::Raw { data: d, .. })) => match result.ty.kind { ty::ConstKind::Value(ConstValue::Scalar(Scalar::Raw { data: d, .. })) => match result.ty.kind {
ty::Bool => Some(Constant::Bool(d == 1)), ty::Bool => Some(Constant::Bool(d == 1)),
@ -492,6 +518,41 @@ pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> {
}, },
_ => None, _ => None,
}, },
ty::ConstKind::Value(ConstValue::ByRef { alloc, offset: _ }) => match result.ty.kind {
ty::Array(sub_type, len) => match sub_type.kind {
ty::Float(FloatTy::F32) => match miri_to_const(len) {
Some(Constant::Int(len)) => alloc
.inspect_with_undef_and_ptr_outside_interpreter(0..(4 * len as usize))
.to_owned()
.chunks(4)
.map(|chunk| {
Some(Constant::F32(f32::from_le_bytes(
chunk.try_into().expect("this shouldn't happen"),
)))
})
.collect::<Option<Vec<Constant>>>()
.map(Constant::Vec),
_ => None,
},
ty::Float(FloatTy::F64) => match miri_to_const(len) {
Some(Constant::Int(len)) => alloc
.inspect_with_undef_and_ptr_outside_interpreter(0..(8 * len as usize))
.to_owned()
.chunks(8)
.map(|chunk| {
Some(Constant::F64(f64::from_le_bytes(
chunk.try_into().expect("this shouldn't happen"),
)))
})
.collect::<Option<Vec<Constant>>>()
.map(Constant::Vec),
_ => None,
},
// FIXME: implement other array type conversions.
_ => None,
},
_ => None,
},
// FIXME: implement other conversions. // FIXME: implement other conversions.
_ => None, _ => None,
} }

View File

@ -1,9 +1,9 @@
use crate::utils::{get_parent_expr, higher, if_sequence, same_tys, snippet, span_lint_and_note, span_lint_and_then}; use crate::utils::{get_parent_expr, higher, if_sequence, same_tys, snippet, span_lint_and_note, span_lint_and_then};
use crate::utils::{SpanlessEq, SpanlessHash}; use crate::utils::{SpanlessEq, SpanlessHash};
use rustc::ty::Ty;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_hir::{Arm, Block, Expr, ExprKind, MatchSource, Pat, PatKind}; use rustc_hir::{Arm, Block, Expr, ExprKind, MatchSource, Pat, PatKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::Ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;

View File

@ -1,8 +1,8 @@
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, QPath}; use rustc_hir::{Expr, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use crate::utils::{any_parent_is_automatically_derived, match_def_path, paths, span_lint_and_sugg}; use crate::utils::{any_parent_is_automatically_derived, match_def_path, paths, span_lint_and_sugg};

View File

@ -147,3 +147,11 @@ declare_deprecated_lint! {
pub UNUSED_LABEL, pub UNUSED_LABEL,
"this lint has been uplifted to rustc and is now called `unused_labels`" "this lint has been uplifted to rustc and is now called `unused_labels`"
} }
declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** Associated-constants are now preferred.
pub REPLACE_CONSTS,
"associated-constants `MIN`/`MAX` of integers are prefer to `{min,max}_value()` and module constants"
}

View File

@ -1,9 +1,9 @@
use crate::utils::paths; use crate::utils::paths;
use crate::utils::{is_automatically_derived, is_copy, match_path, span_lint_and_then}; use crate::utils::{is_automatically_derived, is_copy, match_path, span_lint_and_then};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty::{self, Ty};
use rustc_hir::{Item, ItemKind, TraitRef}; use rustc_hir::{Item, ItemKind, TraitRef};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
@ -94,7 +94,8 @@ fn check_hash_peq<'a, 'tcx>(
if_chain! { if_chain! {
if match_path(&trait_ref.path, &paths::HASH); if match_path(&trait_ref.path, &paths::HASH);
if let Some(peq_trait_def_id) = cx.tcx.lang_items().eq_trait(); if let Some(peq_trait_def_id) = cx.tcx.lang_items().eq_trait();
if !&trait_ref.trait_def_id().is_local(); if let Some(def_id) = &trait_ref.trait_def_id();
if !def_id.is_local();
then { then {
// Look for the PartialEq implementations for `ty` // Look for the PartialEq implementations for `ty`
cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| { cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| {

View File

@ -1,12 +1,12 @@
use crate::utils::{implements_trait, is_entrypoint_fn, match_type, paths, return_ty, span_lint}; use crate::utils::{implements_trait, is_entrypoint_fn, is_type_diagnostic_item, return_ty, span_lint};
use if_chain::if_chain; use if_chain::if_chain;
use itertools::Itertools; use itertools::Itertools;
use rustc::lint::in_external_macro;
use rustc::ty;
use rustc_ast::ast::{AttrKind, Attribute}; use rustc_ast::ast::{AttrKind, Attribute};
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::{BytePos, MultiSpan, Span}; use rustc_span::source_map::{BytePos, MultiSpan, Span};
use rustc_span::Pos; use rustc_span::Pos;
@ -217,7 +217,7 @@ fn lint_for_missing_headers<'a, 'tcx>(
); );
} }
if !headers.errors { if !headers.errors {
if match_type(cx, return_ty(cx, hir_id), &paths::RESULT) { if is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym!(result_type)) {
span_lint( span_lint(
cx, cx,
MISSING_ERRORS_DOC, MISSING_ERRORS_DOC,
@ -229,13 +229,13 @@ fn lint_for_missing_headers<'a, 'tcx>(
if let Some(body_id) = body_id; if let Some(body_id) = body_id;
if let Some(future) = cx.tcx.lang_items().future_trait(); if let Some(future) = cx.tcx.lang_items().future_trait();
let def_id = cx.tcx.hir().body_owner_def_id(body_id); let def_id = cx.tcx.hir().body_owner_def_id(body_id);
let mir = cx.tcx.optimized_mir(def_id); let mir = cx.tcx.optimized_mir(def_id.to_def_id());
let ret_ty = mir.return_ty(); let ret_ty = mir.return_ty();
if implements_trait(cx, ret_ty, future, &[]); if implements_trait(cx, ret_ty, future, &[]);
if let ty::Opaque(_, subs) = ret_ty.kind; if let ty::Opaque(_, subs) = ret_ty.kind;
if let Some(gen) = subs.types().next(); if let Some(gen) = subs.types().next();
if let ty::Generator(_, subs, _) = gen.kind; if let ty::Generator(_, subs, _) = gen.kind;
if match_type(cx, subs.as_generator().return_ty(), &paths::RESULT); if is_type_diagnostic_item(cx, subs.as_generator().return_ty(), sym!(result_type));
then { then {
span_lint( span_lint(
cx, cx,

View File

@ -1,8 +1,8 @@
use crate::utils::{is_copy, match_def_path, paths, qpath_res, span_lint_and_note}; use crate::utils::{is_copy, match_def_path, paths, qpath_res, span_lint_and_note};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty;
use rustc_hir::{Expr, ExprKind}; use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! { declare_clippy_lint! {

View File

@ -1,8 +1,8 @@
//! Lint on if expressions with an else if, but without a final else branch. //! Lint on if expressions with an else if, but without a final else branch.
use rustc::lint::in_external_macro;
use rustc_ast::ast::{Expr, ExprKind}; use rustc_ast::ast::{Expr, ExprKind};
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use crate::utils::span_lint_and_help; use crate::utils::span_lint_and_help;

View File

@ -2,11 +2,11 @@ use crate::utils::SpanlessEq;
use crate::utils::{get_item_name, higher, match_type, paths, snippet, snippet_opt}; use crate::utils::{get_item_name, higher, match_type, paths, snippet, snippet_opt};
use crate::utils::{snippet_with_applicability, span_lint_and_then, walk_ptrs_ty}; use crate::utils::{snippet_with_applicability, span_lint_and_then, walk_ptrs_ty};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::hir::map::Map;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc_hir::{BorrowKind, Expr, ExprKind, UnOp}; use rustc_hir::{BorrowKind, Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;

View File

@ -3,11 +3,11 @@
use crate::consts::{miri_to_const, Constant}; use crate::consts::{miri_to_const, Constant};
use crate::utils::span_lint; use crate::utils::span_lint;
use rustc::ty;
use rustc::ty::util::IntTypeExt;
use rustc_ast::ast::{IntTy, UintTy}; use rustc_ast::ast::{IntTy, UintTy};
use rustc_hir::{Item, ItemKind}; use rustc_hir::{Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_middle::ty::util::IntTypeExt;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use std::convert::TryFrom; use std::convert::TryFrom;
@ -46,12 +46,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant {
for var in def.variants { for var in def.variants {
if let Some(anon_const) = &var.disr_expr { if let Some(anon_const) = &var.disr_expr {
let def_id = cx.tcx.hir().body_owner_def_id(anon_const.body); let def_id = cx.tcx.hir().body_owner_def_id(anon_const.body);
let mut ty = cx.tcx.type_of(def_id); let mut ty = cx.tcx.type_of(def_id.to_def_id());
let constant = cx let constant = cx
.tcx .tcx
.const_eval_poly(def_id) .const_eval_poly(def_id.to_def_id())
.ok() .ok()
.map(|val| rustc::ty::Const::from_value(cx.tcx, val, ty)); .map(|val| rustc_middle::ty::Const::from_value(cx.tcx, val, ty));
if let Some(Constant::Int(val)) = constant.and_then(miri_to_const) { if let Some(Constant::Int(val)) = constant.and_then(miri_to_const) {
if let ty::Adt(adt, _) = ty.kind { if let ty::Adt(adt, _) = ty.kind {
if adt.is_enum() { if adt.is_enum() {

View File

@ -1,11 +1,11 @@
use rustc::ty::layout::LayoutOf;
use rustc::ty::{self, Ty};
use rustc_hir::intravisit; use rustc_hir::intravisit;
use rustc_hir::{self, Body, FnDecl, HirId, HirIdSet, ItemKind, Node}; use rustc_hir::{self, Body, FnDecl, HirId, HirIdSet, ItemKind, Node};
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
use rustc_target::abi::LayoutOf;
use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase}; use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase};
use crate::utils::span_lint; use crate::utils::span_lint;
@ -92,7 +92,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxedLocal {
} }
// TODO: Replace with Map::is_argument(..) when it's fixed // TODO: Replace with Map::is_argument(..) when it's fixed
fn is_argument(map: rustc::hir::map::Map<'_>, id: HirId) -> bool { fn is_argument(map: rustc_middle::hir::map::Map<'_>, id: HirId) -> bool {
match map.find(id) { match map.find(id) {
Some(Node::Binding(_)) => (), Some(Node::Binding(_)) => (),
_ => return false, _ => return false,

View File

@ -1,9 +1,9 @@
use if_chain::if_chain; use if_chain::if_chain;
use rustc::lint::in_external_macro;
use rustc::ty::{self, Ty};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{def_id, Expr, ExprKind, Param, PatKind, QPath}; use rustc_hir::{def_id, Expr, ExprKind, Param, PatKind, QPath};
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use crate::utils::{ use crate::utils::{

View File

@ -1,10 +1,10 @@
use crate::utils::{get_parent_expr, span_lint, span_lint_and_note}; use crate::utils::{get_parent_expr, span_lint, span_lint_and_note};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::hir::map::Map;
use rustc::ty;
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc_hir::{def, BinOpKind, Block, Expr, ExprKind, Guard, HirId, Local, Node, QPath, Stmt, StmtKind}; use rustc_hir::{def, BinOpKind, Block, Expr, ExprKind, Guard, HirId, Local, Node, QPath, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! { declare_clippy_lint! {

View File

@ -1,10 +1,12 @@
use crate::utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT, OPTION, RESULT}; use crate::utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT};
use crate::utils::{is_expn_of, match_def_path, method_chain_args, span_lint_and_then, walk_ptrs_ty}; use crate::utils::{
is_expn_of, is_type_diagnostic_item, match_def_path, method_chain_args, span_lint_and_then, walk_ptrs_ty,
};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::hir::map::Map;
use rustc::ty::{self, Ty};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::Span; use rustc_span::Span;
@ -76,7 +78,9 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it
// check for `unwrap` // check for `unwrap`
if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
let reciever_ty = walk_ptrs_ty(self.tables.expr_ty(&arglists[0][0])); let reciever_ty = walk_ptrs_ty(self.tables.expr_ty(&arglists[0][0]));
if match_type(self.lcx, reciever_ty, &OPTION) || match_type(self.lcx, reciever_ty, &RESULT) { if is_type_diagnostic_item(self.lcx, reciever_ty, sym!(option_type))
|| is_type_diagnostic_item(self.lcx, reciever_ty, sym!(result_type))
{
self.result.push(expr.span); self.result.push(expr.span);
} }
} }
@ -124,10 +128,3 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it
} }
} }
} }
fn match_type(cx: &LateContext<'_, '_>, ty: Ty<'_>, path: &[&str]) -> bool {
match ty.kind {
ty::Adt(adt, _) => match_def_path(cx, adt.did, path),
_ => false,
}
}

View File

@ -1,12 +1,12 @@
use crate::utils::{numeric_literal, span_lint_and_sugg}; use crate::utils::{numeric_literal, span_lint_and_sugg};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty;
use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use std::{f32, f64, fmt}; use std::fmt;
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for float literals with a precision greater /// **What it does:** Checks for float literals with a precision greater

View File

@ -4,10 +4,10 @@ use crate::consts::{
}; };
use crate::utils::{higher, numeric_literal, span_lint_and_sugg, sugg, SpanlessEq}; use crate::utils::{higher, numeric_literal, span_lint_and_sugg, sugg, SpanlessEq};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Spanned; use rustc_span::source_map::Spanned;

View File

@ -91,7 +91,7 @@ fn on_argumentv1_new<'a, 'tcx>(
if pats.len() == 1; if pats.len() == 1;
then { then {
let ty = walk_ptrs_ty(cx.tables.pat_ty(&pats[0])); let ty = walk_ptrs_ty(cx.tables.pat_ty(&pats[0]));
if ty.kind != rustc::ty::Str && !match_type(cx, ty, &paths::STRING) { if ty.kind != rustc_middle::ty::Str && !match_type(cx, ty, &paths::STRING) {
return None; return None;
} }
if let ExprKind::Lit(ref lit) = format_args.kind { if let ExprKind::Lit(ref lit) = format_args.kind {

View File

@ -1,8 +1,8 @@
use crate::utils::{differing_macro_contexts, snippet_opt, span_lint_and_help, span_lint_and_note}; use crate::utils::{differing_macro_contexts, snippet_opt, span_lint_and_help, span_lint_and_note};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::lint::in_external_macro;
use rustc_ast::ast::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp}; use rustc_ast::ast::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp};
use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;

View File

@ -3,9 +3,6 @@ use crate::utils::{
must_use_attr, qpath_res, return_ty, snippet, snippet_opt, span_lint, span_lint_and_help, span_lint_and_then, must_use_attr, qpath_res, return_ty, snippet, snippet_opt, span_lint, span_lint_and_help, span_lint_and_then,
trait_ref_of_method, type_is_unsafe_function, trait_ref_of_method, type_is_unsafe_function,
}; };
use rustc::hir::map::Map;
use rustc::lint::in_external_macro;
use rustc::ty::{self, Ty};
use rustc_ast::ast::Attribute; use rustc_ast::ast::Attribute;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability; use rustc_errors::Applicability;
@ -13,6 +10,9 @@ use rustc_hir as hir;
use rustc_hir::intravisit; use rustc_hir::intravisit;
use rustc_hir::{def::Res, def_id::DefId}; use rustc_hir::{def::Res, def_id::DefId};
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::map::Map;
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;

View File

@ -8,7 +8,6 @@ use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Spanned; use rustc_span::source_map::Spanned;
use rustc_span::symbol::Symbol;
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for using `x.get(x.len() - 1)` instead of /// **What it does:** Checks for using `x.get(x.len() - 1)` instead of
@ -51,12 +50,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for GetLastWithLen {
if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind; if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind;
// Method name is "get" // Method name is "get"
if path.ident.name == Symbol::intern("get"); if path.ident.name == sym!(get);
// Argument 0 (the struct we're calling the method on) is a vector // Argument 0 (the struct we're calling the method on) is a vector
if let Some(struct_calling_on) = args.get(0); if let Some(struct_calling_on) = args.get(0);
let struct_ty = cx.tables.expr_ty(struct_calling_on); let struct_ty = cx.tables.expr_ty(struct_calling_on);
if is_type_diagnostic_item(cx, struct_ty, Symbol::intern("vec_type")); if is_type_diagnostic_item(cx, struct_ty, sym!(vec_type));
// Argument to "get" is a subtraction // Argument to "get" is a subtraction
if let Some(get_index_arg) = args.get(1); if let Some(get_index_arg) = args.get(1);
@ -71,7 +70,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for GetLastWithLen {
// LHS of subtraction is "x.len()" // LHS of subtraction is "x.len()"
if let ExprKind::MethodCall(arg_lhs_path, _, lhs_args) = &lhs.kind; if let ExprKind::MethodCall(arg_lhs_path, _, lhs_args) = &lhs.kind;
if arg_lhs_path.ident.name == Symbol::intern("len"); if arg_lhs_path.ident.name == sym!(len);
if let Some(arg_lhs_struct) = lhs_args.get(0); if let Some(arg_lhs_struct) = lhs_args.get(0);
// The two vectors referenced (x in x.get(...) and in x.len()) // The two vectors referenced (x in x.get(...) and in x.len())

View File

@ -1,6 +1,6 @@
use rustc::ty;
use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;

View File

@ -1,7 +1,7 @@
use crate::utils::{match_type, method_chain_args, paths, snippet_with_applicability, span_lint_and_sugg}; use crate::utils::{is_type_diagnostic_item, method_chain_args, snippet_with_applicability, span_lint_and_sugg};
use if_chain::if_chain; use if_chain::if_chain;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{print, Expr, ExprKind, MatchSource, PatKind, QPath}; use rustc_hir::{Expr, ExprKind, MatchSource, PatKind, QPath};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
@ -45,8 +45,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OkIfLet {
if let ExprKind::MethodCall(_, ok_span, ref result_types) = op.kind; //check is expr.ok() has type Result<T,E>.ok() if let ExprKind::MethodCall(_, ok_span, ref result_types) = op.kind; //check is expr.ok() has type Result<T,E>.ok()
if let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _) = body[0].pat.kind; //get operation if let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _) = body[0].pat.kind; //get operation
if method_chain_args(op, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized; if method_chain_args(op, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized;
let is_result_type = match_type(cx, cx.tables.expr_ty(&result_types[0]), &paths::RESULT); if is_type_diagnostic_item(cx, cx.tables.expr_ty(&result_types[0]), sym!(result_type));
if print::to_string(print::NO_ANN, |s| s.print_path(x, false)) == "Some" && is_result_type; if rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(x, false)) == "Some";
then { then {
let mut applicability = Applicability::MachineApplicable; let mut applicability = Applicability::MachineApplicable;

View File

@ -1,9 +1,9 @@
//! lint on if branches that could be swapped so no `!` operation is necessary //! lint on if branches that could be swapped so no `!` operation is necessary
//! on the condition //! on the condition
use rustc::lint::in_external_macro;
use rustc_ast::ast::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_ast::ast::{BinOpKind, Expr, ExprKind, UnOp};
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use crate::utils::span_lint_and_help; use crate::utils::span_lint_and_help;

View File

@ -135,11 +135,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitReturn {
let def_id = cx.tcx.hir().body_owner_def_id(body.id()); let def_id = cx.tcx.hir().body_owner_def_id(body.id());
// Building MIR for `fn`s with unsatisfiable preds results in ICE. // Building MIR for `fn`s with unsatisfiable preds results in ICE.
if fn_has_unsatisfiable_preds(cx, def_id) { if fn_has_unsatisfiable_preds(cx, def_id.to_def_id()) {
return; return;
} }
let mir = cx.tcx.optimized_mir(def_id); let mir = cx.tcx.optimized_mir(def_id.to_def_id());
// 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

View File

@ -2,10 +2,10 @@
use crate::consts::{constant, Constant}; use crate::consts::{constant, Constant};
use crate::utils::{higher, span_lint, span_lint_and_help}; use crate::utils::{higher, span_lint, span_lint_and_help};
use rustc::ty;
use rustc_ast::ast::RangeLimits; use rustc_ast::ast::RangeLimits;
use rustc_hir::{Expr, ExprKind}; use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! { declare_clippy_lint! {

View File

@ -1,21 +1,24 @@
//! lint when there is a large size difference between variants on an enum //! lint when there is a large size difference between variants on an enum
use crate::utils::{snippet_opt, span_lint_and_then}; use crate::utils::{snippet_opt, span_lint_and_then};
use rustc::ty::layout::LayoutOf;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{Item, ItemKind, VariantData}; use rustc_hir::{Item, ItemKind, VariantData};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_target::abi::LayoutOf;
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for large size differences between variants on /// **What it does:** Checks for large size differences between variants on
/// `enum`s. /// `enum`s.
/// ///
/// **Why is this bad?** Enum size is bounded by the largest variant. Having a /// **Why is this bad?** Enum size is bounded by the largest variant. Having a
/// large variant /// large variant can penalize the memory layout of that enum.
/// can penalize the memory layout of that enum.
/// ///
/// **Known problems:** None. /// **Known problems:** This lint obviously cannot take the distribution of
/// variants in your running program into account. It is possible that the
/// smaller variants make up less than 1% of all instances, in which case
/// the overhead is negligible and the boxing is counter-productive. Always
/// measure the change this lint suggests.
/// ///
/// **Example:** /// **Example:**
/// ```rust /// ```rust
@ -52,8 +55,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant {
let ty = cx.tcx.type_of(did); let ty = cx.tcx.type_of(did);
let adt = ty.ty_adt_def().expect("already checked whether this is an enum"); let adt = ty.ty_adt_def().expect("already checked whether this is an enum");
let mut smallest_variant: Option<(_, _)> = None;
let mut largest_variant: Option<(_, _)> = None; let mut largest_variant: Option<(_, _)> = None;
let mut second_variant: Option<(_, _)> = None;
for (i, variant) in adt.variants.iter().enumerate() { for (i, variant) in adt.variants.iter().enumerate() {
let size: u64 = variant let size: u64 = variant
@ -69,12 +72,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant {
let grouped = (size, (i, variant)); let grouped = (size, (i, variant));
update_if(&mut smallest_variant, grouped, |a, b| b.0 <= a.0); if grouped.0 >= largest_variant.map_or(0, |x| x.0) {
update_if(&mut largest_variant, grouped, |a, b| b.0 >= a.0); second_variant = largest_variant;
largest_variant = Some(grouped);
}
} }
if let (Some(smallest), Some(largest)) = (smallest_variant, largest_variant) { if let (Some(largest), Some(second)) = (largest_variant, second_variant) {
let difference = largest.0 - smallest.0; let difference = largest.0 - second.0;
if difference > self.maximum_size_difference_allowed { if difference > self.maximum_size_difference_allowed {
let (i, variant) = largest.1; let (i, variant) = largest.1;
@ -114,16 +119,3 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant {
} }
} }
} }
fn update_if<T, F>(old: &mut Option<T>, new: T, f: F)
where
F: Fn(&T, &T) -> bool,
{
if let Some(ref mut val) = *old {
if f(val, &new) {
*val = new;
}
} else {
*old = Some(new);
}
}

View File

@ -1,7 +1,7 @@
use rustc::mir::interpret::ConstValue;
use rustc::ty::{self, ConstKind};
use rustc_hir::{Expr, ExprKind}; use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::interpret::ConstValue;
use rustc_middle::ty::{self, ConstKind};
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use if_chain::if_chain; use if_chain::if_chain;

View File

@ -1,11 +1,11 @@
use crate::utils::{get_item_name, snippet_with_applicability, span_lint, span_lint_and_sugg, walk_ptrs_ty}; use crate::utils::{get_item_name, snippet_with_applicability, span_lint, span_lint_and_sugg, walk_ptrs_ty};
use rustc::ty;
use rustc_ast::ast::{LitKind, Name}; use rustc_ast::ast::{LitKind, Name};
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::{AssocItemKind, BinOpKind, Expr, ExprKind, ImplItemRef, Item, ItemKind, TraitItemRef}; use rustc_hir::{AssocItemKind, BinOpKind, Expr, ExprKind, ImplItemRef, Item, ItemKind, TraitItemRef};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::{Span, Spanned}; use rustc_span::source_map::{Span, Spanned};
@ -121,7 +121,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero {
fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item<'_>, trait_items: &[TraitItemRef]) { fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item<'_>, trait_items: &[TraitItemRef]) {
fn is_named_self(cx: &LateContext<'_, '_>, item: &TraitItemRef, name: &str) -> bool { fn is_named_self(cx: &LateContext<'_, '_>, item: &TraitItemRef, name: &str) -> bool {
item.ident.name.as_str() == name item.ident.name.as_str() == name
&& if let AssocItemKind::Method { has_self } = item.kind { && if let AssocItemKind::Fn { has_self } = item.kind {
has_self && { has_self && {
let did = cx.tcx.hir().local_def_id(item.id.hir_id); let did = cx.tcx.hir().local_def_id(item.id.hir_id);
cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1
@ -149,8 +149,8 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item<'_>, trait_i
.iter() .iter()
.flat_map(|&i| cx.tcx.associated_items(i).in_definition_order()) .flat_map(|&i| cx.tcx.associated_items(i).in_definition_order())
.any(|i| { .any(|i| {
i.kind == ty::AssocKind::Method i.kind == ty::AssocKind::Fn
&& i.method_has_self_argument && i.fn_has_self_parameter
&& i.ident.name == sym!(is_empty) && i.ident.name == sym!(is_empty)
&& cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1 && cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1
}); });
@ -172,7 +172,7 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item<'_>, trait_i
fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item<'_>, impl_items: &[ImplItemRef<'_>]) { fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item<'_>, impl_items: &[ImplItemRef<'_>]) {
fn is_named_self(cx: &LateContext<'_, '_>, item: &ImplItemRef<'_>, name: &str) -> bool { fn is_named_self(cx: &LateContext<'_, '_>, item: &ImplItemRef<'_>, name: &str) -> bool {
item.ident.name.as_str() == name item.ident.name.as_str() == name
&& if let AssocItemKind::Method { has_self } = item.kind { && if let AssocItemKind::Fn { has_self } = item.kind {
has_self && { has_self && {
let did = cx.tcx.hir().local_def_id(item.id.hir_id); let did = cx.tcx.hir().local_def_id(item.id.hir_id);
cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1
@ -261,7 +261,7 @@ fn check_len(
fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
/// Gets an `AssocItem` and return true if it matches `is_empty(self)`. /// Gets an `AssocItem` and return true if it matches `is_empty(self)`.
fn is_is_empty(cx: &LateContext<'_, '_>, item: &ty::AssocItem) -> bool { fn is_is_empty(cx: &LateContext<'_, '_>, item: &ty::AssocItem) -> bool {
if let ty::AssocKind::Method = item.kind { if let ty::AssocKind::Fn = item.kind {
if item.ident.name.as_str() == "is_empty" { if item.ident.name.as_str() == "is_empty" {
let sig = cx.tcx.fn_sig(item.def_id); let sig = cx.tcx.fn_sig(item.def_id);
let ty = sig.skip_binder(); let ty = sig.skip_binder();

View File

@ -1,12 +1,12 @@
use crate::utils::{higher, qpath_res, snippet, span_lint_and_then}; use crate::utils::{higher, qpath_res, snippet, span_lint_and_then};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::hir::map::Map;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::Res; use rustc_hir::def::Res;
use rustc_hir::intravisit; use rustc_hir::intravisit;
use rustc_hir::BindingAnnotation; use rustc_hir::BindingAnnotation;
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! { declare_clippy_lint! {

View File

@ -1,7 +1,8 @@
use if_chain::if_chain; use if_chain::if_chain;
use rustc::lint::in_external_macro; use rustc_hir::{Local, PatKind};
use rustc_hir::{PatKind, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use crate::utils::{is_must_use_func_call, is_must_use_ty, match_type, paths, span_lint_and_help}; use crate::utils::{is_must_use_func_call, is_must_use_ty, match_type, paths, span_lint_and_help};
@ -66,22 +67,28 @@ const SYNC_GUARD_PATHS: [&[&str]; 3] = [
]; ];
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnderscore { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnderscore {
fn check_stmt(&mut self, cx: &LateContext<'_, '_>, stmt: &Stmt<'_>) { fn check_local(&mut self, cx: &LateContext<'_, '_>, local: &Local<'_>) {
if in_external_macro(cx.tcx.sess, stmt.span) { if in_external_macro(cx.tcx.sess, local.span) {
return; return;
} }
if_chain! { if_chain! {
if let StmtKind::Local(ref local) = stmt.kind;
if let PatKind::Wild = local.pat.kind; if let PatKind::Wild = local.pat.kind;
if let Some(ref init) = local.init; if let Some(ref init) = local.init;
then { then {
let check_ty = |ty| SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, ty, path)); let init_ty = cx.tables.expr_ty(init);
if cx.tables.expr_ty(init).walk().any(check_ty) { let contains_sync_guard = init_ty.walk().any(|inner| match inner.unpack() {
GenericArgKind::Type(inner_ty) => {
SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, inner_ty, path))
},
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
});
if contains_sync_guard {
span_lint_and_help( span_lint_and_help(
cx, cx,
LET_UNDERSCORE_LOCK, LET_UNDERSCORE_LOCK,
stmt.span, local.span,
"non-binding let on a synchronization lock", "non-binding let on a synchronization lock",
"consider using an underscore-prefixed named \ "consider using an underscore-prefixed named \
binding or dropping explicitly with `std::mem::drop`" binding or dropping explicitly with `std::mem::drop`"
@ -90,7 +97,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnderscore {
span_lint_and_help( span_lint_and_help(
cx, cx,
LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_MUST_USE,
stmt.span, local.span,
"non-binding let on an expression with `#[must_use]` type", "non-binding let on an expression with `#[must_use]` type",
"consider explicitly using expression value" "consider explicitly using expression value"
) )
@ -98,7 +105,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnderscore {
span_lint_and_help( span_lint_and_help(
cx, cx,
LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_MUST_USE,
stmt.span, local.span,
"non-binding let on a result of a `#[must_use]` function", "non-binding let on a result of a `#[must_use]` function",
"consider explicitly using function result" "consider explicitly using function result"
) )

View File

@ -18,8 +18,6 @@
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]
extern crate fmt_macros; extern crate fmt_macros;
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]
extern crate rustc;
#[allow(unused_extern_crates)]
extern crate rustc_ast; extern crate rustc_ast;
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]
extern crate rustc_ast_pretty; extern crate rustc_ast_pretty;
@ -34,6 +32,8 @@ extern crate rustc_errors;
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]
extern crate rustc_hir; extern crate rustc_hir;
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]
extern crate rustc_hir_pretty;
#[allow(unused_extern_crates)]
extern crate rustc_index; extern crate rustc_index;
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]
extern crate rustc_infer; extern crate rustc_infer;
@ -42,6 +42,8 @@ extern crate rustc_lexer;
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]
extern crate rustc_lint; extern crate rustc_lint;
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]
extern crate rustc_middle;
#[allow(unused_extern_crates)]
extern crate rustc_mir; extern crate rustc_mir;
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]
extern crate rustc_parse; extern crate rustc_parse;
@ -80,7 +82,7 @@ use rustc_session::Session;
/// ``` /// ```
/// # #![feature(rustc_private)] /// # #![feature(rustc_private)]
/// # #[allow(unused_extern_crates)] /// # #[allow(unused_extern_crates)]
/// # extern crate rustc; /// # extern crate rustc_middle;
/// # #[allow(unused_extern_crates)] /// # #[allow(unused_extern_crates)]
/// # extern crate rustc_session; /// # extern crate rustc_session;
/// # #[macro_use] /// # #[macro_use]
@ -168,157 +170,157 @@ mod consts;
mod utils; mod utils;
// begin lints modules, do not remove this comment, its used in `update_lints` // begin lints modules, do not remove this comment, its used in `update_lints`
pub mod approx_const; mod approx_const;
pub mod arithmetic; mod arithmetic;
pub mod as_conversions; mod as_conversions;
pub mod assertions_on_constants; mod assertions_on_constants;
pub mod assign_ops; mod assign_ops;
pub mod atomic_ordering; mod atomic_ordering;
pub mod attrs; mod attrs;
pub mod bit_mask; mod bit_mask;
pub mod blacklisted_name; mod blacklisted_name;
pub mod block_in_if_condition; mod block_in_if_condition;
pub mod booleans; mod booleans;
pub mod bytecount; mod bytecount;
pub mod cargo_common_metadata; mod cargo_common_metadata;
pub mod checked_conversions; mod checked_conversions;
pub mod cognitive_complexity; mod cognitive_complexity;
pub mod collapsible_if; mod collapsible_if;
pub mod comparison_chain; mod comparison_chain;
pub mod copies; mod copies;
pub mod copy_iterator; mod copy_iterator;
pub mod dbg_macro; mod dbg_macro;
pub mod default_trait_access; mod default_trait_access;
pub mod derive; mod derive;
pub mod doc; mod doc;
pub mod double_comparison; mod double_comparison;
pub mod double_parens; mod double_parens;
pub mod drop_bounds; mod drop_bounds;
pub mod drop_forget_ref; mod drop_forget_ref;
pub mod duration_subsec; mod duration_subsec;
pub mod else_if_without_else; mod else_if_without_else;
pub mod empty_enum; mod empty_enum;
pub mod entry; mod entry;
pub mod enum_clike; mod enum_clike;
pub mod enum_variants; mod enum_variants;
pub mod eq_op; mod eq_op;
pub mod erasing_op; mod erasing_op;
pub mod escape; mod escape;
pub mod eta_reduction; mod eta_reduction;
pub mod eval_order_dependence; mod eval_order_dependence;
pub mod excessive_bools; mod excessive_bools;
pub mod exit; mod exit;
pub mod explicit_write; mod explicit_write;
pub mod fallible_impl_from; mod fallible_impl_from;
pub mod float_literal; mod float_literal;
pub mod floating_point_arithmetic; mod floating_point_arithmetic;
pub mod format; mod format;
pub mod formatting; mod formatting;
pub mod functions; mod functions;
pub mod get_last_with_len; mod get_last_with_len;
pub mod identity_conversion; mod identity_conversion;
pub mod identity_op; mod identity_op;
pub mod if_let_some_result; mod if_let_some_result;
pub mod if_not_else; mod if_not_else;
pub mod implicit_return; mod implicit_return;
pub mod indexing_slicing; mod indexing_slicing;
pub mod infinite_iter; mod infinite_iter;
pub mod inherent_impl; mod inherent_impl;
pub mod inherent_to_string; mod inherent_to_string;
pub mod inline_fn_without_body; mod inline_fn_without_body;
pub mod int_plus_one; mod int_plus_one;
pub mod integer_division; mod integer_division;
pub mod items_after_statements; mod items_after_statements;
pub mod large_enum_variant; mod large_enum_variant;
pub mod large_stack_arrays; mod large_stack_arrays;
pub mod len_zero; mod len_zero;
pub mod let_if_seq; mod let_if_seq;
pub mod let_underscore; mod let_underscore;
pub mod lifetimes; mod lifetimes;
pub mod literal_representation; mod literal_representation;
pub mod loops; mod loops;
pub mod macro_use; mod macro_use;
pub mod main_recursion; mod main_recursion;
pub mod map_clone; mod map_clone;
pub mod map_unit_fn; mod map_unit_fn;
pub mod matches; mod matches;
pub mod mem_discriminant; mod mem_discriminant;
pub mod mem_forget; mod mem_forget;
pub mod mem_replace; mod mem_replace;
pub mod methods; mod methods;
pub mod minmax; mod minmax;
pub mod misc; mod misc;
pub mod misc_early; mod misc_early;
pub mod missing_const_for_fn; mod missing_const_for_fn;
pub mod missing_doc; mod missing_doc;
pub mod missing_inline; mod missing_inline;
pub mod modulo_arithmetic; mod modulo_arithmetic;
pub mod multiple_crate_versions; mod multiple_crate_versions;
pub mod mut_key; mod mut_key;
pub mod mut_mut; mod mut_mut;
pub mod mut_reference; mod mut_reference;
pub mod mutable_debug_assertion; mod mutable_debug_assertion;
pub mod mutex_atomic; mod mutex_atomic;
pub mod needless_bool; mod needless_bool;
pub mod needless_borrow; mod needless_borrow;
pub mod needless_borrowed_ref; mod needless_borrowed_ref;
pub mod needless_continue; mod needless_continue;
pub mod needless_pass_by_value; mod needless_pass_by_value;
pub mod needless_update; mod needless_update;
pub mod neg_cmp_op_on_partial_ord; mod neg_cmp_op_on_partial_ord;
pub mod neg_multiply; mod neg_multiply;
pub mod new_without_default; mod new_without_default;
pub mod no_effect; mod no_effect;
pub mod non_copy_const; mod non_copy_const;
pub mod non_expressive_names; mod non_expressive_names;
pub mod open_options; mod open_options;
pub mod option_env_unwrap; mod option_env_unwrap;
pub mod overflow_check_conditional; mod overflow_check_conditional;
pub mod panic_unimplemented; mod panic_unimplemented;
pub mod partialeq_ne_impl; mod partialeq_ne_impl;
pub mod path_buf_push_overwrite; mod path_buf_push_overwrite;
pub mod precedence; mod precedence;
pub mod ptr; mod ptr;
pub mod ptr_offset_with_cast; mod ptr_offset_with_cast;
pub mod question_mark; mod question_mark;
pub mod ranges; mod ranges;
pub mod redundant_clone; mod redundant_clone;
pub mod redundant_field_names; mod redundant_field_names;
pub mod redundant_pattern_matching; mod redundant_pattern_matching;
pub mod redundant_pub_crate; mod redundant_pub_crate;
pub mod redundant_static_lifetimes; mod redundant_static_lifetimes;
pub mod reference; mod reference;
pub mod regex; mod regex;
pub mod replace_consts; mod returns;
pub mod returns; mod serde_api;
pub mod serde_api; mod shadow;
pub mod shadow; mod single_component_path_imports;
pub mod single_component_path_imports; mod slow_vector_initialization;
pub mod slow_vector_initialization; mod strings;
pub mod strings; mod suspicious_trait_impl;
pub mod suspicious_trait_impl; mod swap;
pub mod swap; mod tabs_in_doc_comments;
pub mod tabs_in_doc_comments; mod temporary_assignment;
pub mod temporary_assignment; mod to_digit_is_some;
pub mod to_digit_is_some; mod trait_bounds;
pub mod trait_bounds; mod transmute;
pub mod transmute; mod transmuting_null;
pub mod transmuting_null; mod trivially_copy_pass_by_ref;
pub mod trivially_copy_pass_by_ref; mod try_err;
pub mod try_err; mod types;
pub mod types; mod unicode;
pub mod unicode; mod unnamed_address;
pub mod unsafe_removed_from_name; mod unsafe_removed_from_name;
pub mod unused_io_amount; mod unused_io_amount;
pub mod unused_self; mod unused_self;
pub mod unwrap; mod unwrap;
pub mod use_self; mod use_self;
pub mod vec; mod vec;
pub mod verbose_file_reads; mod verbose_file_reads;
pub mod wildcard_dependencies; mod wildcard_dependencies;
pub mod wildcard_imports; mod wildcard_imports;
pub mod write; mod write;
pub mod zero_div_zero; mod zero_div_zero;
// end lints modules, do not remove this comment, its used in `update_lints` // end lints modules, do not remove this comment, its used in `update_lints`
pub use crate::utils::conf::Conf; pub use crate::utils::conf::Conf;
@ -468,6 +470,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
"clippy::unused_label", "clippy::unused_label",
"this lint has been uplifted to rustc and is now called `unused_labels`", "this lint has been uplifted to rustc and is now called `unused_labels`",
); );
store.register_removed(
"clippy::replace_consts",
"associated-constants `MIN`/`MAX` of integers are prefer to `{min,max}_value()` and module constants",
);
// end deprecated lints, do not remove this comment, its used in `update_lints` // end deprecated lints, do not remove this comment, its used in `update_lints`
// begin register lints, do not remove this comment, its used in `update_lints` // begin register lints, do not remove this comment, its used in `update_lints`
@ -660,6 +666,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&methods::OPTION_UNWRAP_USED, &methods::OPTION_UNWRAP_USED,
&methods::OR_FUN_CALL, &methods::OR_FUN_CALL,
&methods::RESULT_EXPECT_USED, &methods::RESULT_EXPECT_USED,
&methods::RESULT_MAP_OR_INTO_OPTION,
&methods::RESULT_MAP_UNWRAP_OR_ELSE, &methods::RESULT_MAP_UNWRAP_OR_ELSE,
&methods::RESULT_UNWRAP_USED, &methods::RESULT_UNWRAP_USED,
&methods::SEARCH_IS_SOME, &methods::SEARCH_IS_SOME,
@ -753,7 +760,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&regex::INVALID_REGEX, &regex::INVALID_REGEX,
&regex::REGEX_MACRO, &regex::REGEX_MACRO,
&regex::TRIVIAL_REGEX, &regex::TRIVIAL_REGEX,
&replace_consts::REPLACE_CONSTS,
&returns::LET_AND_RETURN, &returns::LET_AND_RETURN,
&returns::NEEDLESS_RETURN, &returns::NEEDLESS_RETURN,
&returns::UNUSED_UNIT, &returns::UNUSED_UNIT,
@ -806,6 +812,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&types::LET_UNIT_VALUE, &types::LET_UNIT_VALUE,
&types::LINKEDLIST, &types::LINKEDLIST,
&types::OPTION_OPTION, &types::OPTION_OPTION,
&types::REDUNDANT_ALLOCATION,
&types::TYPE_COMPLEXITY, &types::TYPE_COMPLEXITY,
&types::UNIT_ARG, &types::UNIT_ARG,
&types::UNIT_CMP, &types::UNIT_CMP,
@ -814,12 +821,20 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&unicode::NON_ASCII_LITERAL, &unicode::NON_ASCII_LITERAL,
&unicode::UNICODE_NOT_NFC, &unicode::UNICODE_NOT_NFC,
&unicode::ZERO_WIDTH_SPACE, &unicode::ZERO_WIDTH_SPACE,
&unnamed_address::FN_ADDRESS_COMPARISONS,
&unnamed_address::VTABLE_ADDRESS_COMPARISONS,
&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_self::UNUSED_SELF, &unused_self::UNUSED_SELF,
&unwrap::PANICKING_UNWRAP, &unwrap::PANICKING_UNWRAP,
&unwrap::UNNECESSARY_UNWRAP, &unwrap::UNNECESSARY_UNWRAP,
&use_self::USE_SELF, &use_self::USE_SELF,
&utils::internal_lints::CLIPPY_LINTS_INTERNAL,
&utils::internal_lints::COMPILER_LINT_FUNCTIONS,
&utils::internal_lints::DEFAULT_LINT,
&utils::internal_lints::LINT_WITHOUT_LINT_PASS,
&utils::internal_lints::OUTER_EXPN_EXPN_DATA,
&utils::internal_lints::PRODUCE_ICE,
&vec::USELESS_VEC, &vec::USELESS_VEC,
&verbose_file_reads::VERBOSE_FILE_READS, &verbose_file_reads::VERBOSE_FILE_READS,
&wildcard_dependencies::WILDCARD_DEPENDENCIES, &wildcard_dependencies::WILDCARD_DEPENDENCIES,
@ -951,7 +966,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|| box identity_conversion::IdentityConversion::default()); store.register_late_pass(|| box identity_conversion::IdentityConversion::default());
store.register_late_pass(|| box types::ImplicitHasher); store.register_late_pass(|| box types::ImplicitHasher);
store.register_late_pass(|| box fallible_impl_from::FallibleImplFrom); store.register_late_pass(|| box fallible_impl_from::FallibleImplFrom);
store.register_late_pass(|| box replace_consts::ReplaceConsts);
store.register_late_pass(|| box types::UnitArg); store.register_late_pass(|| box types::UnitArg);
store.register_late_pass(|| box double_comparison::DoubleComparisons); store.register_late_pass(|| box double_comparison::DoubleComparisons);
store.register_late_pass(|| box question_mark::QuestionMark); store.register_late_pass(|| box question_mark::QuestionMark);
@ -1024,6 +1038,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_early_pass(|| box macro_use::MacroUseImports); store.register_early_pass(|| box macro_use::MacroUseImports);
store.register_late_pass(|| box verbose_file_reads::VerboseFileReads); store.register_late_pass(|| box verbose_file_reads::VerboseFileReads);
store.register_late_pass(|| box redundant_pub_crate::RedundantPubCrate::default()); store.register_late_pass(|| box redundant_pub_crate::RedundantPubCrate::default());
store.register_late_pass(|| box unnamed_address::UnnamedAddress);
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
LintId::of(&arithmetic::FLOAT_ARITHMETIC), LintId::of(&arithmetic::FLOAT_ARITHMETIC),
@ -1062,6 +1077,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&shadow::SHADOW_REUSE), LintId::of(&shadow::SHADOW_REUSE),
LintId::of(&shadow::SHADOW_SAME), LintId::of(&shadow::SHADOW_SAME),
LintId::of(&strings::STRING_ADD), LintId::of(&strings::STRING_ADD),
LintId::of(&verbose_file_reads::VERBOSE_FILE_READS),
LintId::of(&write::PRINT_STDOUT), LintId::of(&write::PRINT_STDOUT),
LintId::of(&write::USE_DEBUG), LintId::of(&write::USE_DEBUG),
]); ]);
@ -1089,6 +1105,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&items_after_statements::ITEMS_AFTER_STATEMENTS), LintId::of(&items_after_statements::ITEMS_AFTER_STATEMENTS),
LintId::of(&large_stack_arrays::LARGE_STACK_ARRAYS), LintId::of(&large_stack_arrays::LARGE_STACK_ARRAYS),
LintId::of(&literal_representation::LARGE_DIGIT_GROUPS), LintId::of(&literal_representation::LARGE_DIGIT_GROUPS),
LintId::of(&literal_representation::UNREADABLE_LITERAL),
LintId::of(&loops::EXPLICIT_INTO_ITER_LOOP), LintId::of(&loops::EXPLICIT_INTO_ITER_LOOP),
LintId::of(&loops::EXPLICIT_ITER_LOOP), LintId::of(&loops::EXPLICIT_ITER_LOOP),
LintId::of(&macro_use::MACRO_USE_IMPORTS), LintId::of(&macro_use::MACRO_USE_IMPORTS),
@ -1096,6 +1113,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&methods::FILTER_MAP), LintId::of(&methods::FILTER_MAP),
LintId::of(&methods::FILTER_MAP_NEXT), LintId::of(&methods::FILTER_MAP_NEXT),
LintId::of(&methods::FIND_MAP), LintId::of(&methods::FIND_MAP),
LintId::of(&methods::INEFFICIENT_TO_STRING),
LintId::of(&methods::MAP_FLATTEN), LintId::of(&methods::MAP_FLATTEN),
LintId::of(&methods::OPTION_MAP_UNWRAP_OR), LintId::of(&methods::OPTION_MAP_UNWRAP_OR),
LintId::of(&methods::OPTION_MAP_UNWRAP_OR_ELSE), LintId::of(&methods::OPTION_MAP_UNWRAP_OR_ELSE),
@ -1107,17 +1125,20 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&needless_pass_by_value::NEEDLESS_PASS_BY_VALUE), LintId::of(&needless_pass_by_value::NEEDLESS_PASS_BY_VALUE),
LintId::of(&non_expressive_names::SIMILAR_NAMES), LintId::of(&non_expressive_names::SIMILAR_NAMES),
LintId::of(&ranges::RANGE_PLUS_ONE), LintId::of(&ranges::RANGE_PLUS_ONE),
LintId::of(&replace_consts::REPLACE_CONSTS),
LintId::of(&shadow::SHADOW_UNRELATED), LintId::of(&shadow::SHADOW_UNRELATED),
LintId::of(&strings::STRING_ADD_ASSIGN), LintId::of(&strings::STRING_ADD_ASSIGN),
LintId::of(&trait_bounds::TYPE_REPETITION_IN_BOUNDS), LintId::of(&trait_bounds::TYPE_REPETITION_IN_BOUNDS),
LintId::of(&trivially_copy_pass_by_ref::TRIVIALLY_COPY_PASS_BY_REF),
LintId::of(&types::CAST_LOSSLESS), LintId::of(&types::CAST_LOSSLESS),
LintId::of(&types::CAST_POSSIBLE_TRUNCATION), LintId::of(&types::CAST_POSSIBLE_TRUNCATION),
LintId::of(&types::CAST_POSSIBLE_WRAP), LintId::of(&types::CAST_POSSIBLE_WRAP),
LintId::of(&types::CAST_PRECISION_LOSS), LintId::of(&types::CAST_PRECISION_LOSS),
LintId::of(&types::CAST_SIGN_LOSS), LintId::of(&types::CAST_SIGN_LOSS),
LintId::of(&types::IMPLICIT_HASHER),
LintId::of(&types::INVALID_UPCAST_COMPARISONS), LintId::of(&types::INVALID_UPCAST_COMPARISONS),
LintId::of(&types::LET_UNIT_VALUE),
LintId::of(&types::LINKEDLIST), LintId::of(&types::LINKEDLIST),
LintId::of(&types::OPTION_OPTION),
LintId::of(&unicode::NON_ASCII_LITERAL), LintId::of(&unicode::NON_ASCII_LITERAL),
LintId::of(&unicode::UNICODE_NOT_NFC), LintId::of(&unicode::UNICODE_NOT_NFC),
LintId::of(&unused_self::UNUSED_SELF), LintId::of(&unused_self::UNUSED_SELF),
@ -1153,7 +1174,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&booleans::LOGIC_BUG), LintId::of(&booleans::LOGIC_BUG),
LintId::of(&booleans::NONMINIMAL_BOOL), LintId::of(&booleans::NONMINIMAL_BOOL),
LintId::of(&bytecount::NAIVE_BYTECOUNT), LintId::of(&bytecount::NAIVE_BYTECOUNT),
LintId::of(&cognitive_complexity::COGNITIVE_COMPLEXITY),
LintId::of(&collapsible_if::COLLAPSIBLE_IF), LintId::of(&collapsible_if::COLLAPSIBLE_IF),
LintId::of(&comparison_chain::COMPARISON_CHAIN), LintId::of(&comparison_chain::COMPARISON_CHAIN),
LintId::of(&copies::IFS_SAME_COND), LintId::of(&copies::IFS_SAME_COND),
@ -1210,7 +1230,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&lifetimes::NEEDLESS_LIFETIMES), LintId::of(&lifetimes::NEEDLESS_LIFETIMES),
LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING), LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING),
LintId::of(&literal_representation::MISTYPED_LITERAL_SUFFIXES), LintId::of(&literal_representation::MISTYPED_LITERAL_SUFFIXES),
LintId::of(&literal_representation::UNREADABLE_LITERAL),
LintId::of(&loops::EMPTY_LOOP), LintId::of(&loops::EMPTY_LOOP),
LintId::of(&loops::EXPLICIT_COUNTER_LOOP), LintId::of(&loops::EXPLICIT_COUNTER_LOOP),
LintId::of(&loops::FOR_KV_MAP), LintId::of(&loops::FOR_KV_MAP),
@ -1250,7 +1269,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&methods::EXPECT_FUN_CALL), LintId::of(&methods::EXPECT_FUN_CALL),
LintId::of(&methods::FILTER_NEXT), LintId::of(&methods::FILTER_NEXT),
LintId::of(&methods::FLAT_MAP_IDENTITY), LintId::of(&methods::FLAT_MAP_IDENTITY),
LintId::of(&methods::INEFFICIENT_TO_STRING),
LintId::of(&methods::INTO_ITER_ON_REF), LintId::of(&methods::INTO_ITER_ON_REF),
LintId::of(&methods::ITERATOR_STEP_BY_ZERO), LintId::of(&methods::ITERATOR_STEP_BY_ZERO),
LintId::of(&methods::ITER_CLONED_COLLECT), LintId::of(&methods::ITER_CLONED_COLLECT),
@ -1264,6 +1282,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&methods::OPTION_AS_REF_DEREF), LintId::of(&methods::OPTION_AS_REF_DEREF),
LintId::of(&methods::OPTION_MAP_OR_NONE), LintId::of(&methods::OPTION_MAP_OR_NONE),
LintId::of(&methods::OR_FUN_CALL), LintId::of(&methods::OR_FUN_CALL),
LintId::of(&methods::RESULT_MAP_OR_INTO_OPTION),
LintId::of(&methods::SEARCH_IS_SOME), LintId::of(&methods::SEARCH_IS_SOME),
LintId::of(&methods::SHOULD_IMPLEMENT_TRAIT), LintId::of(&methods::SHOULD_IMPLEMENT_TRAIT),
LintId::of(&methods::SINGLE_CHAR_PATTERN), LintId::of(&methods::SINGLE_CHAR_PATTERN),
@ -1356,7 +1375,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&transmute::UNSOUND_COLLECTION_TRANSMUTE), LintId::of(&transmute::UNSOUND_COLLECTION_TRANSMUTE),
LintId::of(&transmute::WRONG_TRANSMUTE), LintId::of(&transmute::WRONG_TRANSMUTE),
LintId::of(&transmuting_null::TRANSMUTING_NULL), LintId::of(&transmuting_null::TRANSMUTING_NULL),
LintId::of(&trivially_copy_pass_by_ref::TRIVIALLY_COPY_PASS_BY_REF),
LintId::of(&try_err::TRY_ERR), LintId::of(&try_err::TRY_ERR),
LintId::of(&types::ABSURD_EXTREME_COMPARISONS), LintId::of(&types::ABSURD_EXTREME_COMPARISONS),
LintId::of(&types::BORROWED_BOX), LintId::of(&types::BORROWED_BOX),
@ -1366,21 +1384,20 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&types::CHAR_LIT_AS_U8), LintId::of(&types::CHAR_LIT_AS_U8),
LintId::of(&types::FN_TO_NUMERIC_CAST), LintId::of(&types::FN_TO_NUMERIC_CAST),
LintId::of(&types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION), LintId::of(&types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION),
LintId::of(&types::IMPLICIT_HASHER), LintId::of(&types::REDUNDANT_ALLOCATION),
LintId::of(&types::LET_UNIT_VALUE),
LintId::of(&types::OPTION_OPTION),
LintId::of(&types::TYPE_COMPLEXITY), LintId::of(&types::TYPE_COMPLEXITY),
LintId::of(&types::UNIT_ARG), LintId::of(&types::UNIT_ARG),
LintId::of(&types::UNIT_CMP), LintId::of(&types::UNIT_CMP),
LintId::of(&types::UNNECESSARY_CAST), LintId::of(&types::UNNECESSARY_CAST),
LintId::of(&types::VEC_BOX), LintId::of(&types::VEC_BOX),
LintId::of(&unicode::ZERO_WIDTH_SPACE), LintId::of(&unicode::ZERO_WIDTH_SPACE),
LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS),
LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS),
LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME), LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME),
LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT), LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT),
LintId::of(&unwrap::PANICKING_UNWRAP), LintId::of(&unwrap::PANICKING_UNWRAP),
LintId::of(&unwrap::UNNECESSARY_UNWRAP), LintId::of(&unwrap::UNNECESSARY_UNWRAP),
LintId::of(&vec::USELESS_VEC), LintId::of(&vec::USELESS_VEC),
LintId::of(&verbose_file_reads::VERBOSE_FILE_READS),
LintId::of(&write::PRINTLN_EMPTY_STRING), LintId::of(&write::PRINTLN_EMPTY_STRING),
LintId::of(&write::PRINT_LITERAL), LintId::of(&write::PRINT_LITERAL),
LintId::of(&write::PRINT_WITH_NEWLINE), LintId::of(&write::PRINT_WITH_NEWLINE),
@ -1418,7 +1435,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&len_zero::LEN_ZERO), LintId::of(&len_zero::LEN_ZERO),
LintId::of(&let_if_seq::USELESS_LET_IF_SEQ), LintId::of(&let_if_seq::USELESS_LET_IF_SEQ),
LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING), LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING),
LintId::of(&literal_representation::UNREADABLE_LITERAL),
LintId::of(&loops::EMPTY_LOOP), LintId::of(&loops::EMPTY_LOOP),
LintId::of(&loops::FOR_KV_MAP), LintId::of(&loops::FOR_KV_MAP),
LintId::of(&loops::NEEDLESS_RANGE_LOOP), LintId::of(&loops::NEEDLESS_RANGE_LOOP),
@ -1443,6 +1459,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&methods::NEW_RET_NO_SELF), LintId::of(&methods::NEW_RET_NO_SELF),
LintId::of(&methods::OK_EXPECT), LintId::of(&methods::OK_EXPECT),
LintId::of(&methods::OPTION_MAP_OR_NONE), LintId::of(&methods::OPTION_MAP_OR_NONE),
LintId::of(&methods::RESULT_MAP_OR_INTO_OPTION),
LintId::of(&methods::SHOULD_IMPLEMENT_TRAIT), LintId::of(&methods::SHOULD_IMPLEMENT_TRAIT),
LintId::of(&methods::STRING_EXTEND_CHARS), LintId::of(&methods::STRING_EXTEND_CHARS),
LintId::of(&methods::UNNECESSARY_FOLD), LintId::of(&methods::UNNECESSARY_FOLD),
@ -1478,8 +1495,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&try_err::TRY_ERR), LintId::of(&try_err::TRY_ERR),
LintId::of(&types::FN_TO_NUMERIC_CAST), LintId::of(&types::FN_TO_NUMERIC_CAST),
LintId::of(&types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION), LintId::of(&types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION),
LintId::of(&types::IMPLICIT_HASHER),
LintId::of(&types::LET_UNIT_VALUE),
LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME), LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME),
LintId::of(&write::PRINTLN_EMPTY_STRING), LintId::of(&write::PRINTLN_EMPTY_STRING),
LintId::of(&write::PRINT_LITERAL), LintId::of(&write::PRINT_LITERAL),
@ -1493,7 +1508,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&assign_ops::MISREFACTORED_ASSIGN_OP), LintId::of(&assign_ops::MISREFACTORED_ASSIGN_OP),
LintId::of(&attrs::DEPRECATED_CFG_ATTR), LintId::of(&attrs::DEPRECATED_CFG_ATTR),
LintId::of(&booleans::NONMINIMAL_BOOL), LintId::of(&booleans::NONMINIMAL_BOOL),
LintId::of(&cognitive_complexity::COGNITIVE_COMPLEXITY),
LintId::of(&double_comparison::DOUBLE_COMPARISONS), LintId::of(&double_comparison::DOUBLE_COMPARISONS),
LintId::of(&double_parens::DOUBLE_PARENS), LintId::of(&double_parens::DOUBLE_PARENS),
LintId::of(&duration_subsec::DURATION_SUBSEC), LintId::of(&duration_subsec::DURATION_SUBSEC),
@ -1557,13 +1571,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&transmute::TRANSMUTE_PTR_TO_REF), LintId::of(&transmute::TRANSMUTE_PTR_TO_REF),
LintId::of(&types::BORROWED_BOX), LintId::of(&types::BORROWED_BOX),
LintId::of(&types::CHAR_LIT_AS_U8), LintId::of(&types::CHAR_LIT_AS_U8),
LintId::of(&types::OPTION_OPTION),
LintId::of(&types::TYPE_COMPLEXITY), LintId::of(&types::TYPE_COMPLEXITY),
LintId::of(&types::UNIT_ARG), LintId::of(&types::UNIT_ARG),
LintId::of(&types::UNNECESSARY_CAST), LintId::of(&types::UNNECESSARY_CAST),
LintId::of(&types::VEC_BOX), LintId::of(&types::VEC_BOX),
LintId::of(&unwrap::UNNECESSARY_UNWRAP), LintId::of(&unwrap::UNNECESSARY_UNWRAP),
LintId::of(&verbose_file_reads::VERBOSE_FILE_READS),
LintId::of(&zero_div_zero::ZERO_DIVIDED_BY_ZERO), LintId::of(&zero_div_zero::ZERO_DIVIDED_BY_ZERO),
]); ]);
@ -1630,6 +1642,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&types::CAST_REF_TO_MUT), LintId::of(&types::CAST_REF_TO_MUT),
LintId::of(&types::UNIT_CMP), LintId::of(&types::UNIT_CMP),
LintId::of(&unicode::ZERO_WIDTH_SPACE), LintId::of(&unicode::ZERO_WIDTH_SPACE),
LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS),
LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS),
LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT), LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT),
LintId::of(&unwrap::PANICKING_UNWRAP), LintId::of(&unwrap::PANICKING_UNWRAP),
]); ]);
@ -1642,7 +1656,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&loops::MANUAL_MEMCPY), LintId::of(&loops::MANUAL_MEMCPY),
LintId::of(&loops::NEEDLESS_COLLECT), LintId::of(&loops::NEEDLESS_COLLECT),
LintId::of(&methods::EXPECT_FUN_CALL), LintId::of(&methods::EXPECT_FUN_CALL),
LintId::of(&methods::INEFFICIENT_TO_STRING),
LintId::of(&methods::ITER_NTH), LintId::of(&methods::ITER_NTH),
LintId::of(&methods::OR_FUN_CALL), LintId::of(&methods::OR_FUN_CALL),
LintId::of(&methods::SINGLE_CHAR_PATTERN), LintId::of(&methods::SINGLE_CHAR_PATTERN),
@ -1650,8 +1663,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&mutex_atomic::MUTEX_ATOMIC), LintId::of(&mutex_atomic::MUTEX_ATOMIC),
LintId::of(&redundant_clone::REDUNDANT_CLONE), LintId::of(&redundant_clone::REDUNDANT_CLONE),
LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
LintId::of(&trivially_copy_pass_by_ref::TRIVIALLY_COPY_PASS_BY_REF),
LintId::of(&types::BOX_VEC), LintId::of(&types::BOX_VEC),
LintId::of(&types::REDUNDANT_ALLOCATION),
LintId::of(&vec::USELESS_VEC), LintId::of(&vec::USELESS_VEC),
]); ]);
@ -1663,6 +1676,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![ store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
LintId::of(&attrs::EMPTY_LINE_AFTER_OUTER_ATTR), LintId::of(&attrs::EMPTY_LINE_AFTER_OUTER_ATTR),
LintId::of(&cognitive_complexity::COGNITIVE_COMPLEXITY),
LintId::of(&fallible_impl_from::FALLIBLE_IMPL_FROM), LintId::of(&fallible_impl_from::FALLIBLE_IMPL_FROM),
LintId::of(&floating_point_arithmetic::IMPRECISE_FLOPS), LintId::of(&floating_point_arithmetic::IMPRECISE_FLOPS),
LintId::of(&floating_point_arithmetic::SUBOPTIMAL_FLOPS), LintId::of(&floating_point_arithmetic::SUBOPTIMAL_FLOPS),

View File

@ -1,5 +1,3 @@
use rustc::hir::map::Map;
use rustc::lint::in_external_macro;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{ use rustc_hir::intravisit::{
@ -11,13 +9,14 @@ use rustc_hir::{
ItemKind, Lifetime, LifetimeName, ParamName, QPath, TraitBoundModifier, TraitFn, TraitItem, TraitItemKind, Ty, ItemKind, Lifetime, LifetimeName, ParamName, QPath, TraitBoundModifier, TraitFn, TraitItem, TraitItemKind, Ty,
TyKind, WhereClause, WherePredicate, TyKind, WhereClause, WherePredicate,
}; };
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
use rustc_span::symbol::kw; use rustc_span::symbol::kw;
use crate::reexport::Name; use crate::reexport::Name;
use crate::utils::{last_path_segment, span_lint, trait_ref_of_method}; use crate::utils::{in_macro, last_path_segment, span_lint, trait_ref_of_method};
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for lifetime annotations which can be removed by /// **What it does:** Checks for lifetime annotations which can be removed by
@ -125,7 +124,7 @@ fn check_fn_inner<'a, 'tcx>(
span: Span, span: Span,
report_extra_lifetimes: bool, report_extra_lifetimes: bool,
) { ) {
if in_external_macro(cx.sess(), span) || has_where_lifetimes(cx, &generics.where_clause) { if in_macro(span) || has_where_lifetimes(cx, &generics.where_clause) {
return; return;
} }

View File

@ -7,10 +7,10 @@ use crate::utils::{
snippet_opt, span_lint_and_sugg, snippet_opt, span_lint_and_sugg,
}; };
use if_chain::if_chain; use if_chain::if_chain;
use rustc::lint::in_external_macro;
use rustc_ast::ast::{Expr, ExprKind, Lit, LitKind}; use rustc_ast::ast::{Expr, ExprKind, Lit, LitKind};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
declare_clippy_lint! { declare_clippy_lint! {
@ -27,7 +27,7 @@ declare_clippy_lint! {
/// let x: u64 = 61864918973511; /// let x: u64 = 61864918973511;
/// ``` /// ```
pub UNREADABLE_LITERAL, pub UNREADABLE_LITERAL,
style, pedantic,
"long integer literal without underscores" "long integer literal without underscores"
} }
@ -186,6 +186,9 @@ impl EarlyLintPass for LiteralDigitGrouping {
} }
} }
// Length of each UUID hyphenated group in hex digits.
const UUID_GROUP_LENS: [usize; 5] = [8, 4, 4, 4, 12];
impl LiteralDigitGrouping { impl LiteralDigitGrouping {
fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) { fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) {
if_chain! { if_chain! {
@ -196,6 +199,10 @@ impl LiteralDigitGrouping {
return; return;
} }
if Self::is_literal_uuid_formatted(&mut num_lit) {
return;
}
let result = (|| { let result = (|| {
let integral_group_size = Self::get_group_size(num_lit.integer.split('_'))?; let integral_group_size = Self::get_group_size(num_lit.integer.split('_'))?;
@ -266,6 +273,28 @@ impl LiteralDigitGrouping {
} }
} }
/// Checks whether the numeric literal matches the formatting of a UUID.
///
/// Returns `true` if the radix is hexadecimal, and the groups match the
/// UUID format of 8-4-4-4-12.
fn is_literal_uuid_formatted(num_lit: &mut NumericLiteral<'_>) -> bool {
if num_lit.radix != Radix::Hexadecimal {
return false;
}
// UUIDs should not have a fraction
if num_lit.fraction.is_some() {
return false;
}
let group_sizes: Vec<usize> = num_lit.integer.split('_').map(str::len).collect();
if UUID_GROUP_LENS.len() == group_sizes.len() {
UUID_GROUP_LENS.iter().zip(&group_sizes).all(|(&a, &b)| a == b)
} else {
false
}
}
/// Given the sizes of the digit groups of both integral and fractional /// Given the sizes of the digit groups of both integral and fractional
/// parts, and the length /// parts, and the length
/// of both parts, determine if the digits have been grouped consistently. /// of both parts, determine if the digits have been grouped consistently.

View File

@ -11,10 +11,6 @@ use crate::utils::{
use crate::utils::{is_type_diagnostic_item, qpath_res, same_tys, sext, sugg}; use crate::utils::{is_type_diagnostic_item, qpath_res, same_tys, sext, sugg};
use if_chain::if_chain; use if_chain::if_chain;
use itertools::Itertools; use itertools::Itertools;
use rustc::hir::map::Map;
use rustc::lint::in_external_macro;
use rustc::middle::region;
use rustc::ty::{self, Ty};
use rustc_ast::ast; use rustc_ast::ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::Applicability; use rustc_errors::Applicability;
@ -26,9 +22,13 @@ use rustc_hir::{
}; };
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::map::Map;
use rustc_middle::lint::in_external_macro;
use rustc_middle::middle::region;
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
use rustc_span::{BytePos, Symbol}; use rustc_span::BytePos;
use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase}; use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase};
use std::iter::{once, Iterator}; use std::iter::{once, Iterator};
use std::mem; use std::mem;
@ -654,7 +654,7 @@ fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult) -> NeverLoopResult
fn never_loop_block(block: &Block<'_>, main_loop_id: HirId) -> NeverLoopResult { fn never_loop_block(block: &Block<'_>, main_loop_id: HirId) -> NeverLoopResult {
let stmts = block.stmts.iter().map(stmt_to_expr); let stmts = block.stmts.iter().map(stmt_to_expr);
let expr = once(block.expr.as_ref().map(|p| &**p)); let expr = once(block.expr.as_deref());
let mut iter = stmts.chain(expr).filter_map(|e| e); let mut iter = stmts.chain(expr).filter_map(|e| e);
never_loop_expr_seq(&mut iter, main_loop_id) never_loop_expr_seq(&mut iter, main_loop_id)
} }
@ -662,7 +662,7 @@ fn never_loop_block(block: &Block<'_>, main_loop_id: HirId) -> NeverLoopResult {
fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<&'tcx Expr<'tcx>> { fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<&'tcx Expr<'tcx>> {
match stmt.kind { match stmt.kind {
StmtKind::Semi(ref e, ..) | StmtKind::Expr(ref e, ..) => Some(e), StmtKind::Semi(ref e, ..) | StmtKind::Expr(ref e, ..) => Some(e),
StmtKind::Local(ref local) => local.init.as_ref().map(|p| &**p), StmtKind::Local(ref local) => local.init.as_deref(),
_ => None, _ => None,
} }
} }
@ -720,7 +720,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
ExprKind::Struct(_, _, None) ExprKind::Struct(_, _, None)
| ExprKind::Yield(_, _) | ExprKind::Yield(_, _)
| ExprKind::Closure(_, _, _, _, _) | ExprKind::Closure(_, _, _, _, _)
| ExprKind::InlineAsm(_) | ExprKind::LlvmInlineAsm(_)
| ExprKind::Path(_) | ExprKind::Path(_)
| ExprKind::Lit(_) | ExprKind::Lit(_)
| ExprKind::Err => NeverLoopResult::Otherwise, | ExprKind::Err => NeverLoopResult::Otherwise,
@ -804,7 +804,7 @@ fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'_>) -> bool {
_ => false, _ => false,
}; };
is_slice || is_type_diagnostic_item(cx, ty, Symbol::intern("vec_type")) || match_type(cx, ty, &paths::VEC_DEQUE) is_slice || is_type_diagnostic_item(cx, ty, sym!(vec_type)) || match_type(cx, ty, &paths::VEC_DEQUE)
} }
fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) -> Option<FixedOffsetVar> { fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) -> Option<FixedOffsetVar> {
@ -922,7 +922,7 @@ fn get_indexed_assignments<'a, 'tcx>(
.chain(expr.as_ref().into_iter().map(|e| Some(get_assignment(cx, &*e, var)))) .chain(expr.as_ref().into_iter().map(|e| Some(get_assignment(cx, &*e, var))))
.filter_map(|op| op) .filter_map(|op| op)
.collect::<Option<Vec<_>>>() .collect::<Option<Vec<_>>>()
.unwrap_or_else(|| vec![]) .unwrap_or_default()
} else { } else {
get_assignment(cx, body, var).into_iter().collect() get_assignment(cx, body, var).into_iter().collect()
} }
@ -1392,7 +1392,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>, e
/// Checks for `for` loops over `Option`s and `Result`s. /// Checks for `for` loops over `Option`s and `Result`s.
fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>) { fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>) {
let ty = cx.tables.expr_ty(arg); let ty = cx.tables.expr_ty(arg);
if match_type(cx, ty, &paths::OPTION) { if is_type_diagnostic_item(cx, ty, sym!(option_type)) {
span_lint_and_help( span_lint_and_help(
cx, cx,
FOR_LOOP_OVER_OPTION, FOR_LOOP_OVER_OPTION,
@ -1408,7 +1408,7 @@ fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>) {
snippet(cx, arg.span, "_") snippet(cx, arg.span, "_")
), ),
); );
} else if match_type(cx, ty, &paths::RESULT) { } else if is_type_diagnostic_item(cx, ty, sym!(result_type)) {
span_lint_and_help( span_lint_and_help(
cx, cx,
FOR_LOOP_OVER_RESULT, FOR_LOOP_OVER_RESULT,
@ -1955,7 +1955,7 @@ fn is_ref_iterable_type(cx: &LateContext<'_, '_>, e: &Expr<'_>) -> bool {
// will allow further borrows afterwards // will allow further borrows afterwards
let ty = cx.tables.expr_ty(e); let ty = cx.tables.expr_ty(e);
is_iterable_array(ty, cx) || is_iterable_array(ty, cx) ||
is_type_diagnostic_item(cx, ty, Symbol::intern("vec_type")) || is_type_diagnostic_item(cx, ty, sym!(vec_type)) ||
match_type(cx, ty, &paths::LINKED_LIST) || match_type(cx, ty, &paths::LINKED_LIST) ||
match_type(cx, ty, &paths::HASHMAP) || match_type(cx, ty, &paths::HASHMAP) ||
match_type(cx, ty, &paths::HASHSET) || match_type(cx, ty, &paths::HASHSET) ||
@ -2465,7 +2465,7 @@ fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'a, '
if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0); if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0);
then { then {
let ty = cx.tables.node_type(ty.hir_id); let ty = cx.tables.node_type(ty.hir_id);
if is_type_diagnostic_item(cx, ty, Symbol::intern("vec_type")) || if is_type_diagnostic_item(cx, ty, sym!(vec_type)) ||
match_type(cx, ty, &paths::VEC_DEQUE) || match_type(cx, ty, &paths::VEC_DEQUE) ||
match_type(cx, ty, &paths::BTREEMAP) || match_type(cx, ty, &paths::BTREEMAP) ||
match_type(cx, ty, &paths::HASHMAP) { match_type(cx, ty, &paths::HASHMAP) {

View File

@ -1,13 +1,13 @@
use crate::utils::paths; use crate::utils::paths;
use crate::utils::{ use crate::utils::{
is_copy, match_trait_method, match_type, remove_blocks, snippet_with_applicability, span_lint_and_sugg, is_copy, is_type_diagnostic_item, match_trait_method, remove_blocks, snippet_with_applicability, span_lint_and_sugg,
}; };
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty;
use rustc_ast::ast::Ident; use rustc_ast::ast::Ident;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
@ -52,7 +52,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapClone {
if args.len() == 2; if args.len() == 2;
if method.ident.as_str() == "map"; if method.ident.as_str() == "map";
let ty = cx.tables.expr_ty(&args[0]); let ty = cx.tables.expr_ty(&args[0]);
if match_type(cx, ty, &paths::OPTION) || match_trait_method(cx, e, &paths::ITERATOR); if is_type_diagnostic_item(cx, ty, sym!(option_type)) || match_trait_method(cx, e, &paths::ITERATOR);
if let hir::ExprKind::Closure(_, _, body_id, _, _) = args[1].kind; if let hir::ExprKind::Closure(_, _, body_id, _, _) = args[1].kind;
let closure_body = cx.tcx.hir().body(body_id); let closure_body = cx.tcx.hir().body(body_id);
let closure_expr = remove_blocks(&closure_body.value); let closure_expr = remove_blocks(&closure_body.value);

View File

@ -1,10 +1,9 @@
use crate::utils::paths; use crate::utils::{is_type_diagnostic_item, iter_input_pats, method_chain_args, snippet, span_lint_and_then};
use crate::utils::{iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty::{self, Ty};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
@ -206,9 +205,9 @@ fn suggestion_msg(function_type: &str, map_type: &str) -> String {
fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt<'_>, expr: &hir::Expr<'_>, map_args: &[hir::Expr<'_>]) { fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt<'_>, expr: &hir::Expr<'_>, map_args: &[hir::Expr<'_>]) {
let var_arg = &map_args[0]; let var_arg = &map_args[0];
let (map_type, variant, lint) = if match_type(cx, cx.tables.expr_ty(var_arg), &paths::OPTION) { let (map_type, variant, lint) = if is_type_diagnostic_item(cx, cx.tables.expr_ty(var_arg), sym!(option_type)) {
("Option", "Some", OPTION_MAP_UNIT_FN) ("Option", "Some", OPTION_MAP_UNIT_FN)
} else if match_type(cx, cx.tables.expr_ty(var_arg), &paths::RESULT) { } else if is_type_diagnostic_item(cx, cx.tables.expr_ty(var_arg), sym!(result_type)) {
("Result", "Ok", RESULT_MAP_UNIT_FN) ("Result", "Ok", RESULT_MAP_UNIT_FN)
} else { } else {
return; return;

View File

@ -3,22 +3,22 @@ use crate::utils::paths;
use crate::utils::sugg::Sugg; use crate::utils::sugg::Sugg;
use crate::utils::usage::is_unused; use crate::utils::usage::is_unused;
use crate::utils::{ use crate::utils::{
expr_block, get_arg_name, get_parent_expr, in_macro, indent_of, is_allowed, is_expn_of, is_refutable, is_wild, expr_block, get_arg_name, get_parent_expr, in_macro, indent_of, is_allowed, is_expn_of, is_refutable,
match_qpath, match_type, match_var, multispan_sugg, remove_blocks, snippet, snippet_block, is_type_diagnostic_item, is_wild, match_qpath, match_type, match_var, multispan_sugg, remove_blocks, snippet,
snippet_with_applicability, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then, snippet_block, snippet_with_applicability, span_lint_and_help, span_lint_and_note, span_lint_and_sugg,
walk_ptrs_ty, span_lint_and_then, walk_ptrs_ty,
}; };
use if_chain::if_chain; use if_chain::if_chain;
use rustc::lint::in_external_macro;
use rustc::ty::{self, Ty};
use rustc_ast::ast::LitKind; use rustc_ast::ast::LitKind;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::def::CtorKind; use rustc_hir::def::CtorKind;
use rustc_hir::{ use rustc_hir::{
print, Arm, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, Local, MatchSource, Mutability, Node, Pat, Arm, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, Local, MatchSource, Mutability, Node, Pat, PatKind,
PatKind, QPath, RangeEnd, QPath, RangeEnd,
}; };
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
use std::cmp::Ordering; use std::cmp::Ordering;
@ -447,6 +447,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Matches {
#[rustfmt::skip] #[rustfmt::skip]
fn check_single_match(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) { fn check_single_match(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) {
if arms.len() == 2 && arms[0].guard.is_none() && arms[1].guard.is_none() { if arms.len() == 2 && arms[0].guard.is_none() && arms[1].guard.is_none() {
if in_macro(expr.span) {
// Don't lint match expressions present in
// macro_rules! block
return;
}
if let PatKind::Or(..) = arms[0].pat.kind { if let PatKind::Or(..) = arms[0].pat.kind {
// don't lint for or patterns for now, this makes // don't lint for or patterns for now, this makes
// the lint noisy in unnecessary situations // the lint noisy in unnecessary situations
@ -536,10 +541,12 @@ fn check_single_match_opt_like(
if !inner.iter().all(is_wild) { if !inner.iter().all(is_wild) {
return; return;
} }
print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)) rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false))
}, },
PatKind::Binding(BindingAnnotation::Unannotated, .., ident, None) => ident.to_string(), PatKind::Binding(BindingAnnotation::Unannotated, .., ident, None) => ident.to_string(),
PatKind::Path(ref path) => print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)), PatKind::Path(ref path) => {
rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false))
},
_ => return, _ => return,
}; };
@ -635,10 +642,10 @@ fn check_overlapping_arms<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ex: &'tcx Expr<'
fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>]) { fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
let ex_ty = walk_ptrs_ty(cx.tables.expr_ty(ex)); let ex_ty = walk_ptrs_ty(cx.tables.expr_ty(ex));
if match_type(cx, ex_ty, &paths::RESULT) { if is_type_diagnostic_item(cx, ex_ty, sym!(result_type)) {
for arm in arms { for arm in arms {
if let PatKind::TupleStruct(ref path, ref inner, _) = arm.pat.kind { if let PatKind::TupleStruct(ref path, ref inner, _) = arm.pat.kind {
let path_str = print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)); let path_str = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false));
if path_str == "Err" { if path_str == "Err" {
let mut matching_wild = inner.iter().any(is_wild); let mut matching_wild = inner.iter().any(is_wild);
let mut ident_bind_name = String::from("_"); let mut ident_bind_name = String::from("_");
@ -1190,3 +1197,40 @@ where
None None
} }
#[test]
fn test_overlapping() {
use rustc_span::source_map::DUMMY_SP;
let sp = |s, e| SpannedRange {
span: DUMMY_SP,
node: (s, e),
};
assert_eq!(None, overlapping::<u8>(&[]));
assert_eq!(None, overlapping(&[sp(1, Bound::Included(4))]));
assert_eq!(
None,
overlapping(&[sp(1, Bound::Included(4)), sp(5, Bound::Included(6))])
);
assert_eq!(
None,
overlapping(&[
sp(1, Bound::Included(4)),
sp(5, Bound::Included(6)),
sp(10, Bound::Included(11))
],)
);
assert_eq!(
Some((&sp(1, Bound::Included(4)), &sp(3, Bound::Included(6)))),
overlapping(&[sp(1, Bound::Included(4)), sp(3, Bound::Included(6))])
);
assert_eq!(
Some((&sp(5, Bound::Included(6)), &sp(6, Bound::Included(11)))),
overlapping(&[
sp(1, Bound::Included(4)),
sp(5, Bound::Included(6)),
sp(6, Bound::Included(11))
],)
);
}

View File

@ -3,12 +3,13 @@ use crate::utils::{
span_lint_and_sugg, span_lint_and_then, span_lint_and_sugg, span_lint_and_then,
}; };
use if_chain::if_chain; use if_chain::if_chain;
use rustc::lint::in_external_macro;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, QPath}; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, QPath};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
use rustc_span::symbol::sym;
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for `mem::replace()` on an `Option` with /// **What it does:** Checks for `mem::replace()` on an `Option` with
@ -141,7 +142,7 @@ fn check_replace_with_uninit(cx: &LateContext<'_, '_>, src: &Expr<'_>, expr_span
if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind; if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
if let Some(repl_def_id) = cx.tables.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id(); if let Some(repl_def_id) = cx.tables.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
then { then {
if match_def_path(cx, repl_def_id, &paths::MEM_UNINITIALIZED) { if cx.tcx.is_diagnostic_item(sym::mem_uninitialized, repl_def_id) {
span_lint_and_help( span_lint_and_help(
cx, cx,
MEM_REPLACE_WITH_UNINIT, MEM_REPLACE_WITH_UNINIT,
@ -149,7 +150,7 @@ fn check_replace_with_uninit(cx: &LateContext<'_, '_>, src: &Expr<'_>, expr_span
"replacing with `mem::uninitialized()`", "replacing with `mem::uninitialized()`",
"consider using the `take_mut` crate instead", "consider using the `take_mut` crate instead",
); );
} else if match_def_path(cx, repl_def_id, &paths::MEM_ZEROED) && } else if cx.tcx.is_diagnostic_item(sym::mem_zeroed, repl_def_id) &&
!cx.tables.expr_ty(src).is_primitive() { !cx.tables.expr_ty(src).is_primitive() {
span_lint_and_help( span_lint_and_help(
cx, cx,

View File

@ -1,10 +1,10 @@
use super::INEFFICIENT_TO_STRING; use super::INEFFICIENT_TO_STRING;
use crate::utils::{match_def_path, paths, snippet_with_applicability, span_lint_and_then, walk_ptrs_ty_depth}; use crate::utils::{match_def_path, paths, snippet_with_applicability, span_lint_and_then, walk_ptrs_ty_depth};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty::{self, Ty};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty};
/// Checks for the `INEFFICIENT_TO_STRING` lint /// Checks for the `INEFFICIENT_TO_STRING` lint
pub fn lint<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>, arg_ty: Ty<'tcx>) { pub fn lint<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>, arg_ty: Ty<'tcx>) {

View File

@ -8,17 +8,18 @@ use std::fmt;
use std::iter; use std::iter;
use if_chain::if_chain; use if_chain::if_chain;
use rustc::hir::map::Map;
use rustc::lint::in_external_macro;
use rustc::ty::{self, Predicate, Ty};
use rustc_ast::ast; use rustc_ast::ast;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::intravisit::{self, Visitor};
use rustc_lint::{LateContext, LateLintPass, Lint, LintContext}; use rustc_lint::{LateContext, LateLintPass, Lint, LintContext};
use rustc_middle::hir::map::Map;
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{self, Predicate, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
use rustc_span::symbol::{sym, Symbol, SymbolStr}; use rustc_span::symbol::{sym, SymbolStr};
use crate::consts::{constant, Constant}; use crate::consts::{constant, Constant};
use crate::utils::usage::mutated_variables; use crate::utils::usage::mutated_variables;
@ -330,6 +331,32 @@ declare_clippy_lint! {
"using `Option.map_or(None, f)`, which is more succinctly expressed as `and_then(f)`" "using `Option.map_or(None, f)`, which is more succinctly expressed as `and_then(f)`"
} }
declare_clippy_lint! {
/// **What it does:** Checks for usage of `_.map_or(None, Some)`.
///
/// **Why is this bad?** Readability, this can be written more concisely as
/// `_.ok()`.
///
/// **Known problems:** None.
///
/// **Example:**
///
/// Bad:
/// ```rust
/// # let r: Result<u32, &str> = Ok(1);
/// assert_eq!(Some(1), r.map_or(None, Some));
/// ```
///
/// Good:
/// ```rust
/// # let r: Result<u32, &str> = Ok(1);
/// assert_eq!(Some(1), r.ok());
/// ```
pub RESULT_MAP_OR_INTO_OPTION,
style,
"using `Result.map_or(None, Some)`, which is more succinctly expressed as `ok()`"
}
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for usage of `_.and_then(|x| Some(y))`. /// **What it does:** Checks for usage of `_.and_then(|x| Some(y))`.
/// ///
@ -698,12 +725,12 @@ declare_clippy_lint! {
/// ["foo", "bar"].iter().map(|&s| s.to_string()); /// ["foo", "bar"].iter().map(|&s| s.to_string());
/// ``` /// ```
pub INEFFICIENT_TO_STRING, pub INEFFICIENT_TO_STRING,
perf, pedantic,
"using `to_string` on `&&T` where `T: ToString`" "using `to_string` on `&&T` where `T: ToString`"
} }
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for `new` not returning `Self`. /// **What it does:** Checks for `new` not returning a type that contains `Self`.
/// ///
/// **Why is this bad?** As a convention, `new` methods are used to make a new /// **Why is this bad?** As a convention, `new` methods are used to make a new
/// instance of a type. /// instance of a type.
@ -720,9 +747,31 @@ declare_clippy_lint! {
/// } /// }
/// } /// }
/// ``` /// ```
///
/// ```rust
/// # struct Foo;
/// # struct FooError;
/// impl Foo {
/// // Good. Return type contains `Self`
/// fn new() -> Result<Foo, FooError> {
/// # Ok(Foo)
/// }
/// }
/// ```
///
/// ```rust
/// # struct Foo;
/// struct Bar(Foo);
/// impl Foo {
/// // Bad. The type name must contain `Self`.
/// fn new() -> Bar {
/// # Bar(Foo)
/// }
/// }
/// ```
pub NEW_RET_NO_SELF, pub NEW_RET_NO_SELF,
style, style,
"not returning `Self` in a `new` method" "not returning type containing `Self` in a `new` method"
} }
declare_clippy_lint! { declare_clippy_lint! {
@ -1137,8 +1186,8 @@ declare_clippy_lint! {
/// ```rust /// ```rust
/// # let y: u32 = 0; /// # let y: u32 = 0;
/// # let x: u32 = 100; /// # let x: u32 = 100;
/// let add = x.checked_add(y).unwrap_or(u32::max_value()); /// let add = x.checked_add(y).unwrap_or(u32::MAX);
/// let sub = x.checked_sub(y).unwrap_or(u32::min_value()); /// let sub = x.checked_sub(y).unwrap_or(u32::MIN);
/// ``` /// ```
/// ///
/// can be written using dedicated methods for saturating addition/subtraction as: /// can be written using dedicated methods for saturating addition/subtraction as:
@ -1248,6 +1297,7 @@ declare_lint_pass!(Methods => [
OPTION_MAP_UNWRAP_OR, OPTION_MAP_UNWRAP_OR,
OPTION_MAP_UNWRAP_OR_ELSE, OPTION_MAP_UNWRAP_OR_ELSE,
RESULT_MAP_UNWRAP_OR_ELSE, RESULT_MAP_UNWRAP_OR_ELSE,
RESULT_MAP_OR_INTO_OPTION,
OPTION_MAP_OR_NONE, OPTION_MAP_OR_NONE,
OPTION_AND_THEN_SOME, OPTION_AND_THEN_SOME,
OR_FUN_CALL, OR_FUN_CALL,
@ -1289,7 +1339,7 @@ declare_lint_pass!(Methods => [
]); ]);
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
#[allow(clippy::cognitive_complexity, clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
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<'_>) {
if in_macro(expr.span) { if in_macro(expr.span) {
return; return;
@ -1407,7 +1457,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id); let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id);
let item = cx.tcx.hir().expect_item(parent); let item = cx.tcx.hir().expect_item(parent);
let def_id = cx.tcx.hir().local_def_id(item.hir_id); let def_id = cx.tcx.hir().local_def_id(item.hir_id);
let ty = cx.tcx.type_of(def_id); let self_ty = cx.tcx.type_of(def_id);
if_chain! { if_chain! {
if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind; if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind;
if let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir().body(id)).next(); if let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir().body(id)).next();
@ -1425,11 +1475,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
then { then {
if cx.access_levels.is_exported(impl_item.hir_id) { if cx.access_levels.is_exported(impl_item.hir_id) {
// check missing trait implementations // check missing trait implementations
for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { for &(method_name, n_args, fn_header, self_kind, out_type, trait_name) in &TRAIT_METHODS {
if name == method_name && if name == method_name &&
sig.decl.inputs.len() == n_args && sig.decl.inputs.len() == n_args &&
out_type.matches(cx, &sig.decl.output) && out_type.matches(cx, &sig.decl.output) &&
self_kind.matches(cx, ty, first_arg_ty) { self_kind.matches(cx, self_ty, first_arg_ty) &&
fn_header_equals(*fn_header, sig.header) {
span_lint(cx, SHOULD_IMPLEMENT_TRAIT, impl_item.span, &format!( span_lint(cx, SHOULD_IMPLEMENT_TRAIT, impl_item.span, &format!(
"defining a method called `{}` on this type; consider implementing \ "defining a method called `{}` on this type; consider implementing \
the `{}` trait or choosing a less ambiguous name", name, trait_name)); the `{}` trait or choosing a less ambiguous name", name, trait_name));
@ -1441,7 +1492,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
.iter() .iter()
.find(|(ref conv, _)| conv.check(&name)) .find(|(ref conv, _)| conv.check(&name))
{ {
if !self_kinds.iter().any(|k| k.matches(cx, ty, first_arg_ty)) { if !self_kinds.iter().any(|k| k.matches(cx, self_ty, first_arg_ty)) {
let lint = if item.vis.node.is_pub() { let lint = if item.vis.node.is_pub() {
WRONG_PUB_SELF_CONVENTION WRONG_PUB_SELF_CONVENTION
} else { } else {
@ -1471,8 +1522,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
if let hir::ImplItemKind::Fn(_, _) = impl_item.kind { if let hir::ImplItemKind::Fn(_, _) = impl_item.kind {
let ret_ty = return_ty(cx, impl_item.hir_id); let ret_ty = return_ty(cx, impl_item.hir_id);
let contains_self_ty = |ty: Ty<'tcx>| {
ty.walk().any(|inner| match inner.unpack() {
GenericArgKind::Type(inner_ty) => same_tys(cx, self_ty, inner_ty),
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
})
};
// walk the return type and check for Self (this does not check associated types) // walk the return type and check for Self (this does not check associated types)
if ret_ty.walk().any(|inner_type| same_tys(cx, ty, inner_type)) { if contains_self_ty(ret_ty) {
return; return;
} }
@ -1486,10 +1545,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
let associated_type = binder.skip_binder(); let associated_type = binder.skip_binder();
// walk the associated type and check for Self // walk the associated type and check for Self
for inner_type in associated_type.walk() { if contains_self_ty(associated_type) {
if same_tys(cx, ty, inner_type) { return;
return;
}
} }
}, },
(_, _) => {}, (_, _) => {},
@ -1497,7 +1554,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
} }
} }
if name == "new" && !same_tys(cx, ret_ty, ty) { if name == "new" && !same_tys(cx, ret_ty, self_ty) {
span_lint( span_lint(
cx, cx,
NEW_RET_NO_SELF, NEW_RET_NO_SELF,
@ -1801,9 +1858,9 @@ fn lint_expect_fun_call(
} }
let receiver_type = cx.tables.expr_ty_adjusted(&args[0]); let receiver_type = cx.tables.expr_ty_adjusted(&args[0]);
let closure_args = if match_type(cx, receiver_type, &paths::OPTION) { let closure_args = if is_type_diagnostic_item(cx, receiver_type, sym!(option_type)) {
"||" "||"
} else if match_type(cx, receiver_type, &paths::RESULT) { } else if is_type_diagnostic_item(cx, receiver_type, sym!(result_type)) {
"|_|" "|_|"
} else { } else {
return; return;
@ -1912,9 +1969,10 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, arg: &hir:
match &cx.tcx.hir().get(parent) { match &cx.tcx.hir().get(parent) {
hir::Node::Expr(parent) => match parent.kind { hir::Node::Expr(parent) => match parent.kind {
// &*x is a nop, &x.clone() is not // &*x is a nop, &x.clone() is not
hir::ExprKind::AddrOf(..) | hir::ExprKind::AddrOf(..) => return,
// (*x).func() is useless, x.clone().func() can work in case func borrows mutably // (*x).func() is useless, x.clone().func() can work in case func borrows mutably
hir::ExprKind::MethodCall(..) => return, hir::ExprKind::MethodCall(_, _, parent_args) if expr.hir_id == parent_args[0].hir_id => return,
_ => {}, _ => {},
}, },
hir::Node::Stmt(stmt) => { hir::Node::Stmt(stmt) => {
@ -1962,9 +2020,9 @@ fn lint_clone_on_ref_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, arg: &h
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(arg)); let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(arg));
if let ty::Adt(_, subst) = obj_ty.kind { if let ty::Adt(_, subst) = obj_ty.kind {
let caller_type = if match_type(cx, obj_ty, &paths::RC) { let caller_type = if is_type_diagnostic_item(cx, obj_ty, sym::Rc) {
"Rc" "Rc"
} else if match_type(cx, obj_ty, &paths::ARC) { } else if is_type_diagnostic_item(cx, obj_ty, sym::Arc) {
"Arc" "Arc"
} else if match_type(cx, obj_ty, &paths::WEAK_RC) || match_type(cx, obj_ty, &paths::WEAK_ARC) { } else if match_type(cx, obj_ty, &paths::WEAK_RC) || match_type(cx, obj_ty, &paths::WEAK_ARC) {
"Weak" "Weak"
@ -2031,7 +2089,7 @@ fn lint_cstring_as_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, source: &
if_chain! { if_chain! {
let source_type = cx.tables.expr_ty(source); let source_type = cx.tables.expr_ty(source);
if let ty::Adt(def, substs) = source_type.kind; if let ty::Adt(def, substs) = source_type.kind;
if match_def_path(cx, def.did, &paths::RESULT); if cx.tcx.is_diagnostic_item(sym!(result_type), def.did);
if match_type(cx, substs.type_at(0), &paths::CSTRING); if match_type(cx, substs.type_at(0), &paths::CSTRING);
then { then {
span_lint_and_then( span_lint_and_then(
@ -2053,7 +2111,7 @@ fn lint_iter_cloned_collect<'a, 'tcx>(
iter_args: &'tcx [hir::Expr<'_>], iter_args: &'tcx [hir::Expr<'_>],
) { ) {
if_chain! { if_chain! {
if is_type_diagnostic_item(cx, cx.tables.expr_ty(expr), Symbol::intern("vec_type")); if is_type_diagnostic_item(cx, cx.tables.expr_ty(expr), sym!(vec_type));
if let Some(slice) = derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])); if let Some(slice) = derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0]));
if let Some(to_replace) = expr.span.trim_start(slice.span.source_callsite()); if let Some(to_replace) = expr.span.trim_start(slice.span.source_callsite());
@ -2182,7 +2240,7 @@ fn lint_iter_nth<'a, 'tcx>(
let mut_str = if is_mut { "_mut" } else { "" }; let mut_str = if is_mut { "_mut" } else { "" };
let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() { let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() {
"slice" "slice"
} else if is_type_diagnostic_item(cx, cx.tables.expr_ty(&iter_args[0]), Symbol::intern("vec_type")) { } else if is_type_diagnostic_item(cx, cx.tables.expr_ty(&iter_args[0]), sym!(vec_type)) {
"Vec" "Vec"
} else if match_type(cx, cx.tables.expr_ty(&iter_args[0]), &paths::VEC_DEQUE) { } else if match_type(cx, cx.tables.expr_ty(&iter_args[0]), &paths::VEC_DEQUE) {
"VecDeque" "VecDeque"
@ -2239,7 +2297,7 @@ fn lint_get_unwrap<'a, 'tcx>(
let caller_type = if derefs_to_slice(cx, &get_args[0], expr_ty).is_some() { let caller_type = if derefs_to_slice(cx, &get_args[0], expr_ty).is_some() {
needs_ref = get_args_str.parse::<usize>().is_ok(); needs_ref = get_args_str.parse::<usize>().is_ok();
"slice" "slice"
} else if is_type_diagnostic_item(cx, expr_ty, Symbol::intern("vec_type")) { } else if is_type_diagnostic_item(cx, expr_ty, sym!(vec_type)) {
needs_ref = get_args_str.parse::<usize>().is_ok(); needs_ref = get_args_str.parse::<usize>().is_ok();
"Vec" "Vec"
} else if match_type(cx, expr_ty, &paths::VEC_DEQUE) { } else if match_type(cx, expr_ty, &paths::VEC_DEQUE) {
@ -2320,7 +2378,7 @@ fn derefs_to_slice<'a, 'tcx>(
match ty.kind { match ty.kind {
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(..) => is_type_diagnostic_item(cx, ty, Symbol::intern("vec_type")), ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym!(vec_type)),
ty::Array(_, size) => { ty::Array(_, size) => {
if let Some(size) = size.try_eval_usize(cx.tcx, cx.param_env) { if let Some(size) = size.try_eval_usize(cx.tcx, cx.param_env) {
size < 32 size < 32
@ -2359,9 +2417,9 @@ fn derefs_to_slice<'a, 'tcx>(
fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, unwrap_args: &[hir::Expr<'_>]) { fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, unwrap_args: &[hir::Expr<'_>]) {
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&unwrap_args[0])); let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&unwrap_args[0]));
let mess = if match_type(cx, obj_ty, &paths::OPTION) { let mess = if is_type_diagnostic_item(cx, obj_ty, sym!(option_type)) {
Some((OPTION_UNWRAP_USED, "an Option", "None")) Some((OPTION_UNWRAP_USED, "an Option", "None"))
} else if match_type(cx, obj_ty, &paths::RESULT) { } else if is_type_diagnostic_item(cx, obj_ty, sym!(result_type)) {
Some((RESULT_UNWRAP_USED, "a Result", "Err")) Some((RESULT_UNWRAP_USED, "a Result", "Err"))
} else { } else {
None None
@ -2386,9 +2444,9 @@ fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, unwrap_args: &[hi
fn lint_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, expect_args: &[hir::Expr<'_>]) { fn lint_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, expect_args: &[hir::Expr<'_>]) {
let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&expect_args[0])); let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&expect_args[0]));
let mess = if match_type(cx, obj_ty, &paths::OPTION) { let mess = if is_type_diagnostic_item(cx, obj_ty, sym!(option_type)) {
Some((OPTION_EXPECT_USED, "an Option", "None")) Some((OPTION_EXPECT_USED, "an Option", "None"))
} else if match_type(cx, obj_ty, &paths::RESULT) { } else if is_type_diagnostic_item(cx, obj_ty, sym!(result_type)) {
Some((RESULT_EXPECT_USED, "a Result", "Err")) Some((RESULT_EXPECT_USED, "a Result", "Err"))
} else { } else {
None None
@ -2409,7 +2467,7 @@ fn lint_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, expect_args: &[hi
fn lint_ok_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, ok_args: &[hir::Expr<'_>]) { fn lint_ok_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, ok_args: &[hir::Expr<'_>]) {
if_chain! { if_chain! {
// lint if the caller of `ok()` is a `Result` // lint if the caller of `ok()` is a `Result`
if match_type(cx, cx.tables.expr_ty(&ok_args[0]), &paths::RESULT); if is_type_diagnostic_item(cx, cx.tables.expr_ty(&ok_args[0]), sym!(result_type));
let result_type = cx.tables.expr_ty(&ok_args[0]); let result_type = cx.tables.expr_ty(&ok_args[0]);
if let Some(error_type) = get_error_type(cx, result_type); if let Some(error_type) = get_error_type(cx, result_type);
if has_debug_impl(error_type, cx); if has_debug_impl(error_type, cx);
@ -2455,8 +2513,8 @@ fn lint_map_unwrap_or_else<'a, 'tcx>(
unwrap_args: &'tcx [hir::Expr<'_>], unwrap_args: &'tcx [hir::Expr<'_>],
) { ) {
// lint if the caller of `map()` is an `Option` // lint if the caller of `map()` is an `Option`
let is_option = match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION); let is_option = is_type_diagnostic_item(cx, cx.tables.expr_ty(&map_args[0]), sym!(option_type));
let is_result = match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::RESULT); let is_result = is_type_diagnostic_item(cx, cx.tables.expr_ty(&map_args[0]), sym!(result_type));
if is_option || is_result { if is_option || is_result {
// Don't make a suggestion that may fail to compile due to mutably borrowing // Don't make a suggestion that may fail to compile due to mutably borrowing
@ -2517,38 +2575,78 @@ fn lint_map_unwrap_or_else<'a, 'tcx>(
} }
} }
/// lint use of `_.map_or(None, _)` for `Option`s /// lint use of `_.map_or(None, _)` for `Option`s and `Result`s
fn lint_map_or_none<'a, 'tcx>( fn lint_map_or_none<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>, cx: &LateContext<'a, 'tcx>,
expr: &'tcx hir::Expr<'_>, expr: &'tcx hir::Expr<'_>,
map_or_args: &'tcx [hir::Expr<'_>], map_or_args: &'tcx [hir::Expr<'_>],
) { ) {
if match_type(cx, cx.tables.expr_ty(&map_or_args[0]), &paths::OPTION) { let is_option = is_type_diagnostic_item(cx, cx.tables.expr_ty(&map_or_args[0]), sym!(option_type));
// check if the first non-self argument to map_or() is None let is_result = is_type_diagnostic_item(cx, cx.tables.expr_ty(&map_or_args[0]), sym!(result_type));
let map_or_arg_is_none = if let hir::ExprKind::Path(ref qpath) = map_or_args[1].kind {
// There are two variants of this `map_or` lint:
// (1) using `map_or` as an adapter from `Result<T,E>` to `Option<T>`
// (2) using `map_or` as a combinator instead of `and_then`
//
// (For this lint) we don't care if any other type calls `map_or`
if !is_option && !is_result {
return;
}
let (lint_name, msg, instead, hint) = {
let default_arg_is_none = if let hir::ExprKind::Path(ref qpath) = map_or_args[1].kind {
match_qpath(qpath, &paths::OPTION_NONE) match_qpath(qpath, &paths::OPTION_NONE)
} else {
return;
};
if !default_arg_is_none {
// nothing to lint!
return;
}
let f_arg_is_some = if let hir::ExprKind::Path(ref qpath) = map_or_args[2].kind {
match_qpath(qpath, &paths::OPTION_SOME)
} else { } else {
false false
}; };
if map_or_arg_is_none { if is_option {
// lint message let self_snippet = snippet(cx, map_or_args[0].span, "..");
let func_snippet = snippet(cx, map_or_args[2].span, "..");
let msg = "called `map_or(None, f)` on an `Option` value. This can be done more directly by calling \ let msg = "called `map_or(None, f)` on an `Option` value. This can be done more directly by calling \
`and_then(f)` instead"; `and_then(f)` instead";
let map_or_self_snippet = snippet(cx, map_or_args[0].span, ".."); (
let map_or_func_snippet = snippet(cx, map_or_args[2].span, "..");
let hint = format!("{0}.and_then({1})", map_or_self_snippet, map_or_func_snippet);
span_lint_and_sugg(
cx,
OPTION_MAP_OR_NONE, OPTION_MAP_OR_NONE,
expr.span,
msg, msg,
"try using `and_then` instead", "try using `and_then` instead",
hint, format!("{0}.and_then({1})", self_snippet, func_snippet),
Applicability::MachineApplicable, )
); } else if f_arg_is_some {
let msg = "called `map_or(None, Some)` on a `Result` value. This can be done more directly by calling \
`ok()` instead";
let self_snippet = snippet(cx, map_or_args[0].span, "..");
(
RESULT_MAP_OR_INTO_OPTION,
msg,
"try using `ok` instead",
format!("{0}.ok()", self_snippet),
)
} else {
// nothing to lint!
return;
} }
} };
span_lint_and_sugg(
cx,
lint_name,
expr.span,
msg,
instead,
hint,
Applicability::MachineApplicable,
);
} }
/// Lint use of `_.and_then(|x| Some(y))` for `Option`s /// Lint use of `_.and_then(|x| Some(y))` for `Option`s
@ -3133,10 +3231,7 @@ fn is_maybe_uninit_ty_valid(cx: &LateContext<'_, '_>, ty: Ty<'_>) -> bool {
match ty.kind { match ty.kind {
ty::Array(ref component, _) => is_maybe_uninit_ty_valid(cx, component), ty::Array(ref component, _) => is_maybe_uninit_ty_valid(cx, component),
ty::Tuple(ref types) => types.types().all(|ty| is_maybe_uninit_ty_valid(cx, ty)), ty::Tuple(ref types) => types.types().all(|ty| is_maybe_uninit_ty_valid(cx, ty)),
ty::Adt(ref adt, _) => { ty::Adt(ref adt, _) => match_def_path(cx, adt.did, &paths::MEM_MAYBEUNINIT),
// needs to be a MaybeUninit
match_def_path(cx, adt.did, &paths::MEM_MAYBEUNINIT)
},
_ => false, _ => false,
} }
} }
@ -3159,6 +3254,8 @@ fn lint_option_as_ref_deref<'a, 'tcx>(
map_args: &[hir::Expr<'_>], map_args: &[hir::Expr<'_>],
is_mut: bool, is_mut: bool,
) { ) {
let same_mutability = |m| (is_mut && m == &hir::Mutability::Mut) || (!is_mut && m == &hir::Mutability::Not);
let option_ty = cx.tables.expr_ty(&as_ref_args[0]); let option_ty = cx.tables.expr_ty(&as_ref_args[0]);
if !match_type(cx, option_ty, &paths::OPTION) { if !match_type(cx, option_ty, &paths::OPTION) {
return; return;
@ -3181,39 +3278,56 @@ fn lint_option_as_ref_deref<'a, 'tcx>(
hir::ExprKind::Closure(_, _, body_id, _, _) => { hir::ExprKind::Closure(_, _, body_id, _, _) => {
let closure_body = cx.tcx.hir().body(body_id); let closure_body = cx.tcx.hir().body(body_id);
let closure_expr = remove_blocks(&closure_body.value); let closure_expr = remove_blocks(&closure_body.value);
if_chain! {
if let hir::ExprKind::MethodCall(_, _, args) = &closure_expr.kind; match &closure_expr.kind {
if args.len() == 1; hir::ExprKind::MethodCall(_, _, args) => {
if let hir::ExprKind::Path(qpath) = &args[0].kind; if_chain! {
if let hir::def::Res::Local(local_id) = cx.tables.qpath_res(qpath, args[0].hir_id); if args.len() == 1;
if closure_body.params[0].pat.hir_id == local_id; if let hir::ExprKind::Path(qpath) = &args[0].kind;
let adj = cx.tables.expr_adjustments(&args[0]).iter().map(|x| &x.kind).collect::<Box<[_]>>(); if let hir::def::Res::Local(local_id) = cx.tables.qpath_res(qpath, args[0].hir_id);
if let [ty::adjustment::Adjust::Deref(None), ty::adjustment::Adjust::Borrow(_)] = *adj; if closure_body.params[0].pat.hir_id == local_id;
then { let adj = cx.tables.expr_adjustments(&args[0]).iter().map(|x| &x.kind).collect::<Box<[_]>>();
let method_did = cx.tables.type_dependent_def_id(closure_expr.hir_id).unwrap(); if let [ty::adjustment::Adjust::Deref(None), ty::adjustment::Adjust::Borrow(_)] = *adj;
deref_aliases.iter().any(|path| match_def_path(cx, method_did, path)) then {
} else { let method_did = cx.tables.type_dependent_def_id(closure_expr.hir_id).unwrap();
false deref_aliases.iter().any(|path| match_def_path(cx, method_did, path))
} } else {
false
}
}
},
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, m, ref inner) if same_mutability(m) => {
if_chain! {
if let hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner1) = inner.kind;
if let hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner2) = inner1.kind;
if let hir::ExprKind::Path(ref qpath) = inner2.kind;
if let hir::def::Res::Local(local_id) = cx.tables.qpath_res(qpath, inner2.hir_id);
then {
closure_body.params[0].pat.hir_id == local_id
} else {
false
}
}
},
_ => false,
} }
}, },
_ => false, _ => false,
}; };
if is_deref { if is_deref {
let current_method = if is_mut { let current_method = if is_mut {
".as_mut().map(DerefMut::deref_mut)" format!(".as_mut().map({})", snippet(cx, map_args[1].span, ".."))
} else { } else {
".as_ref().map(Deref::deref)" format!(".as_ref().map({})", snippet(cx, map_args[1].span, ".."))
}; };
let method_hint = if is_mut { "as_deref_mut" } else { "as_deref" }; let method_hint = if is_mut { "as_deref_mut" } else { "as_deref" };
let hint = format!("{}.{}()", snippet(cx, as_ref_args[0].span, ".."), method_hint); let hint = format!("{}.{}()", snippet(cx, as_ref_args[0].span, ".."), method_hint);
let suggestion = format!("try using {} instead", method_hint); let suggestion = format!("try using {} instead", method_hint);
let msg = format!( let msg = format!(
"called `{0}` (or with one of deref aliases) on an Option value. \ "called `{0}` on an Option value. This can be done more directly \
This can be done more directly by calling `{1}` instead", by calling `{1}` instead",
current_method, hint current_method, hint
); );
span_lint_and_sugg( span_lint_and_sugg(
@ -3231,7 +3345,7 @@ fn lint_option_as_ref_deref<'a, 'tcx>(
/// Given a `Result<T, E>` type, return its error type (`E`). /// Given a `Result<T, E>` type, return its error type (`E`).
fn get_error_type<'a>(cx: &LateContext<'_, '_>, ty: Ty<'a>) -> Option<Ty<'a>> { fn get_error_type<'a>(cx: &LateContext<'_, '_>, ty: Ty<'a>) -> Option<Ty<'a>> {
match ty.kind { match ty.kind {
ty::Adt(_, substs) if match_type(cx, ty, &paths::RESULT) => substs.types().nth(1), ty::Adt(_, substs) if is_type_diagnostic_item(cx, ty, sym!(result_type)) => substs.types().nth(1),
_ => None, _ => None,
} }
} }
@ -3259,38 +3373,45 @@ const CONVENTIONS: [(Convention, &[SelfKind]); 7] = [
(Convention::StartsWith("to_"), &[SelfKind::Ref]), (Convention::StartsWith("to_"), &[SelfKind::Ref]),
]; ];
const FN_HEADER: hir::FnHeader = hir::FnHeader {
unsafety: hir::Unsafety::Normal,
constness: hir::Constness::NotConst,
asyncness: hir::IsAsync::NotAsync,
abi: rustc_target::spec::abi::Abi::Rust,
};
#[rustfmt::skip] #[rustfmt::skip]
const TRAIT_METHODS: [(&str, usize, SelfKind, OutType, &str); 30] = [ const TRAIT_METHODS: [(&str, usize, &hir::FnHeader, SelfKind, OutType, &str); 30] = [
("add", 2, SelfKind::Value, OutType::Any, "std::ops::Add"), ("add", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Add"),
("as_mut", 1, SelfKind::RefMut, OutType::Ref, "std::convert::AsMut"), ("as_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::convert::AsMut"),
("as_ref", 1, SelfKind::Ref, OutType::Ref, "std::convert::AsRef"), ("as_ref", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, "std::convert::AsRef"),
("bitand", 2, SelfKind::Value, OutType::Any, "std::ops::BitAnd"), ("bitand", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::BitAnd"),
("bitor", 2, SelfKind::Value, OutType::Any, "std::ops::BitOr"), ("bitor", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::BitOr"),
("bitxor", 2, SelfKind::Value, OutType::Any, "std::ops::BitXor"), ("bitxor", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::BitXor"),
("borrow", 1, SelfKind::Ref, OutType::Ref, "std::borrow::Borrow"), ("borrow", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, "std::borrow::Borrow"),
("borrow_mut", 1, SelfKind::RefMut, OutType::Ref, "std::borrow::BorrowMut"), ("borrow_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::borrow::BorrowMut"),
("clone", 1, SelfKind::Ref, OutType::Any, "std::clone::Clone"), ("clone", 1, &FN_HEADER, SelfKind::Ref, OutType::Any, "std::clone::Clone"),
("cmp", 2, SelfKind::Ref, OutType::Any, "std::cmp::Ord"), ("cmp", 2, &FN_HEADER, SelfKind::Ref, OutType::Any, "std::cmp::Ord"),
("default", 0, SelfKind::No, OutType::Any, "std::default::Default"), ("default", 0, &FN_HEADER, SelfKind::No, OutType::Any, "std::default::Default"),
("deref", 1, SelfKind::Ref, OutType::Ref, "std::ops::Deref"), ("deref", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, "std::ops::Deref"),
("deref_mut", 1, SelfKind::RefMut, OutType::Ref, "std::ops::DerefMut"), ("deref_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::ops::DerefMut"),
("div", 2, SelfKind::Value, OutType::Any, "std::ops::Div"), ("div", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Div"),
("drop", 1, SelfKind::RefMut, OutType::Unit, "std::ops::Drop"), ("drop", 1, &FN_HEADER, SelfKind::RefMut, OutType::Unit, "std::ops::Drop"),
("eq", 2, SelfKind::Ref, OutType::Bool, "std::cmp::PartialEq"), ("eq", 2, &FN_HEADER, SelfKind::Ref, OutType::Bool, "std::cmp::PartialEq"),
("from_iter", 1, SelfKind::No, OutType::Any, "std::iter::FromIterator"), ("from_iter", 1, &FN_HEADER, SelfKind::No, OutType::Any, "std::iter::FromIterator"),
("from_str", 1, SelfKind::No, OutType::Any, "std::str::FromStr"), ("from_str", 1, &FN_HEADER, SelfKind::No, OutType::Any, "std::str::FromStr"),
("hash", 2, SelfKind::Ref, OutType::Unit, "std::hash::Hash"), ("hash", 2, &FN_HEADER, SelfKind::Ref, OutType::Unit, "std::hash::Hash"),
("index", 2, SelfKind::Ref, OutType::Ref, "std::ops::Index"), ("index", 2, &FN_HEADER, SelfKind::Ref, OutType::Ref, "std::ops::Index"),
("index_mut", 2, SelfKind::RefMut, OutType::Ref, "std::ops::IndexMut"), ("index_mut", 2, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::ops::IndexMut"),
("into_iter", 1, SelfKind::Value, OutType::Any, "std::iter::IntoIterator"), ("into_iter", 1, &FN_HEADER, SelfKind::Value, OutType::Any, "std::iter::IntoIterator"),
("mul", 2, SelfKind::Value, OutType::Any, "std::ops::Mul"), ("mul", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Mul"),
("neg", 1, SelfKind::Value, OutType::Any, "std::ops::Neg"), ("neg", 1, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Neg"),
("next", 1, SelfKind::RefMut, OutType::Any, "std::iter::Iterator"), ("next", 1, &FN_HEADER, SelfKind::RefMut, OutType::Any, "std::iter::Iterator"),
("not", 1, SelfKind::Value, OutType::Any, "std::ops::Not"), ("not", 1, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Not"),
("rem", 2, SelfKind::Value, OutType::Any, "std::ops::Rem"), ("rem", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Rem"),
("shl", 2, SelfKind::Value, OutType::Any, "std::ops::Shl"), ("shl", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Shl"),
("shr", 2, SelfKind::Value, OutType::Any, "std::ops::Shr"), ("shr", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Shr"),
("sub", 2, SelfKind::Value, OutType::Any, "std::ops::Sub"), ("sub", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Sub"),
]; ];
#[rustfmt::skip] #[rustfmt::skip]
@ -3324,12 +3445,12 @@ enum SelfKind {
impl SelfKind { impl SelfKind {
fn matches<'a>(self, cx: &LateContext<'_, 'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool { fn matches<'a>(self, cx: &LateContext<'_, 'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool {
fn matches_value(parent_ty: Ty<'_>, ty: Ty<'_>) -> bool { fn matches_value<'a>(cx: &LateContext<'_, 'a>, parent_ty: Ty<'_>, ty: Ty<'_>) -> bool {
if ty == parent_ty { if ty == parent_ty {
true true
} else if ty.is_box() { } else if ty.is_box() {
ty.boxed_ty() == parent_ty ty.boxed_ty() == parent_ty
} else if ty.is_rc() || ty.is_arc() { } else if is_type_diagnostic_item(cx, ty, sym::Rc) || is_type_diagnostic_item(cx, ty, sym::Arc) {
if let ty::Adt(_, substs) = ty.kind { if let ty::Adt(_, substs) = ty.kind {
substs.types().next().map_or(false, |t| t == parent_ty) substs.types().next().map_or(false, |t| t == parent_ty)
} else { } else {
@ -3363,7 +3484,7 @@ impl SelfKind {
} }
match self { match self {
Self::Value => matches_value(parent_ty, ty), Self::Value => matches_value(cx, parent_ty, ty),
Self::Ref => matches_ref(cx, hir::Mutability::Not, parent_ty, ty) || ty == parent_ty && is_copy(cx, ty), Self::Ref => matches_ref(cx, hir::Mutability::Not, parent_ty, ty) || ty == parent_ty && is_copy(cx, ty),
Self::RefMut => matches_ref(cx, hir::Mutability::Mut, parent_ty, ty), Self::RefMut => matches_ref(cx, hir::Mutability::Mut, parent_ty, ty),
Self::No => ty != parent_ty, Self::No => ty != parent_ty,
@ -3503,3 +3624,9 @@ fn lint_filetype_is_file(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, args: &
let help_msg = format!("use `{}FileType::is_dir()` instead", help_unary); let help_msg = format!("use `{}FileType::is_dir()` instead", help_unary);
span_lint_and_help(cx, FILETYPE_IS_FILE, span, &lint_msg, &help_msg); span_lint_and_help(cx, FILETYPE_IS_FILE, span, &lint_msg, &help_msg);
} }
fn fn_header_equals(expected: hir::FnHeader, actual: hir::FnHeader) -> bool {
expected.constness == actual.constness
&& expected.unsafety == actual.unsafety
&& expected.asyncness == actual.asyncness
}

View File

@ -1,11 +1,11 @@
use crate::utils::{differing_macro_contexts, paths, snippet_with_applicability, span_lint_and_then}; use crate::utils::{differing_macro_contexts, snippet_with_applicability, span_lint_and_then};
use crate::utils::{is_copy, match_type}; use crate::utils::{is_copy, is_type_diagnostic_item};
use rustc::hir::map::Map;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_path, NestedVisitorMap, Visitor}; use rustc_hir::intravisit::{walk_path, NestedVisitorMap, Visitor};
use rustc_hir::{self, HirId, Path}; use rustc_hir::{self, HirId, Path};
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_middle::hir::map::Map;
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
@ -20,7 +20,7 @@ pub(super) fn lint<'a, 'tcx>(
map_span: Span, map_span: Span,
) { ) {
// lint if the caller of `map()` is an `Option` // lint if the caller of `map()` is an `Option`
if match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION) { if is_type_diagnostic_item(cx, cx.tables.expr_ty(&map_args[0]), sym!(option_type)) {
if !is_copy(cx, cx.tables.expr_ty(&unwrap_args[1])) { if !is_copy(cx, cx.tables.expr_ty(&unwrap_args[1])) {
// Do not lint if the `map` argument uses identifiers in the `map` // Do not lint if the `map` argument uses identifiers in the `map`
// argument that are also used in the `unwrap_or` argument // argument that are also used in the `unwrap_or` argument

View File

@ -1,11 +1,11 @@
use crate::utils::paths; use crate::utils::paths;
use crate::utils::usage::mutated_variables; use crate::utils::usage::mutated_variables;
use crate::utils::{match_qpath, match_trait_method, span_lint}; use crate::utils::{match_qpath, match_trait_method, span_lint};
use rustc::hir::map::Map;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::Res; use rustc_hir::def::Res;
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_middle::hir::map::Map;
use if_chain::if_chain; use if_chain::if_chain;

View File

@ -1,5 +1,4 @@
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty;
use rustc_ast::ast::LitKind; use rustc_ast::ast::LitKind;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind; use rustc_hir::intravisit::FnKind;
@ -8,6 +7,7 @@ use rustc_hir::{
TyKind, UnOp, TyKind, UnOp,
}; };
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::{ExpnKind, Span}; use rustc_span::source_map::{ExpnKind, Span};
@ -57,10 +57,9 @@ declare_clippy_lint! {
/// ///
/// **Example:** /// **Example:**
/// ```rust /// ```rust
/// # use core::f32::NAN;
/// # let x = 1.0; /// # let x = 1.0;
/// ///
/// if x == NAN { } /// if x == f32::NAN { }
/// ``` /// ```
pub CMP_NAN, pub CMP_NAN,
correctness, correctness,
@ -370,26 +369,28 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints {
return; return;
} }
} }
let (lint, msg) = if is_named_constant(cx, left) || is_named_constant(cx, right) { let is_comparing_arrays = is_array(cx, left) || is_array(cx, right);
(FLOAT_CMP_CONST, "strict comparison of `f32` or `f64` constant") let (lint, msg) = get_lint_and_message(
} else { is_named_constant(cx, left) || is_named_constant(cx, right),
(FLOAT_CMP, "strict comparison of `f32` or `f64`") is_comparing_arrays,
}; );
span_lint_and_then(cx, lint, expr.span, msg, |db| { span_lint_and_then(cx, lint, expr.span, msg, |db| {
let lhs = Sugg::hir(cx, left, ".."); let lhs = Sugg::hir(cx, left, "..");
let rhs = Sugg::hir(cx, right, ".."); let rhs = Sugg::hir(cx, right, "..");
db.span_suggestion( if !is_comparing_arrays {
expr.span, db.span_suggestion(
"consider comparing them within some error", expr.span,
format!( "consider comparing them within some error",
"({}).abs() {} error", format!(
lhs - rhs, "({}).abs() {} error",
if op == BinOpKind::Eq { '<' } else { '>' } lhs - rhs,
), if op == BinOpKind::Eq { '<' } else { '>' }
Applicability::HasPlaceholders, // snippet ),
); Applicability::HasPlaceholders, // snippet
db.span_note(expr.span, "`std::f32::EPSILON` and `std::f64::EPSILON` are available."); );
}
db.note("`f32::EPSILON` and `f64::EPSILON` are available for the `error`");
}); });
} else if op == BinOpKind::Rem && is_integer_const(cx, right, 1) { } else if op == BinOpKind::Rem && is_integer_const(cx, right, 1) {
span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0"); span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0");
@ -441,6 +442,31 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints {
} }
} }
fn get_lint_and_message(
is_comparing_constants: bool,
is_comparing_arrays: bool,
) -> (&'static rustc_lint::Lint, &'static str) {
if is_comparing_constants {
(
FLOAT_CMP_CONST,
if is_comparing_arrays {
"strict comparison of `f32` or `f64` constant arrays"
} else {
"strict comparison of `f32` or `f64` constant"
},
)
} else {
(
FLOAT_CMP,
if is_comparing_arrays {
"strict comparison of `f32` or `f64` arrays"
} else {
"strict comparison of `f32` or `f64`"
},
)
}
}
fn check_nan(cx: &LateContext<'_, '_>, expr: &Expr<'_>, cmp_expr: &Expr<'_>) { fn check_nan(cx: &LateContext<'_, '_>, expr: &Expr<'_>, cmp_expr: &Expr<'_>) {
if_chain! { if_chain! {
if !in_constant(cx, cmp_expr.hir_id); if !in_constant(cx, cmp_expr.hir_id);
@ -457,7 +483,7 @@ fn check_nan(cx: &LateContext<'_, '_>, expr: &Expr<'_>, cmp_expr: &Expr<'_>) {
cx, cx,
CMP_NAN, CMP_NAN,
cmp_expr.span, cmp_expr.span,
"doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead", "doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead",
); );
} }
} }
@ -476,6 +502,11 @@ fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) -> boo
match constant(cx, cx.tables, expr) { match constant(cx, cx.tables, expr) {
Some((Constant::F32(f), _)) => f == 0.0 || f.is_infinite(), Some((Constant::F32(f), _)) => f == 0.0 || f.is_infinite(),
Some((Constant::F64(f), _)) => f == 0.0 || f.is_infinite(), Some((Constant::F64(f), _)) => f == 0.0 || f.is_infinite(),
Some((Constant::Vec(vec), _)) => vec.iter().all(|f| match f {
Constant::F32(f) => *f == 0.0 || (*f).is_infinite(),
Constant::F64(f) => *f == 0.0 || (*f).is_infinite(),
_ => false,
}),
_ => false, _ => false,
} }
} }
@ -500,7 +531,17 @@ fn is_signum(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
} }
fn is_float(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { fn is_float(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
matches!(walk_ptrs_ty(cx.tables.expr_ty(expr)).kind, ty::Float(_)) let value = &walk_ptrs_ty(cx.tables.expr_ty(expr)).kind;
if let ty::Array(arr_ty, _) = value {
return matches!(arr_ty.kind, ty::Float(_));
};
matches!(value, ty::Float(_))
}
fn is_array(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
matches!(&walk_ptrs_ty(cx.tables.expr_ty(expr)).kind, ty::Array(_, _))
} }
fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr<'_>, other: &Expr<'_>) { fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr<'_>, other: &Expr<'_>) {

View File

@ -3,7 +3,6 @@ use crate::utils::{
span_lint_and_then, span_lint_and_then,
}; };
use if_chain::if_chain; use if_chain::if_chain;
use rustc::lint::in_external_macro;
use rustc_ast::ast::{ use rustc_ast::ast::{
BindingMode, Block, Expr, ExprKind, GenericParamKind, Generics, Lit, LitFloatType, LitIntType, LitKind, Mutability, BindingMode, Block, Expr, ExprKind, GenericParamKind, Generics, Lit, LitFloatType, LitIntType, LitKind, Mutability,
NodeId, Pat, PatKind, StmtKind, UnOp, NodeId, Pat, PatKind, StmtKind, UnOp,
@ -12,6 +11,7 @@ use rustc_ast::visit::{walk_expr, FnKind, Visitor};
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;

View File

@ -1,9 +1,9 @@
use crate::utils::{fn_has_unsatisfiable_preds, has_drop, is_entrypoint_fn, span_lint, trait_ref_of_method}; use crate::utils::{fn_has_unsatisfiable_preds, has_drop, is_entrypoint_fn, span_lint, trait_ref_of_method};
use rustc::lint::in_external_macro;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::intravisit::FnKind; use rustc_hir::intravisit::FnKind;
use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId}; use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_mir::transform::qualify_min_const_fn::is_min_const_fn; use rustc_mir::transform::qualify_min_const_fn::is_min_const_fn;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::Span; use rustc_span::Span;

View File

@ -7,11 +7,11 @@
use crate::utils::span_lint; use crate::utils::span_lint;
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty;
use rustc_ast::ast::{self, MetaItem, MetaItemKind}; use rustc_ast::ast::{self, MetaItem, MetaItemKind};
use rustc_ast::attr; use rustc_ast::attr;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::ty;
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;

View File

@ -81,7 +81,7 @@ declare_lint_pass!(MissingInline => [MISSING_INLINE_IN_PUBLIC_ITEMS]);
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item<'_>) { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item<'_>) {
if rustc::lint::in_external_macro(cx.sess(), it.span) || is_executable(cx) { if rustc_middle::lint::in_external_macro(cx.sess(), it.span) || is_executable(cx) {
return; return;
} }
@ -130,8 +130,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline {
} }
fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem<'_>) {
use rustc::ty::{ImplContainer, TraitContainer}; use rustc_middle::ty::{ImplContainer, TraitContainer};
if rustc::lint::in_external_macro(cx.sess(), impl_item.span) || is_executable(cx) { if rustc_middle::lint::in_external_macro(cx.sess(), impl_item.span) || is_executable(cx) {
return; return;
} }

View File

@ -1,9 +1,9 @@
use crate::consts::{constant, Constant}; use crate::consts::{constant, Constant};
use crate::utils::{sext, span_lint_and_then}; use crate::utils::{sext, span_lint_and_then};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty::{self};
use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use std::fmt::Display; use std::fmt::Display;

View File

@ -1,7 +1,7 @@
use crate::utils::{match_def_path, paths, span_lint, trait_ref_of_method, walk_ptrs_ty}; use crate::utils::{match_def_path, paths, span_lint, trait_ref_of_method, walk_ptrs_ty};
use rustc::ty::{Adt, Array, RawPtr, Ref, Slice, Tuple, Ty, TypeAndMut};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{Adt, Array, RawPtr, Ref, Slice, Tuple, Ty, TypeAndMut};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;

View File

@ -1,10 +1,10 @@
use crate::utils::{higher, span_lint}; use crate::utils::{higher, span_lint};
use rustc::hir::map::Map;
use rustc::lint::in_external_macro;
use rustc::ty;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::intravisit; use rustc_hir::intravisit;
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::map::Map;
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! { declare_clippy_lint! {

View File

@ -1,8 +1,8 @@
use crate::utils::span_lint; use crate::utils::span_lint;
use rustc::ty::subst::Subst; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability};
use rustc::ty::{self, Ty};
use rustc_hir::{print, BorrowKind, Expr, ExprKind, Mutability};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! { declare_clippy_lint! {
@ -34,7 +34,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed {
cx, cx,
arguments, arguments,
cx.tables.expr_ty(fn_expr), cx.tables.expr_ty(fn_expr),
&print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)), &rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false)),
); );
} }
}, },

View File

@ -1,10 +1,10 @@
use crate::utils::{is_direct_expn_of, span_lint}; use crate::utils::{is_direct_expn_of, span_lint};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::hir::map::Map;
use rustc::ty;
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc_hir::{BorrowKind, Expr, ExprKind, MatchSource, Mutability, StmtKind, UnOp}; use rustc_hir::{BorrowKind, Expr, ExprKind, MatchSource, Mutability, StmtKind, UnOp};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::Span; use rustc_span::Span;
@ -53,7 +53,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DebugAssertWithMutCall {
} }
//HACK(hellow554): remove this when #4694 is implemented //HACK(hellow554): remove this when #4694 is implemented
#[allow(clippy::cognitive_complexity)]
fn extract_call<'a, 'tcx>(cx: &'a LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) -> Option<Span> { fn extract_call<'a, 'tcx>(cx: &'a LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) -> Option<Span> {
if_chain! { if_chain! {
if let ExprKind::Block(ref block, _) = e.kind; if let ExprKind::Block(ref block, _) = e.kind;

View File

@ -3,10 +3,10 @@
//! This lint is **warn** by default //! This lint is **warn** by default
use crate::utils::{match_type, paths, span_lint}; use crate::utils::{match_type, paths, span_lint};
use rustc::ty::{self, Ty};
use rustc_ast::ast; use rustc_ast::ast;
use rustc_hir::Expr; use rustc_hir::Expr;
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! { declare_clippy_lint! {

View File

@ -3,13 +3,15 @@
//! This lint is **warn** by default //! This lint is **warn** by default
use crate::utils::sugg::Sugg; use crate::utils::sugg::Sugg;
use crate::utils::{higher, parent_node_is_if_expr, span_lint, span_lint_and_sugg}; use crate::utils::{higher, parent_node_is_if_expr, snippet_with_applicability, span_lint, span_lint_and_sugg};
use if_chain::if_chain;
use rustc_ast::ast::LitKind; use rustc_ast::ast::LitKind;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Block, Expr, ExprKind, StmtKind}; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Spanned; use rustc_span::source_map::Spanned;
use rustc_span::Span;
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for expressions of the form `if c { true } else { /// **What it does:** Checks for expressions of the form `if c { true } else {
@ -188,6 +190,34 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison {
} }
} }
struct ExpressionInfoWithSpan {
one_side_is_unary_not: bool,
left_span: Span,
right_span: Span,
}
fn is_unary_not(e: &Expr<'_>) -> (bool, Span) {
if_chain! {
if let ExprKind::Unary(unop, operand) = e.kind;
if let UnOp::UnNot = unop;
then {
return (true, operand.span);
}
};
(false, e.span)
}
fn one_side_is_unary_not<'tcx>(left_side: &'tcx Expr<'_>, right_side: &'tcx Expr<'_>) -> ExpressionInfoWithSpan {
let left = is_unary_not(left_side);
let right = is_unary_not(right_side);
ExpressionInfoWithSpan {
one_side_is_unary_not: left.0 != right.0,
left_span: left.1,
right_span: right.1,
}
}
fn check_comparison<'a, 'tcx>( fn check_comparison<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>, cx: &LateContext<'a, 'tcx>,
e: &'tcx Expr<'_>, e: &'tcx Expr<'_>,
@ -199,10 +229,30 @@ fn check_comparison<'a, 'tcx>(
) { ) {
use self::Expression::{Bool, Other}; use self::Expression::{Bool, Other};
if let ExprKind::Binary(_, ref left_side, ref right_side) = e.kind { if let ExprKind::Binary(op, ref left_side, ref right_side) = e.kind {
let (l_ty, r_ty) = (cx.tables.expr_ty(left_side), cx.tables.expr_ty(right_side)); let (l_ty, r_ty) = (cx.tables.expr_ty(left_side), cx.tables.expr_ty(right_side));
if l_ty.is_bool() && r_ty.is_bool() { if l_ty.is_bool() && r_ty.is_bool() {
let mut applicability = Applicability::MachineApplicable; let mut applicability = Applicability::MachineApplicable;
if let BinOpKind::Eq = op.node {
let expression_info = one_side_is_unary_not(&left_side, &right_side);
if expression_info.one_side_is_unary_not {
span_lint_and_sugg(
cx,
BOOL_COMPARISON,
e.span,
"This comparison might be written more concisely",
"try simplifying it as shown",
format!(
"{} != {}",
snippet_with_applicability(cx, expression_info.left_span, "..", &mut applicability),
snippet_with_applicability(cx, expression_info.right_span, "..", &mut applicability)
),
applicability,
)
}
}
match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) {
(Bool(true), Other) => left_true.map_or((), |(h, m)| { (Bool(true), Other) => left_true.map_or((), |(h, m)| {
suggest_bool_comparison(cx, e, right_side, applicability, m, h) suggest_bool_comparison(cx, e, right_side, applicability, m, h)

View File

@ -4,11 +4,11 @@
use crate::utils::{snippet_opt, span_lint_and_then}; use crate::utils::{snippet_opt, span_lint_and_then};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty;
use rustc::ty::adjustment::{Adjust, Adjustment};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{BindingAnnotation, BorrowKind, Expr, ExprKind, HirId, Item, Mutability, Pat, PatKind}; use rustc_hir::{BindingAnnotation, BorrowKind, Expr, ExprKind, HirId, Item, Mutability, Pat, PatKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_middle::ty::adjustment::{Adjust, Adjustment};
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
declare_clippy_lint! { declare_clippy_lint! {

View File

@ -4,7 +4,6 @@ use crate::utils::{
snippet, snippet_opt, span_lint_and_then, snippet, snippet_opt, span_lint_and_then,
}; };
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty::{self, TypeFoldable};
use rustc_ast::ast::Attribute; use rustc_ast::ast::Attribute;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_errors::{Applicability, DiagnosticBuilder};
@ -12,8 +11,9 @@ use rustc_hir::intravisit::FnKind;
use rustc_hir::{BindingAnnotation, Body, FnDecl, GenericArg, HirId, ItemKind, Node, PatKind, QPath, TyKind}; use rustc_hir::{BindingAnnotation, Body, FnDecl, GenericArg, HirId, ItemKind, Node, PatKind, QPath, TyKind};
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, TypeFoldable};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{Span, Symbol}; use rustc_span::Span;
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits; use rustc_trait_selection::traits;
use rustc_trait_selection::traits::misc::can_type_implement_copy; use rustc_trait_selection::traits::misc::can_type_implement_copy;
@ -113,8 +113,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds.to_vec()) let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds.to_vec())
.filter(|p| !p.is_global()) .filter(|p| !p.is_global())
.filter_map(|pred| { .filter_map(|obligation| {
if let ty::Predicate::Trait(poly_trait_ref, _) = pred { if let ty::Predicate::Trait(poly_trait_ref, _) = obligation.predicate {
if poly_trait_ref.def_id() == sized_trait || poly_trait_ref.skip_binder().has_escaping_bound_vars() if poly_trait_ref.def_id() == sized_trait || poly_trait_ref.skip_binder().has_escaping_bound_vars()
{ {
return None; return None;
@ -214,7 +214,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
let deref_span = spans_need_deref.get(&canonical_id); let deref_span = spans_need_deref.get(&canonical_id);
if_chain! { if_chain! {
if is_type_diagnostic_item(cx, ty, Symbol::intern("vec_type")); if is_type_diagnostic_item(cx, ty, sym!(vec_type));
if let Some(clone_spans) = if let Some(clone_spans) =
get_spans(cx, Some(body.id()), idx, &[("clone", ".to_owned()")]); get_spans(cx, Some(body.id()), idx, &[("clone", ".to_owned()")]);
if let TyKind::Path(QPath::Resolved(_, ref path)) = input.kind; if let TyKind::Path(QPath::Resolved(_, ref path)) = input.kind;

View File

@ -1,7 +1,7 @@
use crate::utils::span_lint; use crate::utils::span_lint;
use rustc::ty;
use rustc_hir::{Expr, ExprKind}; use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! { declare_clippy_lint! {

View File

@ -1,7 +1,7 @@
use if_chain::if_chain; use if_chain::if_chain;
use rustc::lint::in_external_macro;
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use crate::utils::{self, paths, span_lint}; use crate::utils::{self, paths, span_lint};
@ -25,13 +25,13 @@ declare_clippy_lint! {
/// ///
/// // Bad /// // Bad
/// let a = 1.0; /// let a = 1.0;
/// let b = std::f64::NAN; /// let b = f64::NAN;
/// ///
/// let _not_less_or_equal = !(a <= b); /// let _not_less_or_equal = !(a <= b);
/// ///
/// // Good /// // Good
/// let a = 1.0; /// let a = 1.0;
/// let b = std::f64::NAN; /// let b = f64::NAN;
/// ///
/// let _not_less_or_equal = match a.partial_cmp(&b) { /// let _not_less_or_equal = match a.partial_cmp(&b) {
/// None | Some(Ordering::Greater) => true, /// None | Some(Ordering::Greater) => true,

View File

@ -2,13 +2,13 @@ use crate::utils::paths;
use crate::utils::sugg::DiagnosticBuilderExt; use crate::utils::sugg::DiagnosticBuilderExt;
use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_hir_and_then}; use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_hir_and_then};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::lint::in_external_macro;
use rustc::ty::{self, Ty};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::HirIdSet; use rustc_hir::HirIdSet;
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
@ -100,7 +100,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
} = item.kind } = item.kind
{ {
for assoc_item in items { for assoc_item in items {
if let hir::AssocItemKind::Method { has_self: false } = assoc_item.kind { if let hir::AssocItemKind::Fn { has_self: false } = assoc_item.kind {
let impl_item = cx.tcx.hir().impl_item(assoc_item.id); let impl_item = cx.tcx.hir().impl_item(assoc_item.id);
if in_external_macro(cx.sess(), impl_item.span) { if in_external_macro(cx.sess(), impl_item.span) {
return; return;

View File

@ -4,11 +4,11 @@
use std::ptr; use std::ptr;
use rustc::ty::adjustment::Adjust;
use rustc::ty::{Ty, TypeFlags};
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp}; use rustc_hir::{Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp};
use rustc_lint::{LateContext, LateLintPass, Lint}; use rustc_lint::{LateContext, LateLintPass, Lint};
use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::{Ty, TypeFlags};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{InnerSpan, Span, DUMMY_SP}; use rustc_span::{InnerSpan, Span, DUMMY_SP};
use rustc_typeck::hir_ty_to_ty; use rustc_typeck::hir_ty_to_ty;

View File

@ -6,16 +6,16 @@ use crate::utils::{
walk_ptrs_hir_ty, walk_ptrs_hir_ty,
}; };
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{ use rustc_hir::{
BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, HirId, ImplItem, ImplItemKind, Item, ItemKind, BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, HirId, ImplItem, ImplItemKind, Item, ItemKind,
Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind,
}; };
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
use rustc_span::{MultiSpan, Symbol}; use rustc_span::MultiSpan;
use std::borrow::Cow; use std::borrow::Cow;
declare_clippy_lint! { declare_clippy_lint! {
@ -153,7 +153,7 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_
for (idx, (arg, ty)) in decl.inputs.iter().zip(fn_ty.inputs()).enumerate() { for (idx, (arg, ty)) in decl.inputs.iter().zip(fn_ty.inputs()).enumerate() {
if let ty::Ref(_, ty, Mutability::Not) = ty.kind { if let ty::Ref(_, ty, Mutability::Not) = ty.kind {
if is_type_diagnostic_item(cx, ty, Symbol::intern("vec_type")) { if is_type_diagnostic_item(cx, ty, sym!(vec_type)) {
let mut ty_snippet = None; let mut ty_snippet = None;
if_chain! { if_chain! {
if let TyKind::Path(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).kind; if let TyKind::Path(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).kind;

View File

@ -5,10 +5,10 @@ use rustc_hir::{def, BindingAnnotation, Block, Expr, ExprKind, MatchSource, PatK
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use crate::utils::paths::{OPTION, OPTION_NONE};
use crate::utils::sugg::Sugg; use crate::utils::sugg::Sugg;
use crate::utils::{ use crate::utils::{
higher, match_def_path, match_qpath, match_type, snippet_with_applicability, span_lint_and_sugg, SpanlessEq, higher, is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet_with_applicability,
span_lint_and_sugg, SpanlessEq,
}; };
declare_clippy_lint! { declare_clippy_lint! {
@ -141,7 +141,7 @@ impl QuestionMark {
fn is_option(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool { fn is_option(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool {
let expr_ty = cx.tables.expr_ty(expression); let expr_ty = cx.tables.expr_ty(expression);
match_type(cx, expr_ty, &OPTION) is_type_diagnostic_item(cx, expr_ty, sym!(option_type))
} }
fn expression_returns_none(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool { fn expression_returns_none(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool {
@ -158,7 +158,7 @@ impl QuestionMark {
if let Res::Def(DefKind::Ctor(def::CtorOf::Variant, def::CtorKind::Const), def_id) = if let Res::Def(DefKind::Ctor(def::CtorOf::Variant, def::CtorKind::Const), def_id) =
cx.tables.qpath_res(qp, expression.hir_id) cx.tables.qpath_res(qp, expression.hir_id)
{ {
return match_def_path(cx, def_id, &OPTION_NONE); return match_def_path(cx, def_id, &paths::OPTION_NONE);
} }
false false

View File

@ -3,19 +3,19 @@ use crate::utils::{
span_lint_hir_and_then, walk_ptrs_ty_depth, span_lint_hir_and_then, walk_ptrs_ty_depth,
}; };
use if_chain::if_chain; use if_chain::if_chain;
use rustc::mir::{
self, traversal,
visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor as _},
};
use rustc::ty::{self, fold::TypeVisitor, Ty};
use rustc_data_structures::{fx::FxHashMap, transitive_relation::TransitiveRelation}; use rustc_data_structures::{fx::FxHashMap, transitive_relation::TransitiveRelation};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind; use rustc_hir::intravisit::FnKind;
use rustc_hir::{def_id, Body, FnDecl, HirId}; use rustc_hir::{def_id, Body, FnDecl, HirId};
use rustc_index::bit_set::{BitSet, HybridBitSet}; use rustc_index::bit_set::{BitSet, HybridBitSet};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_mir::dataflow::generic::{Analysis, AnalysisDomain, GenKill, GenKillAnalysis, ResultsCursor}; use rustc_middle::mir::{
self, traversal,
visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor as _},
};
use rustc_middle::ty::{self, fold::TypeVisitor, Ty};
use rustc_mir::dataflow::BottomValue; use rustc_mir::dataflow::BottomValue;
use rustc_mir::dataflow::{Analysis, AnalysisDomain, GenKill, GenKillAnalysis, ResultsCursor};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::{BytePos, Span}; use rustc_span::source_map::{BytePos, Span};
use std::convert::TryFrom; use std::convert::TryFrom;
@ -80,20 +80,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone {
let def_id = cx.tcx.hir().body_owner_def_id(body.id()); let def_id = cx.tcx.hir().body_owner_def_id(body.id());
// Building MIR for `fn`s with unsatisfiable preds results in ICE. // Building MIR for `fn`s with unsatisfiable preds results in ICE.
if fn_has_unsatisfiable_preds(cx, def_id) { if fn_has_unsatisfiable_preds(cx, def_id.to_def_id()) {
return; return;
} }
let mir = cx.tcx.optimized_mir(def_id); let mir = cx.tcx.optimized_mir(def_id.to_def_id());
let mir_read_only = mir.unwrap_read_only(); let mir_read_only = mir.unwrap_read_only();
let maybe_storage_live_result = MaybeStorageLive let maybe_storage_live_result = MaybeStorageLive
.into_engine(cx.tcx, mir, def_id) .into_engine(cx.tcx, mir, def_id.to_def_id())
.iterate_to_fixpoint() .iterate_to_fixpoint()
.into_results_cursor(mir); .into_results_cursor(mir);
let mut possible_borrower = { let mut possible_borrower = {
let mut vis = PossibleBorrowerVisitor::new(cx, mir); let mut vis = PossibleBorrowerVisitor::new(cx, mir);
vis.visit_body(mir_read_only); vis.visit_body(&mir_read_only);
vis.into_map(cx, maybe_storage_live_result) vis.into_map(cx, maybe_storage_live_result)
}; };
@ -335,12 +335,15 @@ fn base_local_and_movability<'tcx>(
mir: &mir::Body<'tcx>, mir: &mir::Body<'tcx>,
place: mir::Place<'tcx>, place: mir::Place<'tcx>,
) -> Option<(mir::Local, CannotMoveOut)> { ) -> Option<(mir::Local, CannotMoveOut)> {
use rustc::mir::PlaceRef; use rustc_middle::mir::PlaceRef;
// 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;
// If projection is a slice index then clone can be removed only if the
// underlying type implements Copy
let mut slice = false;
let PlaceRef { local, mut projection } = place.as_ref(); let PlaceRef { local, mut projection } = place.as_ref();
while let [base @ .., elem] = projection { while let [base @ .., elem] = projection {
@ -348,9 +351,11 @@ fn base_local_and_movability<'tcx>(
deref |= matches!(elem, mir::ProjectionElem::Deref); deref |= matches!(elem, mir::ProjectionElem::Deref);
field |= matches!(elem, mir::ProjectionElem::Field(..)) field |= matches!(elem, mir::ProjectionElem::Field(..))
&& has_drop(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty); && has_drop(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty);
slice |= matches!(elem, mir::ProjectionElem::Index(..))
&& !is_copy(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty);
} }
Some((local, deref || field)) Some((local, deref || field || slice))
} }
struct LocalUseVisitor { struct LocalUseVisitor {
@ -437,7 +442,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeStorageLive {
_block: mir::BasicBlock, _block: mir::BasicBlock,
_func: &mir::Operand<'tcx>, _func: &mir::Operand<'tcx>,
_args: &[mir::Operand<'tcx>], _args: &[mir::Operand<'tcx>],
_return_place: &mir::Place<'tcx>, _return_place: mir::Place<'tcx>,
) { ) {
// Nothing to do when a call returns successfully // Nothing to do when a call returns successfully
} }
@ -556,7 +561,7 @@ impl TypeVisitor<'_> for ContainsRegion {
} }
fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) { fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) {
use rustc::mir::Rvalue::{Aggregate, BinaryOp, Cast, CheckedBinaryOp, Repeat, UnaryOp, Use}; use rustc_middle::mir::Rvalue::{Aggregate, BinaryOp, Cast, CheckedBinaryOp, Repeat, UnaryOp, Use};
let mut visit_op = |op: &mir::Operand<'_>| match op { let mut visit_op = |op: &mir::Operand<'_>| match op {
mir::Operand::Copy(p) | mir::Operand::Move(p) => visit(p.local), mir::Operand::Copy(p) | mir::Operand::Move(p) => visit(p.local),

View File

@ -1,103 +0,0 @@
use crate::utils::{match_def_path, span_lint_and_sugg};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Expr, ExprKind, Node};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! {
/// **What it does:** Checks for usage of standard library
/// `const`s that could be replaced by `const fn`s.
///
/// **Why is this bad?** `const fn`s exist
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let x = std::u32::MIN;
/// let y = std::u32::MAX;
/// ```
///
/// Could be written:
///
/// ```rust
/// let x = u32::min_value();
/// let y = u32::max_value();
/// ```
pub REPLACE_CONSTS,
pedantic,
"Lint usages of standard library `const`s that could be replaced by `const fn`s"
}
declare_lint_pass!(ReplaceConsts => [REPLACE_CONSTS]);
fn in_pattern(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
let map = &cx.tcx.hir();
let parent_id = map.get_parent_node(expr.hir_id);
if let Some(node) = map.find(parent_id) {
if let Node::Pat(_) = node {
return true;
}
}
false
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ReplaceConsts {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
if_chain! {
if let ExprKind::Path(ref qp) = expr.kind;
if let Res::Def(DefKind::Const, def_id) = cx.tables.qpath_res(qp, expr.hir_id);
// Do not lint within patterns as function calls are disallowed in them
if !in_pattern(cx, expr);
then {
for &(ref const_path, repl_snip) in &REPLACEMENTS {
if match_def_path(cx, def_id, const_path) {
span_lint_and_sugg(
cx,
REPLACE_CONSTS,
expr.span,
&format!("using `{}`", const_path.last().expect("empty path")),
"try this",
repl_snip.to_string(),
Applicability::MachineApplicable,
);
return;
}
}
}
}
}
}
const REPLACEMENTS: [([&str; 3], &str); 24] = [
// Min
(["core", "isize", "MIN"], "isize::min_value()"),
(["core", "i8", "MIN"], "i8::min_value()"),
(["core", "i16", "MIN"], "i16::min_value()"),
(["core", "i32", "MIN"], "i32::min_value()"),
(["core", "i64", "MIN"], "i64::min_value()"),
(["core", "i128", "MIN"], "i128::min_value()"),
(["core", "usize", "MIN"], "usize::min_value()"),
(["core", "u8", "MIN"], "u8::min_value()"),
(["core", "u16", "MIN"], "u16::min_value()"),
(["core", "u32", "MIN"], "u32::min_value()"),
(["core", "u64", "MIN"], "u64::min_value()"),
(["core", "u128", "MIN"], "u128::min_value()"),
// Max
(["core", "isize", "MAX"], "isize::max_value()"),
(["core", "i8", "MAX"], "i8::max_value()"),
(["core", "i16", "MAX"], "i16::max_value()"),
(["core", "i32", "MAX"], "i32::max_value()"),
(["core", "i64", "MAX"], "i64::max_value()"),
(["core", "i128", "MAX"], "i128::max_value()"),
(["core", "usize", "MAX"], "usize::max_value()"),
(["core", "u8", "MAX"], "u8::max_value()"),
(["core", "u16", "MAX"], "u16::max_value()"),
(["core", "u32", "MAX"], "u32::max_value()"),
(["core", "u64", "MAX"], "u64::max_value()"),
(["core", "u128", "MAX"], "u128::max_value()"),
];

View File

@ -1,9 +1,9 @@
use if_chain::if_chain; use if_chain::if_chain;
use rustc::lint::in_external_macro;
use rustc_ast::ast; use rustc_ast::ast;
use rustc_ast::visit::FnKind; use rustc_ast::visit::FnKind;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
use rustc_span::BytePos; use rustc_span::BytePos;

View File

@ -1,13 +1,13 @@
use crate::reexport::Name; use crate::reexport::Name;
use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then}; use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then};
use rustc::lint::in_external_macro;
use rustc::ty;
use rustc_hir::intravisit::FnKind; use rustc_hir::intravisit::FnKind;
use rustc_hir::{ use rustc_hir::{
Block, Body, Expr, ExprKind, FnDecl, Guard, HirId, Local, MutTy, Pat, PatKind, Path, QPath, StmtKind, Ty, TyKind, Block, Body, Expr, ExprKind, FnDecl, Guard, HirId, Local, MutTy, Pat, PatKind, Path, QPath, StmtKind, Ty, TyKind,
UnOp, UnOp,
}; };
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;

View File

@ -1,12 +1,12 @@
use crate::utils::sugg::Sugg; use crate::utils::sugg::Sugg;
use crate::utils::{get_enclosing_block, match_qpath, span_lint_and_then, SpanlessEq}; use crate::utils::{get_enclosing_block, match_qpath, span_lint_and_then, SpanlessEq};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::hir::map::Map;
use rustc_ast::ast::LitKind; use rustc_ast::ast::LitKind;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, NestedVisitorMap, Visitor}; use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, NestedVisitorMap, Visitor};
use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, PatKind, QPath, Stmt, StmtKind}; use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, PatKind, QPath, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass, Lint}; use rustc_lint::{LateContext, LateLintPass, Lint};
use rustc_middle::hir::map::Map;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;

View File

@ -1,7 +1,7 @@
use rustc::lint::in_external_macro;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Spanned; use rustc_span::source_map::Spanned;

View File

@ -1,9 +1,9 @@
use crate::utils::{get_trait_def_id, span_lint, trait_ref_of_method}; use crate::utils::{get_trait_def_id, span_lint, trait_ref_of_method};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::hir::map::Map;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! { declare_clippy_lint! {
@ -54,7 +54,7 @@ declare_lint_pass!(SuspiciousImpl => [SUSPICIOUS_ARITHMETIC_IMPL, SUSPICIOUS_OP_
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl {
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<'_>) {
if let hir::ExprKind::Binary(binop, _, _) = expr.kind { if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind {
match binop.node { match binop.node {
hir::BinOpKind::Eq hir::BinOpKind::Eq
| hir::BinOpKind::Lt | hir::BinOpKind::Lt
@ -65,14 +65,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl {
_ => {}, _ => {},
} }
// Check if the binary expression is part of another bi/unary expression // Check if the binary expression is part of another bi/unary expression
// as a child node // or operator assignment as a child node
let mut parent_expr = cx.tcx.hir().get_parent_node(expr.hir_id); let mut parent_expr = cx.tcx.hir().get_parent_node(expr.hir_id);
while parent_expr != hir::CRATE_HIR_ID { while parent_expr != hir::CRATE_HIR_ID {
if let hir::Node::Expr(e) = cx.tcx.hir().get(parent_expr) { if let hir::Node::Expr(e) = cx.tcx.hir().get(parent_expr) {
match e.kind { match e.kind {
hir::ExprKind::Binary(..) hir::ExprKind::Binary(..)
| hir::ExprKind::Unary(hir::UnOp::UnNot, _) | hir::ExprKind::Unary(hir::UnOp::UnNot, _)
| hir::ExprKind::Unary(hir::UnOp::UnNeg, _) => return, | hir::ExprKind::Unary(hir::UnOp::UnNeg, _)
| hir::ExprKind::AssignOp(..) => return,
_ => {}, _ => {},
} }
} }
@ -191,7 +192,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BinaryExprVisitor {
match expr.kind { match expr.kind {
hir::ExprKind::Binary(..) hir::ExprKind::Binary(..)
| hir::ExprKind::Unary(hir::UnOp::UnNot, _) | hir::ExprKind::Unary(hir::UnOp::UnNot, _)
| hir::ExprKind::Unary(hir::UnOp::UnNeg, _) => self.in_binary_expr = true, | hir::ExprKind::Unary(hir::UnOp::UnNeg, _)
| hir::ExprKind::AssignOp(..) => self.in_binary_expr = true,
_ => {}, _ => {},
} }

View File

@ -4,12 +4,11 @@ use crate::utils::{
span_lint_and_then, walk_ptrs_ty, SpanlessEq, span_lint_and_then, walk_ptrs_ty, SpanlessEq,
}; };
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, StmtKind}; use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, StmtKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::Symbol;
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for manual swapping. /// **What it does:** Checks for manual swapping.
@ -199,7 +198,7 @@ fn check_for_slice<'a>(cx: &LateContext<'_, '_>, lhs1: &'a Expr<'_>, lhs2: &'a E
if matches!(ty.kind, ty::Slice(_)) if matches!(ty.kind, ty::Slice(_))
|| matches!(ty.kind, ty::Array(_, _)) || matches!(ty.kind, ty::Array(_, _))
|| is_type_diagnostic_item(cx, ty, Symbol::intern("vec_type")) || is_type_diagnostic_item(cx, ty, sym!(vec_type))
|| match_type(cx, ty, &paths::VEC_DEQUE) || match_type(cx, ty, &paths::VEC_DEQUE)
{ {
return Slice::Swappable(lhs1, idx1, idx2); return Slice::Swappable(lhs1, idx1, idx2);

View File

@ -1,9 +1,9 @@
use crate::utils::{match_def_path, snippet_with_applicability, span_lint_and_sugg}; use crate::utils::{match_def_path, snippet_with_applicability, span_lint_and_sugg};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! { declare_clippy_lint! {

View File

@ -1,5 +1,6 @@
use crate::utils::{in_macro, snippet, span_lint_and_help, SpanlessHash}; use crate::utils::{in_macro, snippet, snippet_with_applicability, span_lint_and_help, SpanlessHash};
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_errors::Applicability;
use rustc_hir::{GenericBound, Generics, WherePredicate}; use rustc_hir::{GenericBound, Generics, WherePredicate};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
@ -41,6 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TraitBounds {
hasher.finish() hasher.finish()
}; };
let mut map = FxHashMap::default(); let mut map = FxHashMap::default();
let mut applicability = Applicability::MaybeIncorrect;
for bound in gen.where_clause.predicates { for bound in gen.where_clause.predicates {
if let WherePredicate::BoundPredicate(ref p) = bound { if let WherePredicate::BoundPredicate(ref p) = bound {
let h = hash(&p.bounded_ty); let h = hash(&p.bounded_ty);
@ -52,13 +54,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TraitBounds {
for b in v.iter() { for b in v.iter() {
if let GenericBound::Trait(ref poly_trait_ref, _) = b { if let GenericBound::Trait(ref poly_trait_ref, _) = b {
let path = &poly_trait_ref.trait_ref.path; let path = &poly_trait_ref.trait_ref.path;
hint_string.push_str(&format!(" {} +", path)); hint_string.push_str(&format!(
" {} +",
snippet_with_applicability(cx, path.span, "..", &mut applicability)
));
} }
} }
for b in p.bounds.iter() { for b in p.bounds.iter() {
if let GenericBound::Trait(ref poly_trait_ref, _) = b { if let GenericBound::Trait(ref poly_trait_ref, _) = b {
let path = &poly_trait_ref.trait_ref.path; let path = &poly_trait_ref.trait_ref.path;
hint_string.push_str(&format!(" {} +", path)); hint_string.push_str(&format!(
" {} +",
snippet_with_applicability(cx, path.span, "..", &mut applicability)
));
} }
} }
hint_string.truncate(hint_string.len() - 2); hint_string.truncate(hint_string.len() - 2);

View File

@ -2,11 +2,11 @@ use crate::utils::{
is_normalizable, last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then, sugg, is_normalizable, last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then, sugg,
}; };
use if_chain::if_chain; use if_chain::if_chain;
use rustc::ty::{self, Ty};
use rustc_ast::ast; use rustc_ast::ast;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, GenericArg, Mutability, QPath, TyKind, UnOp}; use rustc_hir::{Expr, ExprKind, GenericArg, Mutability, QPath, TyKind, UnOp};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use std::borrow::Cow; use std::borrow::Cow;

View File

@ -1,10 +1,10 @@
use crate::consts::{constant_context, Constant}; use crate::consts::{constant_context, Constant};
use crate::utils::{match_qpath, paths, span_lint}; use crate::utils::{match_qpath, paths, span_lint};
use if_chain::if_chain; use if_chain::if_chain;
use rustc::lint::in_external_macro;
use rustc_ast::ast::LitKind; use rustc_ast::ast::LitKind;
use rustc_hir::{Expr, ExprKind}; use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! { declare_clippy_lint! {

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