install:
- |
if [ -z ${INTEGRATION} ]; then
+ rustup component add rustfmt-preview || cargo install --git https://github.com/rust-lang/rustfmt/ --force
if [ "$TRAVIS_OS_NAME" == "linux" ]; then
. $HOME/.nvm/nvm.sh
nvm install stable
* [Author lint](#author-lint)
* [Documentation](#documentation)
* [Running test suite](#running-test-suite)
+ * [Running rustfmt](#running-rustfmt)
* [Testing manually](#testing-manually)
+ * [Linting Clippy with your local changes](#linting-clippy-with-your-local-changes)
* [How Clippy works](#how-clippy-works)
* [Fixing nightly build failures](#fixing-build-failures-caused-by-rust)
* [Contributions](#contributions)
`cargo test`) and check whether the output looks as you expect with `git diff`. Commit all
`*.stderr` files, too.
+### Running rustfmt
+
+[Rustfmt](https://github.com/rust-lang/rustfmt) is a tool for formatting Rust code according
+to style guidelines. The code has to be formatted by `rustfmt` before a PR will be merged.
+
+It can be installed via `rustup`:
+```bash
+rustup component add rustfmt-preview
+```
+
+Use `cargo fmt --all` to format the whole codebase.
+
### Testing manually
Manually testing against an example file is useful if you have added some
local modifications, run `env CLIPPY_TESTS=true cargo run --bin clippy-driver -- -L ./target/debug input.rs`
from the working copy root.
-### Linting Clippy with your changes locally
+### Linting Clippy with your local changes
Clippy CI only passes if all lints defined in the version of the Clippy being
tested pass (that is, don’t report any suggestions). You can avoid prolonging
be reviewed by a core contributor (someone with permission to land patches) and either landed in the
main tree or given feedback for changes that would be required.
-All code in this repository is under the [Mozilla Public License, 2.0](https://www.mozilla.org/MPL/2.0/)
+All code in this repository is under the [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0>)
+or the [MIT](http://opensource.org/licenses/MIT) license.
<!-- adapted from https://github.com/servo/servo/blob/master/CONTRIBUTING.md -->
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
fn main() {
// Forward the profile to the main compilation
println!("cargo:rustc-env=PROFILE={}", std::env::var("PROFILE").unwrap());
# Perform various checks for lint registration
./util/dev update_lints --check
+cargo +nightly fmt --all -- --check
CLIPPY="`pwd`/target/debug/cargo-clippy clippy"
# run clippy on its own codebase...
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
#![allow(clippy::default_hash_types)]
use itertools::Itertools;
use lazy_static::lazy_static;
use regex::Regex;
-use walkdir::WalkDir;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs;
use std::io::prelude::*;
+use walkdir::WalkDir;
lazy_static! {
- static ref DEC_CLIPPY_LINT_RE: Regex = Regex::new(r#"(?x)
+ static ref DEC_CLIPPY_LINT_RE: Regex = Regex::new(
+ r#"(?x)
declare_clippy_lint!\s*[\{(]\s*
pub\s+(?P<name>[A-Z_][A-Z_0-9]*)\s*,\s*
(?P<cat>[a-z_]+)\s*,\s*
"(?P<desc>(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})]
- "#).unwrap();
- static ref DEC_DEPRECATED_LINT_RE: Regex = Regex::new(r#"(?x)
+ "#
+ )
+ .unwrap();
+ static ref DEC_DEPRECATED_LINT_RE: Regex = Regex::new(
+ r#"(?x)
declare_deprecated_lint!\s*[{(]\s*
pub\s+(?P<name>[A-Z_][A-Z_0-9]*)\s*,\s*
"(?P<desc>(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})]
- "#).unwrap();
+ "#
+ )
+ .unwrap();
static ref NL_ESCAPE_RE: Regex = Regex::new(r#"\\\n\s*"#).unwrap();
pub static ref DOCS_LINK: String = "https://rust-lang.github.io/rust-clippy/master/index.html".to_string();
}
}
/// Returns all non-deprecated lints and non-internal lints
- pub fn usable_lints(lints: impl Iterator<Item=Self>) -> impl Iterator<Item=Self> {
+ pub fn usable_lints(lints: impl Iterator<Item = Self>) -> impl Iterator<Item = Self> {
lints.filter(|l| l.deprecation.is_none() && !l.is_internal())
}
/// Returns the lints in a HashMap, grouped by the different lint groups
pub fn by_lint_group(lints: &[Self]) -> HashMap<String, Vec<Self>> {
- lints.iter().map(|lint| (lint.group.to_string(), lint.clone())).into_group_map()
+ lints
+ .iter()
+ .map(|lint| (lint.group.to_string(), lint.clone()))
+ .into_group_map()
}
pub fn is_internal(&self) -> bool {
/// Generates the Vec items for `register_lint_group` calls in `clippy_lints/src/lib.rs`.
pub fn gen_lint_group_list(lints: Vec<Lint>) -> Vec<String> {
- lints.into_iter()
+ lints
+ .into_iter()
.filter_map(|l| {
if l.is_internal() || l.deprecation.is_some() {
None
/// Generates the `pub mod module_name` list in `clippy_lints/src/lib.rs`.
pub fn gen_modules_list(lints: Vec<Lint>) -> Vec<String> {
- lints.into_iter()
+ lints
+ .into_iter()
.filter_map(|l| {
- if l.is_internal() || l.deprecation.is_some() { None } else { Some(l.module) }
+ if l.is_internal() || l.deprecation.is_some() {
+ None
+ } else {
+ Some(l.module)
+ }
})
.unique()
- .map(|module| {
- format!("pub mod {};", module)
- })
+ .map(|module| format!("pub mod {};", module))
.sorted()
}
} else {
Some(format!("[`{}`]: {}#{}", l.name, DOCS_LINK.clone(), l.name))
}
- }).collect()
+ })
+ .collect()
}
/// Generates the `register_removed` code in `./clippy_lints/src/lib.rs`.
pub fn gen_deprecated(lints: &[Lint]) -> Vec<String> {
- itertools::flatten(
- lints
- .iter()
- .filter_map(|l| {
- l.clone().deprecation.and_then(|depr_text| {
- Some(
- vec![
- " store.register_removed(".to_string(),
- format!(" \"{}\",", l.name),
- format!(" \"{}\",", depr_text),
- " );".to_string()
- ]
- )
- })
- })
- ).collect()
+ itertools::flatten(lints.iter().filter_map(|l| {
+ l.clone().deprecation.and_then(|depr_text| {
+ Some(vec![
+ " store.register_removed(".to_string(),
+ format!(" \"{}\",", l.name),
+ format!(" \"{}\",", depr_text),
+ " );".to_string(),
+ ])
+ })
+ }))
+ .collect()
}
/// Gathers all files in `src/clippy_lints` and gathers all lints inside
-pub fn gather_all() -> impl Iterator<Item=Lint> {
+pub fn gather_all() -> impl Iterator<Item = Lint> {
lint_files().flat_map(|f| gather_from_file(&f))
}
-fn gather_from_file(dir_entry: &walkdir::DirEntry) -> impl Iterator<Item=Lint> {
+fn gather_from_file(dir_entry: &walkdir::DirEntry) -> impl Iterator<Item = Lint> {
let mut file = fs::File::open(dir_entry.path()).unwrap();
let mut content = String::new();
file.read_to_string(&mut content).unwrap();
// If the lints are stored in mod.rs, we get the module name from
// the containing directory:
if filename == "mod" {
- filename = dir_entry.path().parent().unwrap().file_stem().unwrap().to_str().unwrap()
+ filename = dir_entry
+ .path()
+ .parent()
+ .unwrap()
+ .file_stem()
+ .unwrap()
+ .to_str()
+ .unwrap()
}
parse_contents(&content, filename)
}
-fn parse_contents(content: &str, filename: &str) -> impl Iterator<Item=Lint> {
+fn parse_contents(content: &str, filename: &str) -> impl Iterator<Item = Lint> {
let lints = DEC_CLIPPY_LINT_RE
.captures_iter(content)
.map(|m| Lint::new(&m["name"], &m["cat"], &m["desc"], None, filename));
let deprecated = DEC_DEPRECATED_LINT_RE
.captures_iter(content)
- .map(|m| Lint::new( &m["name"], "Deprecated", &m["desc"], Some(&m["desc"]), filename));
+ .map(|m| Lint::new(&m["name"], "Deprecated", &m["desc"], Some(&m["desc"]), filename));
// Removing the `.collect::<Vec<Lint>>().into_iter()` causes some lifetime issues due to the map
lints.chain(deprecated).collect::<Vec<Lint>>().into_iter()
}
/// Collects all .rs files in the `clippy_lints/src` directory
-fn lint_files() -> impl Iterator<Item=walkdir::DirEntry> {
+fn lint_files() -> impl Iterator<Item = walkdir::DirEntry> {
// We use `WalkDir` instead of `fs::read_dir` here in order to recurse into subdirectories.
// Otherwise we would not collect all the lints, for example in `clippy_lints/src/methods/`.
WalkDir::new("../clippy_lints/src")
///
/// See `replace_region_in_text` for documentation of the other options.
#[allow(clippy::expect_fun_call)]
-pub fn replace_region_in_file<F>(path: &str, start: &str, end: &str, replace_start: bool, write_back: bool, replacements: F) -> FileChange where F: Fn() -> Vec<String> {
+pub fn replace_region_in_file<F>(
+ path: &str,
+ start: &str,
+ end: &str,
+ replace_start: bool,
+ write_back: bool,
+ replacements: F,
+) -> FileChange
+where
+ F: Fn() -> Vec<String>,
+{
let mut f = fs::File::open(path).expect(&format!("File not found: {}", path));
let mut contents = String::new();
- f.read_to_string(&mut contents).expect("Something went wrong reading the file");
+ f.read_to_string(&mut contents)
+ .expect("Something went wrong reading the file");
let file_change = replace_region_in_text(&contents, start, end, replace_start, replacements);
if write_back {
let mut f = fs::File::create(path).expect(&format!("File not found: {}", path));
- f.write_all(file_change.new_lines.as_bytes()).expect("Unable to write file");
+ f.write_all(file_change.new_lines.as_bytes())
+ .expect("Unable to write file");
// Ensure we write the changes with a trailing newline so that
// the file has the proper line endings.
f.write_all(b"\n").expect("Unable to write file");
/// * `text` is the input text on which you want to perform the replacement
/// * `start` is a `&str` that describes the delimiter line before the region you want to replace.
/// As the `&str` will be converted to a `Regex`, this can contain regex syntax, too.
-/// * `end` is a `&str` that describes the delimiter line until where the replacement should
-/// happen. As the `&str` will be converted to a `Regex`, this can contain regex syntax, too.
-/// * If `replace_start` is true, the `start` delimiter line is replaced as well.
-/// The `end` delimiter line is never replaced.
+/// * `end` is a `&str` that describes the delimiter line until where the replacement should happen.
+/// As the `&str` will be converted to a `Regex`, this can contain regex syntax, too.
+/// * If `replace_start` is true, the `start` delimiter line is replaced as well. The `end`
+/// delimiter line is never replaced.
/// * `replacements` is a closure that has to return a `Vec<String>` which contains the new text.
///
/// If you want to perform the replacement on files instead of already parsed text,
///
/// ```
/// let the_text = "replace_start\nsome text\nthat will be replaced\nreplace_end";
-/// let result = clippy_dev::replace_region_in_text(
-/// the_text,
-/// r#"replace_start"#,
-/// r#"replace_end"#,
-/// false,
-/// || {
-/// vec!["a different".to_string(), "text".to_string()]
-/// }
-/// ).new_lines;
+/// let result = clippy_dev::replace_region_in_text(the_text, r#"replace_start"#, r#"replace_end"#, false, || {
+/// vec!["a different".to_string(), "text".to_string()]
+/// })
+/// .new_lines;
/// assert_eq!("replace_start\na different\ntext\nreplace_end", result);
/// ```
-pub fn replace_region_in_text<F>(text: &str, start: &str, end: &str, replace_start: bool, replacements: F) -> FileChange where F: Fn() -> Vec<String> {
+pub fn replace_region_in_text<F>(text: &str, start: &str, end: &str, replace_start: bool, replacements: F) -> FileChange
+where
+ F: Fn() -> Vec<String>,
+{
let lines = text.lines();
let mut in_old_region = false;
let mut found = false;
FileChange {
changed: lines.ne(new_lines.clone()),
- new_lines: new_lines.join("\n")
+ new_lines: new_lines.join("\n"),
}
}
"`assert!()` will be more flexible with RFC 2011"
}
"#,
- "module_name").collect();
+ "module_name",
+ )
+ .collect();
let expected = vec![
Lint::new("ptr_arg", "style", "really long text", None, "module_name"),
"Deprecated",
"`assert!()` will be more flexible with RFC 2011",
Some("`assert!()` will be more flexible with RFC 2011"),
- "module_name"
+ "module_name",
),
];
assert_eq!(expected, result);
let text = "\nabc\n123\n789\ndef\nghi";
let expected = FileChange {
changed: true,
- new_lines: "\nabc\nhello world\ndef\nghi".to_string()
+ new_lines: "\nabc\nhello world\ndef\nghi".to_string(),
};
let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, false, || {
vec!["hello world".to_string()]
let text = "\nabc\n123\n789\ndef\nghi";
let expected = FileChange {
changed: true,
- new_lines: "\nhello world\ndef\nghi".to_string()
+ new_lines: "\nhello world\ndef\nghi".to_string(),
};
let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, true, || {
vec!["hello world".to_string()]
let text = "123\n456\n789";
let expected = FileChange {
changed: false,
- new_lines: "123\n456\n789".to_string()
+ new_lines: "123\n456\n789".to_string(),
};
- let result = replace_region_in_text(text, r#"^\s*123$"#, r#"^\s*456"#, false, || {
- vec![]
- });
+ let result = replace_region_in_text(text, r#"^\s*123$"#, r#"^\s*456"#, false, || vec![]);
assert_eq!(expected, result);
}
Lint::new("should_assert_eq", "Deprecated", "abc", Some("Reason"), "module_name"),
Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name"),
Lint::new("should_assert_eq2", "internal", "abc", None, "module_name"),
- Lint::new("should_assert_eq2", "internal_style", "abc", None, "module_name")
- ];
- let expected = vec![
- Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name")
+ Lint::new("should_assert_eq2", "internal_style", "abc", None, "module_name"),
];
+ let expected = vec![Lint::new(
+ "should_assert_eq2",
+ "Not Deprecated",
+ "abc",
+ None,
+ "module_name",
+ )];
assert_eq!(expected, Lint::usable_lints(lints.into_iter()).collect::<Vec<Lint>>());
}
Lint::new("incorrect_match", "group1", "abc", None, "module_name"),
];
let mut expected: HashMap<String, Vec<Lint>> = HashMap::new();
- expected.insert("group1".to_string(), vec![
- Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
- Lint::new("incorrect_match", "group1", "abc", None, "module_name"),
- ]);
- expected.insert("group2".to_string(), vec![
- Lint::new("should_assert_eq2", "group2", "abc", None, "module_name")
- ]);
+ expected.insert(
+ "group1".to_string(),
+ vec![
+ Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
+ Lint::new("incorrect_match", "group1", "abc", None, "module_name"),
+ ],
+ );
+ expected.insert(
+ "group2".to_string(),
+ vec![Lint::new("should_assert_eq2", "group2", "abc", None, "module_name")],
+ );
assert_eq!(expected, Lint::by_lint_group(&lints));
}
];
let expected = vec![
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));
}
#[test]
fn test_gen_deprecated() {
let lints = vec![
- Lint::new("should_assert_eq", "group1", "abc", Some("has been superseeded by should_assert_eq2"), "module_name"),
- Lint::new("another_deprecated", "group2", "abc", Some("will be removed"), "module_name"),
- Lint::new("should_assert_eq2", "group2", "abc", None, "module_name")
+ Lint::new(
+ "should_assert_eq",
+ "group1",
+ "abc",
+ Some("has been superseeded by should_assert_eq2"),
+ "module_name",
+ ),
+ Lint::new(
+ "another_deprecated",
+ "group2",
+ "abc",
+ Some("will be removed"),
+ "module_name",
+ ),
+ Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"),
];
let expected: Vec<String> = vec![
" store.register_removed(",
" store.register_removed(",
" \"another_deprecated\",",
" \"will be removed\",",
- " );"
- ].into_iter().map(String::from).collect();
+ " );",
+ ]
+ .into_iter()
+ .map(String::from)
+ .collect();
assert_eq!(expected, gen_deprecated(&lints));
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
extern crate clap;
extern crate clippy_dev;
extern crate regex;
#[derive(PartialEq)]
enum UpdateMode {
Check,
- Change
+ Change,
}
fn main() {
let matches = App::new("Clippy developer tooling")
.subcommand(
SubCommand::with_name("update_lints")
- .about("Makes sure that:\n \
- * the lint count in README.md is correct\n \
- * the changelog contains markdown link references at the bottom\n \
- * all lint groups include the correct lints\n \
- * lint modules in `clippy_lints/*` are visible in `src/lib.rs` via `pub mod`\n \
- * all lints are registered in the lint store")
- .arg(
- Arg::with_name("print-only")
- .long("print-only")
- .help("Print a table of lints to STDOUT. This does not include deprecated and internal lints. (Does not modify any files)")
+ .about(
+ "Makes sure that:\n \
+ * the lint count in README.md is correct\n \
+ * the changelog contains markdown link references at the bottom\n \
+ * all lint groups include the correct lints\n \
+ * lint modules in `clippy_lints/*` are visible in `src/lib.rs` via `pub mod`\n \
+ * all lints are registered in the lint store",
)
+ .arg(Arg::with_name("print-only").long("print-only").help(
+ "Print a table of lints to STDOUT. \
+ This does not include deprecated and internal lints. \
+ (Does not modify any files)",
+ ))
.arg(
Arg::with_name("check")
.long("check")
.help("Checks that util/dev update_lints has been run. Used on CI."),
- )
- )
- .get_matches();
+ ),
+ )
+ .get_matches();
if let Some(matches) = matches.subcommand_matches("update_lints") {
if matches.is_present("print-only") {
let grouped_by_lint_group = Lint::by_lint_group(&usable_lints);
for (lint_group, mut lints) in grouped_by_lint_group {
- if lint_group == "Deprecated" { continue; }
+ 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.clone(), lint.name, lint.desc);
+ println!(
+ "* [{}]({}#{}) ({})",
+ lint.name,
+ clippy_dev::DOCS_LINK.clone(),
+ lint.name,
+ lint.desc
+ );
}
}
"<!-- end autogenerated links to lint list -->",
false,
update_mode == &UpdateMode::Change,
- || { gen_changelog_lint_list(lint_list.clone()) }
- ).changed;
+ || gen_changelog_lint_list(lint_list.clone()),
+ )
+ .changed;
file_change |= replace_region_in_file(
"../clippy_lints/src/lib.rs",
"end deprecated lints",
false,
update_mode == &UpdateMode::Change,
- || { gen_deprecated(&lint_list) }
- ).changed;
+ || gen_deprecated(&lint_list),
+ )
+ .changed;
file_change |= replace_region_in_file(
"../clippy_lints/src/lib.rs",
"end lints modules",
false,
update_mode == &UpdateMode::Change,
- || { gen_modules_list(lint_list.clone()) }
- ).changed;
+ || gen_modules_list(lint_list.clone()),
+ )
+ .changed;
// Generate lists of lints in the clippy::all lint group
file_change |= replace_region_in_file(
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();
+ 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;
+ },
+ )
+ .changed;
// Generate the list of lints for all other lint groups
for (lint_group, lints) in Lint::by_lint_group(&usable_lints) {
r#"\]\);"#,
false,
update_mode == &UpdateMode::Change,
- || { gen_lint_group_list(lints.clone()) }
- ).changed;
+ || gen_lint_group_list(lints.clone()),
+ )
+ .changed;
}
if update_mode == &UpdateMode::Check && file_change {
- println!("Not all lints defined properly. Please run `util/dev update_lints` to make sure all lints are defined properly.");
- std::process::exit(1);
+ println!(
+ "Not all lints defined properly. \
+ Please run `util/dev update_lints` to make sure all lints are defined properly."
+ );
+ std::process::exit(1);
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use crate::utils::span_lint;
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use std::f64::consts as f64;
use crate::syntax::ast::{FloatTy, Lit, LitKind};
use crate::syntax::symbol;
+use crate::utils::span_lint;
+use std::f64::consts as f64;
/// **What it does:** Checks for floating point literals that approximate
/// constants which are defined in
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use crate::utils::span_lint;
use crate::rustc::hir;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::source_map::Span;
+use crate::utils::span_lint;
/// **What it does:** Checks for plain integer arithmetic.
///
#[derive(Copy, Clone, Default)]
pub struct Arithmetic {
expr_span: Option<Span>,
- /// This field is used to check whether expressions are constants, such as in enum discriminants and consts
+ /// This field is used to check whether expressions are constants, such as in enum discriminants
+ /// and consts
const_span: Option<Span>,
}
let body_owner = cx.tcx.hir.body_owner(body.id());
match cx.tcx.hir.body_owner_kind(body_owner) {
- hir::BodyOwnerKind::Static(_)
- | hir::BodyOwnerKind::Const => {
+ hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const => {
let body_span = cx.tcx.hir.span(body_owner);
if let Some(span) = self.const_span {
}
}
self.const_span = Some(body_span);
- }
+ },
hir::BodyOwnerKind::Fn => (),
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use crate::utils::{get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, SpanlessEq};
-use crate::utils::{higher, sugg};
use crate::rustc::hir;
use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
-use crate::syntax::ast;
use crate::rustc_errors::Applicability;
+use crate::syntax::ast;
+use crate::utils::{get_trait_def_id, implements_trait, snippet_opt, span_lint_and_then, SpanlessEq};
+use crate::utils::{higher, sugg};
+use if_chain::if_chain;
/// **What it does:** Checks for `a = a op b` or `a = b commutative_op a`
/// patterns.
// a = b commutative_op a
// Limited to primitive type as these ops are know to be commutative
if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r)
- && cx.tables.expr_ty(assignee).is_primitive_ty() {
+ && cx.tables.expr_ty(assignee).is_primitive_ty()
+ {
match op.node {
hir::BinOpKind::Add
| hir::BinOpKind::Mul
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! checks for attributes
use crate::reexport::*;
-use crate::utils::{
- in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_sugg,
- span_lint_and_then, without_block_comments,
-};
-use if_chain::if_chain;
use crate::rustc::hir::*;
use crate::rustc::lint::{
CheckLintNameResult, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass,
};
use crate::rustc::ty::{self, TyCtxt};
use crate::rustc::{declare_tool_lint, lint_array};
-use semver::Version;
-use crate::syntax::ast::{
- AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind,
-};
-use crate::syntax::source_map::Span;
use crate::rustc_errors::Applicability;
+use crate::syntax::ast::{AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
+use crate::syntax::source_map::Span;
+use crate::utils::{
+ in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_sugg,
+ span_lint_and_then, without_block_comments,
+};
+use if_chain::if_chain;
+use semver::Version;
/// **What it does:** Checks for items annotated with `#[inline(always)]`,
/// unless the annotated function is empty or simply panics.
match &*attr.name().as_str() {
"allow" | "warn" | "deny" | "forbid" => {
check_clippy_lint_names(cx, items);
- }
- _ => {}
+ },
+ _ => {},
}
if items.is_empty() || attr.name() != "deprecated" {
return;
// and `unused_imports` for `extern crate` items with `macro_use`
for lint in lint_list {
match item.node {
- ItemKind::Use(..) => if is_word(lint, "unused_imports")
- || is_word(lint, "deprecated") {
- return
+ ItemKind::Use(..) => {
+ if is_word(lint, "unused_imports") || is_word(lint, "deprecated") {
+ return;
+ }
},
ItemKind::ExternCrate(..) => {
- if is_word(lint, "unused_imports")
- && skip_unused_imports {
- return
+ if is_word(lint, "unused_imports") && skip_unused_imports {
+ return;
}
if is_word(lint, "unused_extern_crates") {
- return
+ return;
}
- }
+ },
_ => {},
}
}
ExprKind::Block(ref block, _) => is_relevant_block(tcx, tables, block),
ExprKind::Ret(Some(ref e)) => is_relevant_expr(tcx, tables, e),
ExprKind::Ret(None) | ExprKind::Break(_, None) => false,
- ExprKind::Call(ref path_expr, _) => if let ExprKind::Path(ref qpath) = path_expr.node {
- if let Some(fun_id) = opt_def_id(tables.qpath_def(qpath, path_expr.hir_id)) {
- !match_def_path(tcx, fun_id, &paths::BEGIN_PANIC)
+ ExprKind::Call(ref path_expr, _) => {
+ if let ExprKind::Path(ref qpath) = path_expr.node {
+ if let Some(fun_id) = opt_def_id(tables.qpath_def(qpath, path_expr.hir_id)) {
+ !match_def_path(tcx, fun_id, &paths::BEGIN_PANIC)
+ } else {
+ true
+ }
} else {
true
}
- } else {
- true
},
_ => true,
}
cx,
EMPTY_LINE_AFTER_OUTER_ATTR,
begin_of_attr_to_item,
- "Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute?"
+ "Found an empty line after an outer attribute. \
+ Perhaps you forgot to add a '!' to make it an inner attribute?",
);
}
}
impl LintPass for CfgAttrPass {
fn get_lints(&self) -> LintArray {
- lint_array!(
- DEPRECATED_CFG_ATTR,
- )
+ lint_array!(DEPRECATED_CFG_ATTR,)
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::consts::{constant, Constant};
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
+use crate::rustc_errors::Applicability;
use crate::syntax::ast::LitKind;
use crate::syntax::source_map::Span;
-use crate::utils::{span_lint, span_lint_and_then};
use crate::utils::sugg::Sugg;
-use crate::consts::{constant, Constant};
-use crate::rustc_errors::Applicability;
+use crate::utils::{span_lint, span_lint_and_then};
+use if_chain::if_chain;
/// **What it does:** Checks for incompatible bit masks in comparisons.
///
}
}
-
fn check_compare(cx: &LateContext<'_, '_>, bit_op: &Expr, cmp_op: BinOpKind, cmp_value: u128, span: Span) {
if let ExprKind::Binary(ref op, ref left, ref right) = bit_op.node {
if op.node != BinOpKind::BitAnd && op.node != BinOpKind::BitOr {
}
}
-fn check_bit_mask(cx: &LateContext<'_, '_>, bit_op: BinOpKind, cmp_op: BinOpKind, mask_value: u128, cmp_value: u128, span: Span) {
+fn check_bit_mask(
+ cx: &LateContext<'_, '_>,
+ bit_op: BinOpKind,
+ cmp_op: BinOpKind,
+ mask_value: u128,
+ cmp_value: u128,
+ span: Span,
+) {
match cmp_op {
BinOpKind::Eq | BinOpKind::Ne => match bit_op {
- BinOpKind::BitAnd => if mask_value & cmp_value != cmp_value {
- if cmp_value != 0 {
+ BinOpKind::BitAnd => {
+ if mask_value & cmp_value != cmp_value {
+ if cmp_value != 0 {
+ span_lint(
+ cx,
+ BAD_BIT_MASK,
+ span,
+ &format!(
+ "incompatible bit mask: `_ & {}` can never be equal to `{}`",
+ mask_value, cmp_value
+ ),
+ );
+ }
+ } else if mask_value == 0 {
+ span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero");
+ }
+ },
+ BinOpKind::BitOr => {
+ if mask_value | cmp_value != cmp_value {
span_lint(
cx,
BAD_BIT_MASK,
span,
&format!(
- "incompatible bit mask: `_ & {}` can never be equal to `{}`",
- mask_value,
- cmp_value
+ "incompatible bit mask: `_ | {}` can never be equal to `{}`",
+ mask_value, cmp_value
),
);
}
- } else if mask_value == 0 {
- span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero");
- },
- BinOpKind::BitOr => if mask_value | cmp_value != cmp_value {
- span_lint(
- cx,
- BAD_BIT_MASK,
- span,
- &format!(
- "incompatible bit mask: `_ | {}` can never be equal to `{}`",
- mask_value,
- cmp_value
- ),
- );
},
_ => (),
},
BinOpKind::Lt | BinOpKind::Ge => match bit_op {
- BinOpKind::BitAnd => if mask_value < cmp_value {
- span_lint(
- cx,
- BAD_BIT_MASK,
- span,
- &format!(
- "incompatible bit mask: `_ & {}` will always be lower than `{}`",
- mask_value,
- cmp_value
- ),
- );
- } else if mask_value == 0 {
- span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero");
+ BinOpKind::BitAnd => {
+ if mask_value < cmp_value {
+ span_lint(
+ cx,
+ BAD_BIT_MASK,
+ span,
+ &format!(
+ "incompatible bit mask: `_ & {}` will always be lower than `{}`",
+ mask_value, cmp_value
+ ),
+ );
+ } else if mask_value == 0 {
+ span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero");
+ }
},
- BinOpKind::BitOr => if mask_value >= cmp_value {
- span_lint(
- cx,
- BAD_BIT_MASK,
- span,
- &format!(
- "incompatible bit mask: `_ | {}` will never be lower than `{}`",
- mask_value,
- cmp_value
- ),
- );
- } else {
- check_ineffective_lt(cx, span, mask_value, cmp_value, "|");
+ BinOpKind::BitOr => {
+ if mask_value >= cmp_value {
+ span_lint(
+ cx,
+ BAD_BIT_MASK,
+ span,
+ &format!(
+ "incompatible bit mask: `_ | {}` will never be lower than `{}`",
+ mask_value, cmp_value
+ ),
+ );
+ } else {
+ check_ineffective_lt(cx, span, mask_value, cmp_value, "|");
+ }
},
BinOpKind::BitXor => check_ineffective_lt(cx, span, mask_value, cmp_value, "^"),
_ => (),
},
BinOpKind::Le | BinOpKind::Gt => match bit_op {
- BinOpKind::BitAnd => if mask_value <= cmp_value {
- span_lint(
- cx,
- BAD_BIT_MASK,
- span,
- &format!(
- "incompatible bit mask: `_ & {}` will never be higher than `{}`",
- mask_value,
- cmp_value
- ),
- );
- } else if mask_value == 0 {
- span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero");
+ BinOpKind::BitAnd => {
+ if mask_value <= cmp_value {
+ span_lint(
+ cx,
+ BAD_BIT_MASK,
+ span,
+ &format!(
+ "incompatible bit mask: `_ & {}` will never be higher than `{}`",
+ mask_value, cmp_value
+ ),
+ );
+ } else if mask_value == 0 {
+ span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero");
+ }
},
- BinOpKind::BitOr => if mask_value > cmp_value {
- span_lint(
- cx,
- BAD_BIT_MASK,
- span,
- &format!(
- "incompatible bit mask: `_ | {}` will always be higher than `{}`",
- mask_value,
- cmp_value
- ),
- );
- } else {
- check_ineffective_gt(cx, span, mask_value, cmp_value, "|");
+ BinOpKind::BitOr => {
+ if mask_value > cmp_value {
+ span_lint(
+ cx,
+ BAD_BIT_MASK,
+ span,
+ &format!(
+ "incompatible bit mask: `_ | {}` will always be higher than `{}`",
+ mask_value, cmp_value
+ ),
+ );
+ } else {
+ check_ineffective_gt(cx, span, mask_value, cmp_value, "|");
+ }
},
BinOpKind::BitXor => check_ineffective_gt(cx, span, mask_value, cmp_value, "^"),
_ => (),
span,
&format!(
"ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly",
- op,
- m,
- c
+ op, m, c
),
);
}
span,
&format!(
"ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly",
- op,
- m,
- c
+ op, m, c
),
);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use crate::rustc::hir::*;
use crate::utils::span_lint;
/// **What it does:** Checks for usage of blacklisted names for variables, such
impl BlackListedName {
pub fn new(blacklist: Vec<String>) -> Self {
- Self {
- blacklist,
- }
+ Self { blacklist }
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use matches::matches;
+use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use crate::rustc::hir::*;
-use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use crate::utils::*;
+use matches::matches;
/// **What it does:** Checks for `if` conditions that use blocks to contain an
/// expression.
);
}
} else {
- let span = block
- .expr
- .as_ref()
- .map_or_else(|| block.stmts[0].span, |e| e.span);
+ let span = block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span);
if in_macro(span) || differing_macro_contexts(expr.span, span) {
return;
}
}
}
} else {
- let mut visitor = ExVisitor {
- found_block: None,
- cx,
- };
+ let mut visitor = ExVisitor { found_block: None, cx };
walk_expr(&mut visitor, check);
if let Some(block) = visitor.found_block {
span_lint(cx, BLOCK_IN_IF_CONDITION_STMT, block.span, COMPLEX_BLOCK_MESSAGE);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::intravisit::*;
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use crate::rustc::hir::*;
-use crate::rustc::hir::intravisit::*;
-use crate::syntax::ast::{LitKind, NodeId, DUMMY_NODE_ID};
-use crate::syntax::source_map::{dummy_spanned, Span, DUMMY_SP};
use crate::rustc_data_structures::thin_vec::ThinVec;
-use crate::utils::{in_macro, paths, match_type, snippet_opt, span_lint_and_then, SpanlessEq, get_trait_def_id, implements_trait};
use crate::rustc_errors::Applicability;
+use crate::syntax::ast::{LitKind, NodeId, DUMMY_NODE_ID};
+use crate::syntax::source_map::{dummy_spanned, Span, DUMMY_SP};
+use crate::utils::{
+ get_trait_def_id, implements_trait, in_macro, match_type, paths, snippet_opt, span_lint_and_then, SpanlessEq,
+};
/// **What it does:** Checks for boolean expressions that can be written more
/// concisely.
}
// For each pairs, both orders are considered.
-const METHODS_WITH_NEGATION: [(&str, &str); 2] = [
- ("is_some", "is_none"),
- ("is_err", "is_ok"),
-];
+const METHODS_WITH_NEGATION: [(&str, &str); 2] = [("is_some", "is_none"), ("is_err", "is_ok")];
#[derive(Copy, Clone)]
pub struct NonminimalBool;
}
let negated = match e.node {
ExprKind::Binary(binop, ref lhs, ref rhs) => {
-
if !implements_ord(self.cx, lhs) {
continue;
}
- let mk_expr = |op| {
- Expr {
- id: DUMMY_NODE_ID,
- hir_id: DUMMY_HIR_ID,
- span: DUMMY_SP,
- attrs: ThinVec::new(),
- node: ExprKind::Binary(dummy_spanned(op), lhs.clone(), rhs.clone()),
- }
+ let mk_expr = |op| Expr {
+ id: DUMMY_NODE_ID,
+ hir_id: DUMMY_HIR_ID,
+ span: DUMMY_SP,
+ attrs: ThinVec::new(),
+ node: ExprKind::Binary(dummy_spanned(op), lhs.clone(), rhs.clone()),
};
match binop.node {
BinOpKind::Eq => mk_expr(BinOpKind::Ne),
fn simplify_not(&self, expr: &Expr) -> Option<String> {
match expr.node {
ExprKind::Binary(binop, ref lhs, ref rhs) => {
-
if !implements_ord(self.cx, lhs) {
return None;
}
BinOpKind::Le => Some(" > "),
BinOpKind::Ge => Some(" < "),
_ => None,
- }.and_then(|op| Some(format!("{}{}{}", self.snip(lhs)?, op, self.snip(rhs)?)))
+ }
+ .and_then(|op| Some(format!("{}{}{}", self.snip(lhs)?, op, self.snip(rhs)?)))
},
ExprKind::MethodCall(ref path, _, ref args) if args.len() == 1 => {
let type_of_receiver = self.cx.tables.expr_ty(&args[0]);
- if !match_type(self.cx, type_of_receiver, &paths::OPTION) &&
- !match_type(self.cx, type_of_receiver, &paths::RESULT) {
- return None;
+ if !match_type(self.cx, type_of_receiver, &paths::OPTION)
+ && !match_type(self.cx, type_of_receiver, &paths::RESULT)
+ {
+ return None;
}
METHODS_WITH_NEGATION
- .iter().cloned()
+ .iter()
+ .cloned()
.flat_map(|(a, b)| vec![(a, b), (b, a)])
.find(|&(a, _)| a == path.ident.as_str())
.and_then(|(_, neg_method)| Some(format!("{}.{}()", self.snip(&args[0])?, neg_method)))
improvements
.into_iter()
.map(|suggestion| suggest(self.cx, suggestion, &h2q.terminals).0)
- .collect()
+ .collect(),
);
}
}
return;
}
match e.node {
- ExprKind::Binary(binop, _, _) if binop.node == BinOpKind::Or || binop.node == BinOpKind::And => self.bool_expr(e),
- ExprKind::Unary(UnNot, ref inner) => if self.cx.tables.node_types()[inner.hir_id].is_bool() {
- self.bool_expr(e);
- } else {
- walk_expr(self, e);
+ ExprKind::Binary(binop, _, _) if binop.node == BinOpKind::Or || binop.node == BinOpKind::And => {
+ self.bool_expr(e)
+ },
+ ExprKind::Unary(UnNot, ref inner) => {
+ if self.cx.tables.node_types()[inner.hir_id].is_bool() {
+ self.bool_expr(e);
+ } else {
+ walk_expr(self, e);
+ }
},
_ => walk_expr(self, e),
}
}
}
-
fn implements_ord<'a, 'tcx>(cx: &'a LateContext<'a, 'tcx>, expr: &Expr) -> bool {
let ty = cx.tables.expr_ty(expr);
- get_trait_def_id(cx, &paths::ORD)
- .map_or(false, |id| implements_trait(cx, ty, id, &[]))
+ get_trait_def_id(cx, &paths::ORD).map_or(false, |id| implements_trait(cx, ty, id, &[]))
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::ty;
fn get_path_name(expr: &Expr) -> Option<Name> {
match expr.node {
ExprKind::Box(ref e) | ExprKind::AddrOf(_, ref e) | ExprKind::Unary(UnOp::UnDeref, ref e) => get_path_name(e),
- ExprKind::Block(ref b, _) => if b.stmts.is_empty() {
- b.expr.as_ref().and_then(|p| get_path_name(p))
- } else {
- None
+ ExprKind::Block(ref b, _) => {
+ if b.stmts.is_empty() {
+ b.expr.as_ref().and_then(|p| get_path_name(p))
+ } else {
+ None
+ }
},
ExprKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name),
_ => None,
match value {
None => true,
Some(value) if value.is_empty() => true,
- _ => false
+ _ => false,
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! Checks for if expressions that contain only an if expression.
//!
//! For example, the lint would catch:
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
use crate::syntax::ast;
+use if_chain::if_chain;
-use crate::utils::{in_macro, snippet_block, snippet_block_with_applicability, span_lint_and_sugg, span_lint_and_then};
-use crate::utils::sugg::Sugg;
use crate::rustc_errors::Applicability;
+use crate::utils::sugg::Sugg;
+use crate::utils::{in_macro, snippet_block, snippet_block_with_applicability, span_lint_and_sugg, span_lint_and_then};
/// **What it does:** Checks for nested `if` statements which can be collapsed
/// by `&&`-combining their conditions and for `else { if ... }` expressions
fn check_if(cx: &EarlyContext<'_>, expr: &ast::Expr) {
match expr.node {
- ast::ExprKind::If(ref check, ref then, ref else_) => if let Some(ref else_) = *else_ {
- check_collapsible_maybe_if_let(cx, else_);
- } else {
- check_collapsible_no_if_let(cx, expr, check, then);
+ ast::ExprKind::If(ref check, ref then, ref else_) => {
+ if let Some(ref else_) = *else_ {
+ check_collapsible_maybe_if_let(cx, else_);
+ } else {
+ check_collapsible_no_if_let(cx, expr, check, then);
+ }
},
ast::ExprKind::IfLet(_, _, _, Some(ref else_)) => {
check_collapsible_maybe_if_let(cx, else_);
fn block_starts_with_comment(cx: &EarlyContext<'_>, expr: &ast::Block) -> bool {
// We trim all opening braces and whitespaces and then check if the next string is a comment.
- let trimmed_block_text =
- snippet_block(cx, expr.span, "..").trim_left_matches(|c: char| c.is_whitespace() || c == '{').to_owned();
+ let trimmed_block_text = snippet_block(cx, expr.span, "..")
+ .trim_left_matches(|c: char| c.is_whitespace() || c == '{')
+ .to_owned();
trimmed_block_text.starts_with("//") || trimmed_block_text.starts_with("/*")
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use crate::syntax::ast::*;
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use crate::utils::{in_macro, snippet, span_lint_and_then};
use crate::rustc_errors::Applicability;
+use crate::syntax::ast::*;
+use crate::utils::{in_macro, snippet, span_lint_and_then};
/// **What it does:** Checks for constants with an explicit `'static` lifetime.
///
TyKind::Array(ref ty, _) => {
self.visit_type(&*ty, cx);
},
- TyKind::Tup(ref tup) => for tup_ty in tup {
- self.visit_type(&*tup_ty, cx);
+ TyKind::Tup(ref tup) => {
+ for tup_ty in tup {
+ self.visit_type(&*tup_ty, cx);
+ }
},
// This is what we are looking for !
TyKind::Rptr(ref optional_lifetime, ref borrow_type) => {
// Match the 'static lifetime
if let Some(lifetime) = *optional_lifetime {
match borrow_type.ty.node {
- TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) |
- TyKind::Tup(..) => {
+ TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) | TyKind::Tup(..) => {
if lifetime.ident.name == "'static" {
let snip = snippet(cx, borrow_type.ty.span, "<type>");
let sugg = format!("&{}", snip);
"Constants have by default a `'static` lifetime",
|db| {
db.span_suggestion_with_applicability(
- ty.span,
+ ty.span,
"consider removing `'static`",
sugg,
Applicability::MachineApplicable, //snippet
},
);
}
- }
- _ => {}
+ },
+ _ => {},
}
}
self.visit_type(&*borrow_type.ty, cx);
#![allow(clippy::float_cmp)]
-use crate::rustc::lint::LateContext;
-use crate::rustc::{span_bug, bug};
use crate::rustc::hir::def::Def;
use crate::rustc::hir::*;
-use crate::rustc::ty::{self, Ty, TyCtxt, Instance};
+use crate::rustc::lint::LateContext;
use crate::rustc::ty::subst::{Subst, Substs};
+use crate::rustc::ty::{self, Instance, Ty, TyCtxt};
+use crate::rustc::{bug, span_bug};
+use crate::syntax::ast::{FloatTy, LitKind};
+use crate::syntax::ptr::P;
+use crate::utils::{clip, sext, unsext};
use std::cmp::Ordering::{self, Equal};
use std::cmp::PartialOrd;
use std::convert::TryInto;
use std::hash::{Hash, Hasher};
use std::mem;
use std::rc::Rc;
-use crate::syntax::ast::{FloatTy, LitKind};
-use crate::syntax::ptr::P;
-use crate::utils::{sext, unsext, clip};
/// A `LitKind`-like enum to fold constant `Expr`s into.
#[derive(Debug, Clone)]
unsafe { mem::transmute::<f64, u64>(f64::from(l)) == mem::transmute::<f64, u64>(f64::from(r)) }
},
(&Constant::Bool(l), &Constant::Bool(r)) => l == r,
- (&Constant::Vec(ref l), &Constant::Vec(ref r)) | (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) => l == r,
+ (&Constant::Vec(ref l), &Constant::Vec(ref r)) | (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) => {
+ l == r
+ },
(&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => ls == rs && lv == rv,
_ => false, // TODO: Are there inter-type equalities?
}
}
impl Constant {
- pub fn partial_cmp(tcx: TyCtxt<'_, '_, '_>, cmp_type: &ty::TyKind<'_>, left: &Self, right: &Self) -> Option<Ordering> {
+ pub fn partial_cmp(
+ tcx: TyCtxt<'_, '_, '_>,
+ cmp_type: &ty::TyKind<'_>,
+ left: &Self,
+ right: &Self,
+ ) -> Option<Ordering> {
match (left, right) {
(&Constant::Str(ref ls), &Constant::Str(ref rs)) => Some(ls.cmp(rs)),
(&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)),
LitKind::ByteStr(ref s) => Constant::Binary(Rc::clone(s)),
LitKind::Char(c) => Constant::Char(c),
LitKind::Int(n, _) => Constant::Int(n),
- LitKind::Float(ref is, _) |
- LitKind::FloatUnsuffixed(ref is) => match ty.sty {
+ LitKind::Float(ref is, _) | LitKind::FloatUnsuffixed(ref is) => match ty.sty {
ty::Float(FloatTy::F32) => Constant::F32(is.as_str().parse().unwrap()),
ty::Float(FloatTy::F64) => Constant::F64(is.as_str().parse().unwrap()),
_ => bug!(),
}
}
-pub fn constant<'c, 'cc>(lcx: &LateContext<'c, 'cc>, tables: &'c ty::TypeckTables<'cc>, e: &Expr) -> Option<(Constant, bool)> {
+pub fn constant<'c, 'cc>(
+ lcx: &LateContext<'c, 'cc>,
+ tables: &'c ty::TypeckTables<'cc>,
+ e: &Expr,
+) -> Option<(Constant, bool)> {
let mut cx = ConstEvalLateContext {
tcx: lcx.tcx,
tables,
cx.expr(e).map(|cst| (cst, cx.needed_resolution))
}
-pub fn constant_simple<'c, 'cc>(lcx: &LateContext<'c, 'cc>, tables: &'c ty::TypeckTables<'cc>, e: &Expr) -> Option<Constant> {
+pub fn constant_simple<'c, 'cc>(
+ lcx: &LateContext<'c, 'cc>,
+ tables: &'c ty::TypeckTables<'cc>,
+ e: &Expr,
+) -> Option<Constant> {
constant(lcx, tables, e).and_then(|(cst, res)| if res { None } else { Some(cst) })
}
/// Creates a `ConstEvalLateContext` from the given `LateContext` and `TypeckTables`
-pub fn constant_context<'c, 'cc>(lcx: &LateContext<'c, 'cc>, tables: &'c ty::TypeckTables<'cc>) -> ConstEvalLateContext<'c, 'cc> {
+pub fn constant_context<'c, 'cc>(
+ lcx: &LateContext<'c, 'cc>,
+ tables: &'c ty::TypeckTables<'cc>,
+) -> ConstEvalLateContext<'c, 'cc> {
ConstEvalLateContext {
tcx: lcx.tcx,
tables,
/// create `Some(Vec![..])` of all constants, unless there is any
/// non-constant part
fn multi(&mut self, vec: &[Expr]) -> Option<Vec<Constant>> {
- vec.iter()
- .map(|elem| self.expr(elem))
- .collect::<Option<_>>()
+ vec.iter().map(|elem| self.expr(elem)).collect::<Option<_>>()
}
/// lookup a possibly constant expression from a ExprKind::Path
let l = self.expr(left)?;
let r = self.expr(right);
match (l, r) {
- (Constant::Int(l), Some(Constant::Int(r))) => {
- match self.tables.expr_ty(left).sty {
- ty::Int(ity) => {
- let l = sext(self.tcx, l, ity);
- let r = sext(self.tcx, r, ity);
- let zext = |n: i128| Constant::Int(unsext(self.tcx, n, ity));
- match op.node {
- BinOpKind::Add => l.checked_add(r).map(zext),
- BinOpKind::Sub => l.checked_sub(r).map(zext),
- BinOpKind::Mul => l.checked_mul(r).map(zext),
- BinOpKind::Div if r != 0 => l.checked_div(r).map(zext),
- BinOpKind::Rem if r != 0 => l.checked_rem(r).map(zext),
- BinOpKind::Shr => l.checked_shr(
- r.try_into().expect("invalid shift")
- ).map(zext),
- BinOpKind::Shl => l.checked_shl(
- r.try_into().expect("invalid shift")
- ).map(zext),
- BinOpKind::BitXor => Some(zext(l ^ r)),
- BinOpKind::BitOr => Some(zext(l | r)),
- BinOpKind::BitAnd => Some(zext(l & r)),
- BinOpKind::Eq => Some(Constant::Bool(l == r)),
- BinOpKind::Ne => Some(Constant::Bool(l != r)),
- BinOpKind::Lt => Some(Constant::Bool(l < r)),
- BinOpKind::Le => Some(Constant::Bool(l <= r)),
- BinOpKind::Ge => Some(Constant::Bool(l >= r)),
- BinOpKind::Gt => Some(Constant::Bool(l > r)),
- _ => None,
- }
+ (Constant::Int(l), Some(Constant::Int(r))) => match self.tables.expr_ty(left).sty {
+ ty::Int(ity) => {
+ let l = sext(self.tcx, l, ity);
+ let r = sext(self.tcx, r, ity);
+ let zext = |n: i128| Constant::Int(unsext(self.tcx, n, ity));
+ match op.node {
+ BinOpKind::Add => l.checked_add(r).map(zext),
+ BinOpKind::Sub => l.checked_sub(r).map(zext),
+ BinOpKind::Mul => l.checked_mul(r).map(zext),
+ BinOpKind::Div if r != 0 => l.checked_div(r).map(zext),
+ BinOpKind::Rem if r != 0 => l.checked_rem(r).map(zext),
+ BinOpKind::Shr => l.checked_shr(r.try_into().expect("invalid shift")).map(zext),
+ BinOpKind::Shl => l.checked_shl(r.try_into().expect("invalid shift")).map(zext),
+ BinOpKind::BitXor => Some(zext(l ^ r)),
+ BinOpKind::BitOr => Some(zext(l | r)),
+ BinOpKind::BitAnd => Some(zext(l & r)),
+ BinOpKind::Eq => Some(Constant::Bool(l == r)),
+ BinOpKind::Ne => Some(Constant::Bool(l != r)),
+ BinOpKind::Lt => Some(Constant::Bool(l < r)),
+ BinOpKind::Le => Some(Constant::Bool(l <= r)),
+ BinOpKind::Ge => Some(Constant::Bool(l >= r)),
+ BinOpKind::Gt => Some(Constant::Bool(l > r)),
+ _ => None,
}
- ty::Uint(_) => {
- match op.node {
- BinOpKind::Add => l.checked_add(r).map(Constant::Int),
- BinOpKind::Sub => l.checked_sub(r).map(Constant::Int),
- BinOpKind::Mul => l.checked_mul(r).map(Constant::Int),
- BinOpKind::Div => l.checked_div(r).map(Constant::Int),
- BinOpKind::Rem => l.checked_rem(r).map(Constant::Int),
- BinOpKind::Shr => l.checked_shr(
- r.try_into().expect("shift too large")
- ).map(Constant::Int),
- BinOpKind::Shl => l.checked_shl(
- r.try_into().expect("shift too large")
- ).map(Constant::Int),
- BinOpKind::BitXor => Some(Constant::Int(l ^ r)),
- BinOpKind::BitOr => Some(Constant::Int(l | r)),
- BinOpKind::BitAnd => Some(Constant::Int(l & r)),
- BinOpKind::Eq => Some(Constant::Bool(l == r)),
- BinOpKind::Ne => Some(Constant::Bool(l != r)),
- BinOpKind::Lt => Some(Constant::Bool(l < r)),
- BinOpKind::Le => Some(Constant::Bool(l <= r)),
- BinOpKind::Ge => Some(Constant::Bool(l >= r)),
- BinOpKind::Gt => Some(Constant::Bool(l > r)),
- _ => None,
- }
- },
+ },
+ ty::Uint(_) => match op.node {
+ BinOpKind::Add => l.checked_add(r).map(Constant::Int),
+ BinOpKind::Sub => l.checked_sub(r).map(Constant::Int),
+ BinOpKind::Mul => l.checked_mul(r).map(Constant::Int),
+ BinOpKind::Div => l.checked_div(r).map(Constant::Int),
+ BinOpKind::Rem => l.checked_rem(r).map(Constant::Int),
+ BinOpKind::Shr => l.checked_shr(r.try_into().expect("shift too large")).map(Constant::Int),
+ BinOpKind::Shl => l.checked_shl(r.try_into().expect("shift too large")).map(Constant::Int),
+ BinOpKind::BitXor => Some(Constant::Int(l ^ r)),
+ BinOpKind::BitOr => Some(Constant::Int(l | r)),
+ BinOpKind::BitAnd => Some(Constant::Int(l & r)),
+ BinOpKind::Eq => Some(Constant::Bool(l == r)),
+ BinOpKind::Ne => Some(Constant::Bool(l != r)),
+ BinOpKind::Lt => Some(Constant::Bool(l < r)),
+ BinOpKind::Le => Some(Constant::Bool(l <= r)),
+ BinOpKind::Ge => Some(Constant::Bool(l >= r)),
+ BinOpKind::Gt => Some(Constant::Bool(l > r)),
_ => None,
- }
+ },
+ _ => None,
},
(Constant::F32(l), Some(Constant::F32(r))) => match op.node {
BinOpKind::Add => Some(Constant::F32(l + r)),
(l, r) => match (op.node, l, r) {
(BinOpKind::And, Constant::Bool(false), _) => Some(Constant::Bool(false)),
(BinOpKind::Or, Constant::Bool(true), _) => Some(Constant::Bool(true)),
- (BinOpKind::And, Constant::Bool(true), Some(r)) | (BinOpKind::Or, Constant::Bool(false), Some(r)) => Some(r),
+ (BinOpKind::And, Constant::Bool(true), Some(r)) | (BinOpKind::Or, Constant::Bool(false), Some(r)) => {
+ Some(r)
+ },
(BinOpKind::BitXor, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l ^ r)),
(BinOpKind::BitAnd, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l & r)),
(BinOpKind::BitOr, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l | r)),
}
pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<'tcx>) -> Option<Constant> {
- use crate::rustc::mir::interpret::{Scalar, ConstValue};
+ use crate::rustc::mir::interpret::{ConstValue, Scalar};
match result.val {
- ConstValue::Scalar(Scalar::Bits{ bits: b, ..}) => match result.ty.sty {
+ ConstValue::Scalar(Scalar::Bits { bits: b, .. }) => match result.ty.sty {
ty::Bool => Some(Constant::Bool(b == 1)),
ty::Uint(_) | ty::Int(_) => Some(Constant::Int(b)),
ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(
- b.try_into().expect("invalid f32 bit representation")
+ b.try_into().expect("invalid f32 bit representation"),
))),
ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(
- b.try_into().expect("invalid f64 bit representation")
+ b.try_into().expect("invalid f64 bit representation"),
))),
// FIXME: implement other conversion
_ => None,
},
- ConstValue::ScalarPair(Scalar::Ptr(ptr),
- Scalar::Bits { bits: n, .. }) => match result.ty.sty {
+ ConstValue::ScalarPair(Scalar::Ptr(ptr), Scalar::Bits { bits: n, .. }) => match result.ty.sty {
ty::Ref(_, tam, _) => match tam.sty {
ty::Str => {
- let alloc = tcx
- .alloc_map
- .lock()
- .unwrap_memory(ptr.alloc_id);
+ let alloc = tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
let offset = ptr.offset.bytes().try_into().expect("too-large pointer offset");
let n = n as usize;
- String::from_utf8(alloc.bytes[offset..(offset + n)].to_owned()).ok().map(Constant::Str)
+ String::from_utf8(alloc.bytes[offset..(offset + n)].to_owned())
+ .ok()
+ .map(Constant::Str)
},
_ => None,
},
_ => None,
- }
+ },
// FIXME: implement other conversions
_ => None,
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc::ty::Ty;
-use crate::rustc::hir::*;
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_data_structures::fx::FxHashMap;
-use std::collections::hash_map::Entry;
-use std::hash::BuildHasherDefault;
use crate::syntax::symbol::LocalInternedString;
-use smallvec::SmallVec;
-use crate::utils::{SpanlessEq, SpanlessHash};
use crate::utils::{get_parent_expr, in_macro, snippet, span_lint_and_then, span_note_and_lint};
+use crate::utils::{SpanlessEq, SpanlessHash};
+use smallvec::SmallVec;
+use std::collections::hash_map::Entry;
+use std::hash::BuildHasherDefault;
/// **What it does:** Checks for consecutive `if`s with the same condition.
///
h.finish()
};
- let eq: &dyn Fn(&&Expr, &&Expr) -> bool = &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) };
+ let eq: &dyn Fn(&&Expr, &&Expr) -> bool =
+ &|&lhs, &rhs| -> bool { SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) };
if let Some((i, j)) = search_same(conds, hash, eq) {
span_note_and_lint(
// hiding all the subsequent arms, and rust won't compile
db.span_note(
i.body.span,
- &format!("`{}` has the same arm body as the `_` wildcard, consider removing it`", lhs),
+ &format!(
+ "`{}` has the same arm body as the `_` wildcard, consider removing it`",
+ lhs
+ ),
);
} else {
db.span_note(i.body.span, &format!("consider refactoring into `{} | {}`", lhs, rhs));
/// Return the list of bindings in a pattern.
fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> FxHashMap<LocalInternedString, Ty<'tcx>> {
- fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat, map: &mut FxHashMap<LocalInternedString, Ty<'tcx>>) {
+ fn bindings_impl<'a, 'tcx>(
+ cx: &LateContext<'a, 'tcx>,
+ pat: &Pat,
+ map: &mut FxHashMap<LocalInternedString, Ty<'tcx>>,
+ ) {
match pat.node {
PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map),
- PatKind::TupleStruct(_, ref pats, _) => for pat in pats {
- bindings_impl(cx, pat, map);
+ PatKind::TupleStruct(_, ref pats, _) => {
+ for pat in pats {
+ bindings_impl(cx, pat, map);
+ }
},
PatKind::Binding(_, _, ident, ref as_pat) => {
if let Entry::Vacant(v) = map.entry(ident.as_str()) {
bindings_impl(cx, as_pat, map);
}
},
- PatKind::Struct(_, ref fields, _) => for pat in fields {
- bindings_impl(cx, &pat.node.pat, map);
+ PatKind::Struct(_, ref fields, _) => {
+ for pat in fields {
+ bindings_impl(cx, &pat.node.pat, map);
+ }
},
- PatKind::Tuple(ref fields, _) => for pat in fields {
- bindings_impl(cx, pat, map);
+ PatKind::Tuple(ref fields, _) => {
+ for pat in fields {
+ bindings_impl(cx, pat, map);
+ }
},
PatKind::Slice(ref lhs, ref mid, ref rhs) => {
for pat in lhs {
result
}
-
fn search_same_sequenced<T, Eq>(exprs: &[T], eq: Eq) -> Option<(&T, &T)>
where
Eq: Fn(&T, &T) -> bool,
};
}
- let mut map: FxHashMap<_, Vec<&_>> = FxHashMap::with_capacity_and_hasher(
- exprs.len(),
- BuildHasherDefault::default()
- );
+ let mut map: FxHashMap<_, Vec<&_>> =
+ FxHashMap::with_capacity_and_hasher(exprs.len(), BuildHasherDefault::default());
for expr in exprs {
match map.entry(hash(expr)) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use crate::utils::{is_copy, match_path, paths, span_note_and_lint};
use crate::rustc::hir::{Item, ItemKind};
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
+use crate::utils::{is_copy, match_path, paths, span_note_and_lint};
/// **What it does:** Checks for types that implement `Copy` as well as
/// `Iterator`.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! calculate cyclomatic complexity and warn about overly complex functions
use crate::rustc::cfg::CFG;
-use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, LintContext};
-use crate::rustc::{declare_tool_lint, lint_array};
+use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use crate::rustc::hir::*;
+use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
use crate::rustc::ty;
-use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast::{Attribute, NodeId};
use crate::syntax::source_map::Span;
}
fn enter_lint_attrs(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) {
- self.limit
- .push_attrs(cx.sess(), attrs, "cyclomatic_complexity");
+ self.limit.push_attrs(cx.sess(), attrs, "cyclomatic_complexity");
}
fn exit_lint_attrs(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) {
- self.limit
- .pop_attrs(cx.sess(), attrs, "cyclomatic_complexity");
+ self.limit.pop_attrs(cx.sess(), attrs, "cyclomatic_complexity");
}
}
#[cfg(feature = "debugging")]
#[allow(clippy::too_many_arguments)]
-fn report_cc_bug(_: &LateContext<'_, '_>, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span, _: NodeId) {
+fn report_cc_bug(
+ _: &LateContext<'_, '_>,
+ cc: u64,
+ narms: u64,
+ div: u64,
+ shorts: u64,
+ returns: u64,
+ span: Span,
+ _: NodeId,
+) {
span_bug!(
span,
"Clippy encountered a bug calculating cyclomatic complexity: cc = {}, arms = {}, \
}
#[cfg(not(feature = "debugging"))]
#[allow(clippy::too_many_arguments)]
-fn report_cc_bug(cx: &LateContext<'_, '_>, cc: u64, narms: u64, div: u64, shorts: u64, returns: u64, span: Span, id: NodeId) {
+fn report_cc_bug(
+ cx: &LateContext<'_, '_>,
+ cc: u64,
+ narms: u64,
+ div: u64,
+ shorts: u64,
+ returns: u64,
+ span: Span,
+ id: NodeId,
+) {
if !is_allowed(cx, CYCLOMATIC_COMPLEXITY, id) {
cx.sess().span_note_without_error(
span,
(hide this message with `#[allow(cyclomatic_complexity)]`): \
cc = {}, arms = {}, div = {}, shorts = {}, returns = {}. \
Please file a bug report.",
- cc,
- narms,
- div,
- shorts,
- returns
+ cc, narms, div, shorts, returns
),
);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::ty::TyKind;
use crate::utils::{any_parent_is_automatically_derived, match_def_path, opt_def_id, paths, span_lint_and_sugg};
-
/// **What it does:** Checks for literal calls to `Default::default()`.
///
/// **Why is this bad?** It's more clear to the reader to use the name of the type whose default is
QPath::TypeRelative(..) => {},
}
}
- }
+ }
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
use crate::rustc::ty::{self, Ty};
-use crate::rustc::hir::*;
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::source_map::Span;
use crate::utils::paths;
use crate::utils::{is_automatically_derived, is_copy, match_path, span_lint_and_then};
+use if_chain::if_chain;
/// **What it does:** Checks for deriving `Hash` but implementing `PartialEq`
/// explicitly or vice versa.
ty::Adt(def, _) if def.is_union() => return,
// Some types are not Clone by default but could be cloned “by hand” if necessary
- ty::Adt(def, substs) => for variant in &def.variants {
- for field in &variant.fields {
- if let ty::FnDef(..) = field.ty(cx.tcx, substs).sty {
- return;
- }
- }
- for subst in substs {
- if let ty::subst::UnpackedKind::Type(subst) = subst.unpack() {
- if let ty::Param(_) = subst.sty {
+ ty::Adt(def, substs) => {
+ for variant in &def.variants {
+ for field in &variant.fields {
+ if let ty::FnDef(..) = field.ty(cx.tcx, substs).sty {
return;
}
}
+ for subst in substs {
+ if let ty::subst::UnpackedKind::Type(subst) = subst.unpack() {
+ if let ty::Param(_) = subst.sty {
+ return;
+ }
+ }
+ }
}
},
_ => (),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use itertools::Itertools;
-use pulldown_cmark;
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast;
use crate::syntax::source_map::{BytePos, Span};
use crate::syntax_pos::Pos;
use crate::utils::span_lint;
+use itertools::Itertools;
+use pulldown_cmark;
use url::Url;
/// **What it does:** Checks for the presence of `_`, `::` or camel-case words
impl Doc {
pub fn new(valid_idents: Vec<String>) -> Self {
- Self {
- valid_idents,
- }
+ Self { valid_idents }
}
}
doc.push('\n');
return (
doc.to_owned(),
- vec![
- (doc.len(), span.with_lo(span.lo() + BytePos(prefix.len() as u32))),
- ],
+ vec![(doc.len(), span.with_lo(span.lo() + BytePos(prefix.len() as u32)))],
);
}
}
return false;
}
- let s = if s.ends_with('s') {
- &s[..s.len() - 1]
- } else {
- s
- };
+ let s = if s.ends_with('s') { &s[..s.len() - 1] } else { s };
- s.chars().all(char::is_alphanumeric) && s.chars().filter(|&c| c.is_uppercase()).take(2).count() > 1
+ s.chars().all(char::is_alphanumeric)
+ && s.chars().filter(|&c| c.is_uppercase()).take(2).count() > 1
&& s.chars().filter(|&c| c.is_lowercase()).take(1).count() > 0
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! Lint on unnecessary double comparisons. Some examples:
use crate::rustc::hir::*;
impl<'a, 'tcx> Pass {
#[allow(clippy::similar_names)]
- fn check_binop(
- &self,
- cx: &LateContext<'a, 'tcx>,
- op: BinOpKind,
- lhs: &'tcx Expr,
- rhs: &'tcx Expr,
- span: Span,
- ) {
+ fn check_binop(&self, cx: &LateContext<'a, 'tcx>, op: BinOpKind, lhs: &'tcx Expr, rhs: &'tcx Expr, span: Span) {
let (lkind, llhs, lrhs, rkind, rlhs, rrhs) = match (lhs.node.clone(), rhs.node.clone()) {
(ExprKind::Binary(lb, llhs, lrhs), ExprKind::Binary(rb, rlhs, rrhs)) => {
(lb.node, llhs, lrhs, rb.node, rlhs, rrhs)
- }
+ },
_ => return,
};
let mut spanless_eq = SpanlessEq::new(cx).ignore_fn();
sugg,
applicability,
);
- }}
+ }};
}
match (op, lkind, rkind) {
- (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Lt) | (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Eq) => lint_double_comparison!(<=),
- (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Eq) => lint_double_comparison!(>=),
- (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Lt) => lint_double_comparison!(!=),
- (BinOpKind::And, BinOpKind::Le, BinOpKind::Ge) | (BinOpKind::And, BinOpKind::Ge, BinOpKind::Le) => lint_double_comparison!(==),
+ (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Lt) | (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Eq) => {
+ lint_double_comparison!(<=)
+ },
+ (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Eq) => {
+ lint_double_comparison!(>=)
+ },
+ (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Lt) => {
+ lint_double_comparison!(!=)
+ },
+ (BinOpKind::And, BinOpKind::Le, BinOpKind::Ge) | (BinOpKind::And, BinOpKind::Ge, BinOpKind::Le) => {
+ lint_double_comparison!(==)
+ },
_ => (),
};
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use crate::syntax::ast::*;
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
+use crate::syntax::ast::*;
use crate::utils::{in_macro, span_lint};
-
/// **What it does:** Checks for unnecessary double parentheses.
///
/// **Why is this bad?** This makes code harder to read and might indicate a
match expr.node {
ExprKind::Paren(ref in_paren) => match in_paren.node {
ExprKind::Paren(_) | ExprKind::Tup(_) => {
- span_lint(cx, DOUBLE_PARENS, expr.span, "Consider removing unnecessary double parentheses");
+ span_lint(
+ cx,
+ DOUBLE_PARENS,
+ expr.span,
+ "Consider removing unnecessary double parentheses",
+ );
},
_ => {},
},
- ExprKind::Call(_, ref params) => if params.len() == 1 {
- let param = ¶ms[0];
- if let ExprKind::Paren(_) = param.node {
- span_lint(cx, DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses");
+ ExprKind::Call(_, ref params) => {
+ if params.len() == 1 {
+ let param = ¶ms[0];
+ if let ExprKind::Paren(_) = param.node {
+ span_lint(
+ cx,
+ DOUBLE_PARENS,
+ param.span,
+ "Consider removing unnecessary double parentheses",
+ );
+ }
}
},
- ExprKind::MethodCall(_, ref params) => if params.len() == 2 {
- let param = ¶ms[1];
- if let ExprKind::Paren(_) = param.node {
- span_lint(cx, DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses");
+ ExprKind::MethodCall(_, ref params) => {
+ if params.len() == 2 {
+ let param = ¶ms[1];
+ if let ExprKind::Paren(_) = param.node {
+ span_lint(
+ cx,
+ DOUBLE_PARENS,
+ param.span,
+ "Consider removing unnecessary double parentheses",
+ );
+ }
}
},
_ => {},
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
use crate::rustc::ty;
-use crate::rustc::hir::*;
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::utils::{is_copy, match_def_path, opt_def_id, paths, span_note_and_lint};
+use if_chain::if_chain;
/// **What it does:** Checks for calls to `std::mem::drop` with a reference
/// instead of an owned value.
///
/// **Example:**
/// ```rust
-/// let x:i32 = 42; // i32 implements Copy
+/// let x: i32 = 42; // i32 implements Copy
/// std::mem::drop(x) // A copy of x is passed to the function, leaving the
-/// // original unaffected
+/// // original unaffected
/// ```
declare_clippy_lint! {
pub DROP_COPY,
///
/// **Example:**
/// ```rust
-/// let x:i32 = 42; // i32 implements Copy
+/// let x: i32 = 42; // i32 implements Copy
/// std::mem::forget(x) // A copy of x is passed to the function, leaving the
-/// // original unaffected
+/// // original unaffected
/// ```
declare_clippy_lint! {
pub FORGET_COPY,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
expr.span,
&format!("Calling `{}()` is more concise than this calculation", suggested_fn),
"try",
- format!("{}.{}()", snippet_with_applicability(cx, args[0].span, "_", &mut applicability), suggested_fn),
+ format!(
+ "{}.{}()",
+ snippet_with_applicability(cx, args[0].span, "_", &mut applicability),
+ suggested_fn
+ ),
applicability,
);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! lint on if expressions with an else if, but without a final else branch
-use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_external_macro, LintContext};
+use crate::rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast::*;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! lint when there is an enum with no variants
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use crate::rustc::hir::*;
use crate::utils::span_lint_and_then;
/// **What it does:** Checks for `enum`s with no variants.
let did = cx.tcx.hir.local_def_id(item.id);
if let ItemKind::Enum(..) = item.node {
let ty = cx.tcx.type_of(did);
- let adt = ty.ty_adt_def()
- .expect("already checked whether this is an enum");
+ let adt = ty.ty_adt_def().expect("already checked whether this is an enum");
if adt.variants.is_empty() {
span_lint_and_then(cx, EMPTY_ENUM, item.span, "enum with no variants", |db| {
- db.span_help(item.span, "consider using the uninhabited type `!` or a wrapper around it");
+ db.span_help(
+ item.span,
+ "consider using the uninhabited type `!` or a wrapper around it",
+ );
});
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use crate::rustc::hir::*;
use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
+use crate::rustc_errors::Applicability;
use crate::syntax::source_map::Span;
use crate::utils::SpanlessEq;
use crate::utils::{get_item_name, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty};
-use crate::rustc_errors::Applicability;
+use if_chain::if_chain;
/// **What it does:** Checks for uses of `contains_key` + `insert` on `HashMap`
/// or `BTreeMap`.
/// **Known problems:** Some false negatives, eg.:
/// ```rust
/// let k = &key;
-/// if !m.contains_key(k) { m.insert(k.clone(), v); }
+/// if !m.contains_key(k) {
+/// m.insert(k.clone(), v);
+/// }
/// ```
///
/// **Example:**
/// ```rust
-/// if !m.contains_key(&k) { m.insert(k, v) }
+/// if !m.contains_key(&k) {
+/// m.insert(k, v)
+/// }
/// ```
/// can be rewritten as:
/// ```rust
// in case of `if !m.contains_key(&k) { m.insert(k, v); }`
// we can give a better error message
let sole_expr = {
- else_block.is_none() && if let ExprKind::Block(ref then_block, _) = then_block.node {
- (then_block.expr.is_some() as usize) + then_block.stmts.len() == 1
- } else {
- true
- }
+ else_block.is_none()
+ && if let ExprKind::Block(ref then_block, _) = then_block.node {
+ (then_block.expr.is_some() as usize) + then_block.stmts.len() == 1
+ } else {
+ true
+ }
};
let mut visitor = InsertVisitor {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! lint on C-like enums that are `repr(isize/usize)` and have values that
//! don't fit into an `i32`
-use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
+use crate::consts::{miri_to_const, Constant};
use crate::rustc::hir::*;
+use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
+use crate::rustc::mir::interpret::GlobalId;
use crate::rustc::ty;
use crate::rustc::ty::subst::Substs;
+use crate::rustc::ty::util::IntTypeExt;
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast::{IntTy, UintTy};
use crate::utils::span_lint;
-use crate::consts::{Constant, miri_to_const};
-use crate::rustc::ty::util::IntTypeExt;
-use crate::rustc::mir::interpret::GlobalId;
/// **What it does:** Checks for C-like enumerations that are
/// `repr(isize/usize)` and have values that don't fit into an `i32`.
/// #[repr(usize)]
/// enum NonPortable {
/// X = 0x1_0000_0000,
-/// Y = 0
+/// Y = 0,
/// }
/// ```
declare_clippy_lint! {
let instance = ty::Instance::new(def_id, substs);
let c_id = GlobalId {
instance,
- promoted: None
+ promoted: None,
};
let constant = cx.tcx.const_eval(param_env.and(c_id)).ok();
if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx.tcx, c)) {
if val <= i128::from(i32::max_value()) && val >= i128::from(i32::min_value()) {
continue;
}
- }
+ },
ty::Uint(UintTy::Usize) if val > u128::from(u32::max_value()) => {},
_ => continue,
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! lint on `use`ing all variants of an enum
-use crate::rustc::hir::*;
use crate::rustc::hir::def::Def;
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast::NodeId;
}
if let ItemKind::Use(ref path, UseKind::Glob) = item.node {
if let Def::Enum(_) = path.def {
- span_lint(
- cx,
- ENUM_GLOB_USE,
- item.span,
- "don't use glob imports for enum variants",
- );
+ span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants");
}
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! lint on enum variants that are prefixed or suffixed by the same characters
-use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, Lint};
+use crate::rustc::lint::{EarlyContext, EarlyLintPass, Lint, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast::*;
use crate::syntax::source_map::Span;
use crate::syntax::symbol::LocalInternedString;
-use crate::utils::{span_help_and_lint, span_lint};
use crate::utils::{camel_case, in_macro};
+use crate::utils::{span_help_and_lint, span_lint};
/// **What it does:** Detects enumeration variants that are prefixed or suffixed
/// by the same characters.
fn partial_match(pre: &str, name: &str) -> usize {
let mut name_iter = name.chars();
let _ = name_iter.next_back(); // make sure the name is never fully matched
- pre.chars()
- .zip(name_iter)
- .take_while(|&(l, r)| l == r)
- .count()
+ pre.chars().zip(name_iter).take_while(|&(l, r)| l == r).count()
}
/// Returns the number of chars that match from the end
for var in &def.variants {
let name = var2str(var);
if partial_match(item_name, &name) == item_name_chars
- && name.chars()
- .nth(item_name_chars)
- .map_or(false, |c| !c.is_lowercase())
+ && name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase())
{
span_lint(cx, lint, var.span, "Variant name starts with the enum's name");
}
let rmatching = partial_rmatch(mod_camel, &item_camel);
let nchars = mod_camel.chars().count();
- let is_word_beginning = |c: char| {
- c == '_' || c.is_uppercase() || c.is_numeric()
- };
+ let is_word_beginning = |c: char| c == '_' || c.is_uppercase() || c.is_numeric();
if matching == nchars {
match item_camel.chars().nth(nchars) {
- Some(c) if is_word_beginning(c) =>
- span_lint(cx, STUTTER, item.span, "item name starts with its containing module's name"),
- _ => ()
+ Some(c) if is_word_beginning(c) => span_lint(
+ cx,
+ STUTTER,
+ item.span,
+ "item name starts with its containing module's name",
+ ),
+ _ => (),
}
}
if rmatching == nchars {
- span_lint(cx, STUTTER, item.span, "item name ends with its containing module's name");
+ span_lint(
+ cx,
+ STUTTER,
+ item.span,
+ "item name ends with its containing module's name",
+ );
}
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use crate::utils::{in_macro, implements_trait, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq};
use crate::rustc_errors::Applicability;
+use crate::utils::{
+ implements_trait, in_macro, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq,
+};
/// **What it does:** Checks for equal operands to comparison, logical and
/// bitwise, difference and division binary operators (`==`, `>`, etc., `&&`,
BinOpKind::Shl => (cx.tcx.lang_items().shl_trait(), false),
BinOpKind::Shr => (cx.tcx.lang_items().shr_trait(), false),
BinOpKind::Ne | BinOpKind::Eq => (cx.tcx.lang_items().eq_trait(), true),
- BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ge | BinOpKind::Gt => (cx.tcx.lang_items().ord_trait(), true),
+ BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ge | BinOpKind::Gt => {
+ (cx.tcx.lang_items().ord_trait(), true)
+ },
};
if let Some(trait_id) = trait_id {
#[allow(clippy::match_same_arms)]
);
},
)
- } else if lcpy && !rcpy && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()]) {
+ } else if lcpy
+ && !rcpy
+ && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()])
+ {
span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| {
let lsnip = snippet(cx, l.span, "...").to_string();
db.span_suggestion_with_applicability(
Applicability::MachineApplicable, // snippet
);
})
- } else if !lcpy && rcpy && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()]) {
+ } else if !lcpy
+ && rcpy
+ && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()])
+ {
span_lint_and_then(
cx,
OP_REF,
(&ExprKind::AddrOf(_, ref l), _) => {
let lty = cx.tables.expr_ty(l);
let lcpy = is_copy(cx, lty);
- if (requires_ref || lcpy) && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()]) {
+ if (requires_ref || lcpy)
+ && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()])
+ {
span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| {
let lsnip = snippet(cx, l.span, "...").to_string();
db.span_suggestion_with_applicability(
(_, &ExprKind::AddrOf(_, ref r)) => {
let rty = cx.tables.expr_ty(r);
let rcpy = is_copy(cx, rty);
- if (requires_ref || rcpy) && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()]) {
+ if (requires_ref || rcpy)
+ && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()])
+ {
span_lint_and_then(cx, OP_REF, e.span, "taken reference of right operand", |db| {
let rsnip = snippet(cx, r.span, "...").to_string();
db.span_suggestion_with_applicability(
}
}
-
fn is_valid_operator(op: BinOp) -> bool {
match op.node {
- BinOpKind::Sub | BinOpKind::Div | BinOpKind::Eq | BinOpKind::Lt | BinOpKind::Le | BinOpKind::Gt | BinOpKind::Ge | BinOpKind::Ne | BinOpKind::And | BinOpKind::Or | BinOpKind::BitXor | BinOpKind::BitAnd | BinOpKind::BitOr => true,
+ BinOpKind::Sub
+ | BinOpKind::Div
+ | BinOpKind::Eq
+ | BinOpKind::Lt
+ | BinOpKind::Le
+ | BinOpKind::Gt
+ | BinOpKind::Ge
+ | BinOpKind::Ne
+ | BinOpKind::And
+ | BinOpKind::Or
+ | BinOpKind::BitXor
+ | BinOpKind::BitAnd
+ | BinOpKind::BitOr => true,
_ => false,
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::consts::{constant_simple, Constant};
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
///
/// **Example:**
/// ```rust
-/// 0 / x; 0 * x; x & 0
+/// 0 / x;
+/// 0 * x;
+/// x & 0
/// ```
declare_clippy_lint! {
pub ERASING_OP,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use crate::rustc::hir::*;
use crate::rustc::hir::intravisit as visit;
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc::middle::expr_use_visitor::*;
use crate::rustc::middle::mem_categorization::{cmt_, Categorization};
-use crate::rustc::ty::{self, Ty};
use crate::rustc::ty::layout::LayoutOf;
+use crate::rustc::ty::{self, Ty};
use crate::rustc::util::nodemap::NodeSet;
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast::NodeId;
use crate::syntax::source_map::Span;
use crate::utils::span_lint;
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
-
fn check_fn(
&mut self,
cx: &LateContext<'a, 'tcx>,
}
}
}
- fn borrow(&mut self, _: NodeId, _: Span, cmt: &cmt_<'tcx>, _: ty::Region<'_>, _: ty::BorrowKind, loan_cause: LoanCause) {
+ fn borrow(
+ &mut self,
+ _: NodeId,
+ _: Span,
+ cmt: &cmt_<'tcx>,
+ _: ty::Region<'_>,
+ _: ty::BorrowKind,
+ loan_cause: LoanCause,
+ ) {
if let Categorization::Local(lid) = cmt.cat {
match loan_cause {
// x.foo()
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc::ty;
-use crate::rustc::hir::*;
-use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then};
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
+use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then};
pub struct EtaPass;
-
/// **What it does:** Checks for closures which just call another function where
/// the function can be called directly. `unsafe` functions or calls where types
/// get adjusted are ignored.
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaPass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
match expr.node {
- ExprKind::Call(_, ref args) | ExprKind::MethodCall(_, _, ref args) => for arg in args {
- check_closure(cx, arg)
+ ExprKind::Call(_, ref args) | ExprKind::MethodCall(_, _, ref args) => {
+ for arg in args {
+ check_closure(cx, arg)
+ }
},
_ => (),
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use crate::rustc::hir::*;
-use crate::rustc::ty;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
+use crate::rustc::ty;
use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
use crate::syntax::ast;
use crate::utils::{get_parent_expr, span_lint, span_note_and_lint};
+use if_chain::if_chain;
/// **What it does:** Checks for a read and a write to the same variable where
/// whether the read occurs before or after the write depends on the evaluation
/// **Example:**
/// ```rust
/// let mut x = 0;
-/// let a = {x = 1; 1} + x;
+/// let a = {
+/// x = 1;
+/// 1
+/// } + x;
/// // Unclear whether a is 1 or 2.
/// ```
declare_clippy_lint! {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
// Find a write to a local variable.
match expr.node {
- ExprKind::Assign(ref lhs, _) | ExprKind::AssignOp(_, ref lhs, _) => if let ExprKind::Path(ref qpath) = lhs.node {
- if let QPath::Resolved(_, ref path) = *qpath {
- if path.segments.len() == 1 {
- if let def::Def::Local(var) = cx.tables.qpath_def(qpath, lhs.hir_id) {
- let mut visitor = ReadVisitor {
- cx,
- var,
- write_expr: expr,
- last_expr: expr,
- };
- check_for_unsequenced_reads(&mut visitor);
+ ExprKind::Assign(ref lhs, _) | ExprKind::AssignOp(_, ref lhs, _) => {
+ if let ExprKind::Path(ref qpath) = lhs.node {
+ if let QPath::Resolved(_, ref path) = *qpath {
+ if path.segments.len() == 1 {
+ if let def::Def::Local(var) = cx.tables.qpath_def(qpath, lhs.hir_id) {
+ let mut visitor = ReadVisitor {
+ cx,
+ var,
+ write_expr: expr,
+ last_expr: expr,
+ };
+ check_for_unsequenced_reads(&mut visitor);
+ }
}
}
}
fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) {
match stmt.node {
StmtKind::Expr(ref e, _) | StmtKind::Semi(ref e, _) => DivergenceVisitor { cx }.maybe_walk_expr(e),
- StmtKind::Decl(ref d, _) => if let DeclKind::Local(ref local) = d.node {
- if let Local {
- init: Some(ref e), ..
- } = **local
- {
- DivergenceVisitor { cx }.visit_expr(e);
+ StmtKind::Decl(ref d, _) => {
+ if let DeclKind::Local(ref local) = d.node {
+ if let Local { init: Some(ref e), .. } = **local {
+ DivergenceVisitor { cx }.visit_expr(e);
+ }
}
},
}
/// This means reads for which there is a common ancestor between the read and
/// the write such that
///
-/// * evaluating the ancestor necessarily evaluates both the read and the write
-/// (for example, `&x` and `|| x = 1` don't necessarily evaluate `x`), and
+/// * evaluating the ancestor necessarily evaluates both the read and the write (for example, `&x`
+/// and `|| x = 1` don't necessarily evaluate `x`), and
///
-/// * which one is evaluated first depends on the order of sub-expression
-/// evaluation. Blocks, `if`s, loops, `match`es, and the short-circuiting
-/// logical operators are considered to have a defined evaluation order.
+/// * which one is evaluated first depends on the order of sub-expression evaluation. Blocks, `if`s,
+/// loops, `match`es, and the short-circuiting logical operators are considered to have a defined
+/// evaluation order.
///
/// When such a read is found, the lint is triggered.
fn check_for_unsequenced_reads(vis: &mut ReadVisitor<'_, '_>) {
}
match expr.node {
- ExprKind::Array(_) |
- ExprKind::Tup(_) |
- ExprKind::MethodCall(..) |
- ExprKind::Call(_, _) |
- ExprKind::Assign(_, _) |
- ExprKind::Index(_, _) |
- ExprKind::Repeat(_, _) |
- ExprKind::Struct(_, _, _) => {
+ ExprKind::Array(_)
+ | ExprKind::Tup(_)
+ | ExprKind::MethodCall(..)
+ | ExprKind::Call(_, _)
+ | ExprKind::Assign(_, _)
+ | ExprKind::Index(_, _)
+ | ExprKind::Repeat(_, _)
+ | ExprKind::Struct(_, _, _) => {
walk_expr(vis, expr);
},
ExprKind::Binary(op, _, _) | ExprKind::AssignOp(op, _, _) => {
ExprKind::Closure(_, _, _, _, _) => {
// Either
//
- // * `var` is defined in the closure body, in which case we've
- // reached the top of the enclosing function and can stop, or
+ // * `var` is defined in the closure body, in which case we've reached the top of the enclosing
+ // function and can stop, or
//
- // * `var` is captured by the closure, in which case, because
- // evaluating a closure does not evaluate its body, we don't
- // necessarily have a write, so we need to stop to avoid
- // generating false positives.
+ // * `var` is captured by the closure, in which case, because evaluating a closure does not evaluate
+ // its body, we don't necessarily have a write, so we need to stop to avoid generating false
+ // positives.
//
// This is also the only place we need to stop early (grrr).
return StopEarly::Stop;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::ty::TyKind;
///
/// ```rust
/// // Bad
-/// let v: f32 = 0.123_456_789_9;
-/// println!("{}", v); // 0.123_456_789
+/// let v: f32 = 0.123_456_789_9;
+/// println!("{}", v); // 0.123_456_789
///
/// // Good
-/// let v: f64 = 0.123_456_789_9;
-/// println!("{}", v); // 0.123_456_789_9
+/// let v: f64 = 0.123_456_789_9;
+/// println!("{}", v); // 0.123_456_789_9
/// ```
declare_clippy_lint! {
pub EXCESSIVE_PRECISION,
let max = max_digits(fty);
let sym_str = sym.as_str();
if dot_zero_exclusion(&sym_str) {
- return None
+ return None;
}
// Try to bail out if the float is for sure fine.
// If its within the 2 decimal digits of being out of precision we
/// Ex 1_000_000_000.
fn dot_zero_exclusion(s: &str) -> bool {
if let Some(after_dec) = s.split('.').nth(1) {
- let mut decpart = after_dec
- .chars()
- .take_while(|c| *c != 'e' || *c != 'E');
+ let mut decpart = after_dec.chars().take_while(|c| *c != 'e' || *c != 'E');
match decpart.next() {
Some('0') => decpart.count() == 0,
.unwrap_or(FloatFormat::Normal)
}
fn format<T>(&self, f: T) -> String
- where T: fmt::UpperExp + fmt::LowerExp + fmt::Display {
+ where
+ T: fmt::UpperExp + fmt::LowerExp + fmt::Display,
+ {
match self {
FloatFormat::LowerExp => format!("{:e}", f),
FloatFormat::UpperExp => format!("{:E}", f),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
-use crate::utils::{is_expn_of, match_def_path, resolve_node, span_lint};
use crate::utils::opt_def_id;
+use crate::utils::{is_expn_of, match_def_path, resolve_node, span_lint};
+use if_chain::if_chain;
/// **What it does:** Checks for usage of `write!()` / `writeln()!` which can be
/// replaced with `(e)print!()` / `(e)println!()`
declare_clippy_lint! {
pub EXPLICIT_WRITE,
complexity,
- "using the `write!()` family of functions instead of the `print!()` family \
- of functions, when using the latter would work"
+ "using the `write!()` family of functions instead of the `print!()` family of functions, when using the latter would work"
}
#[derive(Copy, Clone, Debug)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
use crate::rustc::hir;
+use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::ty;
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax_pos::Span;
-use crate::utils::{match_def_path, method_chain_args, span_lint_and_then, walk_ptrs_ty, is_expn_of, opt_def_id};
use crate::utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT, OPTION, RESULT};
+use crate::utils::{is_expn_of, match_def_path, method_chain_args, opt_def_id, span_lint_and_then, walk_ptrs_ty};
+use if_chain::if_chain;
/// **What it does:** Checks for impls of `From<..>` that contain `panic!()` or `unwrap()`
///
}
fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_items: &hir::HirVec<hir::ImplItemRef>) {
- use crate::rustc::hir::*;
use crate::rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+ use crate::rustc::hir::*;
struct FindPanicUnwrap<'a, 'tcx: 'a> {
tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
use crate::rustc::ty;
+use crate::rustc::{declare_tool_lint, lint_array};
+use crate::rustc_errors::Applicability;
use crate::syntax::ast::LitKind;
use crate::utils::paths;
-use crate::utils::{in_macro, is_expn_of, last_path_segment, match_def_path, match_type, opt_def_id, resolve_node, snippet, span_lint_and_then, walk_ptrs_ty};
-use crate::rustc_errors::Applicability;
+use crate::utils::{
+ in_macro, is_expn_of, last_path_segment, match_def_path, match_type, opt_def_id, resolve_node, snippet,
+ span_lint_and_then, walk_ptrs_ty,
+};
+use if_chain::if_chain;
/// **What it does:** Checks for the use of `format!("string literal with no
/// argument")` and `format!("{}", foo)` where `foo` is a string.
}
},
// `format!("foo")` expansion contains `match () { () => [], }`
- ExprKind::Match(ref matchee, _, _) => if let ExprKind::Tup(ref tup) = matchee.node {
- if tup.is_empty() {
- let sugg = format!("{}.to_string()", snippet(cx, expr.span, "<expr>").into_owned());
- span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| {
- db.span_suggestion_with_applicability(
- span,
- "consider using .to_string()",
- sugg,
- Applicability::MachineApplicable, // snippet
- );
- });
+ ExprKind::Match(ref matchee, _, _) => {
+ if let ExprKind::Tup(ref tup) = matchee.node {
+ if tup.is_empty() {
+ let sugg = format!("{}.to_string()", snippet(cx, expr.span, "<expr>").into_owned());
+ span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |db| {
+ db.span_suggestion_with_applicability(
+ span,
+ "consider using .to_string()",
+ sugg,
+ Applicability::MachineApplicable, // snippet
+ );
+ });
+ }
}
},
_ => (),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast;
-use crate::utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint};
use crate::syntax::ptr::P;
+use crate::utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint};
/// **What it does:** Checks for use of the non-existent `=*`, `=!` and `=-`
/// operators.
"possible missing comma in array"
}
-
#[derive(Copy, Clone)]
pub struct Formatting;
fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) {
for w in block.stmts.windows(2) {
match (&w[0].node, &w[1].node) {
- (&ast::StmtKind::Expr(ref first), &ast::StmtKind::Expr(ref second)) |
- (&ast::StmtKind::Expr(ref first), &ast::StmtKind::Semi(ref second)) => {
+ (&ast::StmtKind::Expr(ref first), &ast::StmtKind::Expr(ref second))
+ | (&ast::StmtKind::Expr(ref first), &ast::StmtKind::Semi(ref second)) => {
check_consecutive_ifs(cx, first, second);
},
_ => (),
// the snippet should look like " else \n " with maybe comments anywhere
// it’s bad when there is a ‘\n’ after the “else”
if let Some(else_snippet) = snippet_opt(cx, else_span) {
- let else_pos = else_snippet
- .find("else")
- .expect("there must be a `else` here");
+ let else_pos = else_snippet.find("else").expect("there must be a `else` here");
if else_snippet[else_pos..].contains('\n') {
span_note_and_lint(
fn has_unary_equivalent(bin_op: ast::BinOpKind) -> bool {
// &, *, -
- bin_op == ast::BinOpKind::And
- || bin_op == ast::BinOpKind::Mul
- || bin_op == ast::BinOpKind::Sub
+ bin_op == ast::BinOpKind::And || bin_op == ast::BinOpKind::Mul || bin_op == ast::BinOpKind::Sub
}
/// Implementation of the `POSSIBLE_MISSING_COMMA` lint for array
/// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for consecutive ifs.
fn check_consecutive_ifs(cx: &EarlyContext<'_>, first: &ast::Expr, second: &ast::Expr) {
- if !differing_macro_contexts(first.span, second.span) && !in_macro(first.span) && unsugar_if(first).is_some()
+ if !differing_macro_contexts(first.span, second.span)
+ && !in_macro(first.span)
+ && unsugar_if(first).is_some()
&& unsugar_if(second).is_some()
{
// where the else would be
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use matches::matches;
-use crate::rustc::hir::intravisit;
use crate::rustc::hir;
+use crate::rustc::hir::def::Def;
+use crate::rustc::hir::intravisit;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc::ty;
-use crate::rustc::hir::def::Def;
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_data_structures::fx::FxHashSet;
-use crate::syntax::ast;
use crate::rustc_target::spec::abi::Abi;
+use crate::syntax::ast;
use crate::syntax::source_map::Span;
use crate::utils::{iter_input_pats, span_lint, type_is_unsafe_function};
+use matches::matches;
/// **What it does:** Checks for functions with too many parameters.
///
///
/// **Example:**
/// ```rust
-/// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b:
-/// f32) { .. }
+/// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) {
+/// ..
+/// }
/// ```
declare_clippy_lint! {
pub TOO_MANY_ARGUMENTS,
///
/// **Example:**
/// ```rust
-/// pub fn foo(x: *const u8) { println!("{}", unsafe { *x }); }
+/// pub fn foo(x: *const u8) {
+/// println!("{}", unsafe { *x });
+/// }
/// ```
declare_clippy_lint! {
pub NOT_UNSAFE_PTR_ARG_DEREF,
impl Functions {
pub fn new(threshold: u64) -> Self {
- Self {
- threshold,
- }
+ Self { threshold }
}
}
if !is_impl {
// don't lint extern functions decls, it's not their fault either
match kind {
- hir::intravisit::FnKind::Method(_, &hir::MethodSig { header: hir::FnHeader { abi: Abi::Rust, .. }, .. }, _, _) |
- hir::intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _, _) => self.check_arg_number(cx, decl, span),
+ hir::intravisit::FnKind::Method(
+ _,
+ &hir::MethodSig {
+ header: hir::FnHeader { abi: Abi::Rust, .. },
+ ..
+ },
+ _,
+ _,
+ )
+ | hir::intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _, _) => {
+ self.check_arg_number(cx, decl, span)
+ },
_ => {},
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use crate::rustc::hir::*;
+use crate::rustc_errors::Applicability;
use crate::syntax::ast::NodeId;
-use crate::utils::{in_macro, match_def_path, match_trait_method, same_tys, snippet, snippet_with_macro_callsite, span_lint_and_then};
+use crate::utils::{
+ in_macro, match_def_path, match_trait_method, same_tys, snippet, snippet_with_macro_callsite, span_lint_and_then,
+};
use crate::utils::{opt_def_id, paths, resolve_node};
-use crate::rustc_errors::Applicability;
/// **What it does:** Checks for always-identical `Into`/`From`/`IntoIter` conversions.
///
}
},
- ExprKind::Call(ref path, ref args) => if let ExprKind::Path(ref qpath) = path.node {
- if let Some(def_id) = opt_def_id(resolve_node(cx, qpath, path.hir_id)) {
- if match_def_path(cx.tcx, def_id, &paths::FROM_FROM[..]) {
- let a = cx.tables.expr_ty(e);
- let b = cx.tables.expr_ty(&args[0]);
- if same_tys(cx, a, b) {
- let sugg = snippet(cx, args[0].span.source_callsite(), "<expr>").into_owned();
- let sugg_msg = format!("consider removing `{}()`", snippet(cx, path.span, "From::from"));
- span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| {
- db.span_suggestion_with_applicability(
- e.span,
- &sugg_msg,
- sugg,
- Applicability::MachineApplicable, // snippet
- );
- });
+ ExprKind::Call(ref path, ref args) => {
+ if let ExprKind::Path(ref qpath) = path.node {
+ if let Some(def_id) = opt_def_id(resolve_node(cx, qpath, path.hir_id)) {
+ if match_def_path(cx.tcx, def_id, &paths::FROM_FROM[..]) {
+ let a = cx.tables.expr_ty(e);
+ let b = cx.tables.expr_ty(&args[0]);
+ if same_tys(cx, a, b) {
+ let sugg = snippet(cx, args[0].span.source_callsite(), "<expr>").into_owned();
+ let sugg_msg =
+ format!("consider removing `{}()`", snippet(cx, path.span, "From::from"));
+ span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| {
+ db.span_suggestion_with_applicability(
+ e.span,
+ &sugg_msg,
+ sugg,
+ Applicability::MachineApplicable, // snippet
+ );
+ });
+ }
}
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::consts::{constant_simple, Constant};
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
+use crate::rustc::ty;
use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::source_map::Span;
-use crate::utils::{in_macro, snippet, span_lint, unsext, clip};
-use crate::rustc::ty;
+use crate::utils::{clip, in_macro, snippet, span_lint, unsext};
/// **What it does:** Checks for identity operations, e.g. `x + 0`.
///
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! lint on if branches that could be swapped so no `!` operation is necessary
//! on the condition
-use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_external_macro, LintContext};
+use crate::rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast::*;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! lint on indexing and slicing operations
use crate::consts::{constant, Constant};
-use crate::utils;
-use crate::utils::higher;
-use crate::utils::higher::Range;
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc::ty;
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast::RangeLimits;
+use crate::utils;
+use crate::utils::higher;
+use crate::utils::higher::Range;
/// **What it does:** Checks for out of bounds array indexing with a constant
/// index.
///
/// **Example:**
/// ```rust
-/// let x = [1,2,3,4];
+/// let x = [1, 2, 3, 4];
///
/// // Bad
/// x[9];
if let ExprKind::Index(ref array, ref index) = &expr.node {
let ty = cx.tables.expr_ty(array);
if let Some(range) = higher::range(cx, index) {
-
// Ranged indexes, i.e. &x[n..m], &x[n..], &x[..n] and &x[..]
if let ty::Array(_, s) = ty.sty {
let size: u128 = s.assert_usize(cx.tcx).unwrap().into();
(None, None) => return, // [..] is ok.
};
- utils::span_help_and_lint(
- cx,
- INDEXING_SLICING,
- expr.span,
- "slicing may panic.",
- help_msg,
- );
+ utils::span_help_and_lint(cx, INDEXING_SLICING, expr.span, "slicing may panic.", help_msg);
} else {
// Catchall non-range index, i.e. [n] or [n << m]
if let ty::Array(..) = ty.sty {
range: Range<'_>,
array_size: u128,
) -> (Option<u128>, Option<u128>) {
- let s = range
- .start
- .map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c));
+ let s = range.start.map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c));
let start = match s {
Some(Some(Constant::Int(x))) => Some(x),
Some(_) => None,
None => Some(0),
};
- let e = range
- .end
- .map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c));
+ let e = range.end.map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c));
let end = match e {
- Some(Some(Constant::Int(x))) => if range.limits == RangeLimits::Closed {
- Some(x + 1)
- } else {
- Some(x)
+ Some(Some(Constant::Int(x))) => {
+ if range.limits == RangeLimits::Closed {
+ Some(x + 1)
+ } else {
+ Some(x)
+ }
},
Some(_) => None,
None => Some(array_size),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use super::utils::{get_arg_name, match_var, remove_blocks, snippet_with_applicability, span_lint_and_sugg};
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
First => is_infinite(cx, &args[0]),
Any => is_infinite(cx, &args[0]).or(is_infinite(cx, &args[1])),
All => is_infinite(cx, &args[0]).and(is_infinite(cx, &args[1])),
- }).and(cap);
+ })
+ .and(cap);
}
}
if method.ident.name == "flat_map" && args.len() == 2 {
},
ExprKind::Block(ref block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)),
ExprKind::Box(ref e) | ExprKind::AddrOf(_, ref e) => is_infinite(cx, e),
- ExprKind::Call(ref path, _) => if let ExprKind::Path(ref qpath) = path.node {
- match_qpath(qpath, &paths::REPEAT).into()
- } else {
- Finite
+ ExprKind::Call(ref path, _) => {
+ if let ExprKind::Path(ref qpath) = path.node {
+ match_qpath(qpath, &paths::REPEAT).into()
+ } else {
+ Finite
+ }
},
- ExprKind::Struct(..) => higher::range(cx, expr)
- .map_or(false, |r| r.end.is_none())
- .into(),
+ ExprKind::Struct(..) => higher::range(cx, expr).map_or(false, |r| r.end.is_none()).into(),
_ => Finite,
}
}
}
}
},
- ExprKind::Binary(op, ref l, ref r) => if op.node.is_comparison() {
- return is_infinite(cx, l)
- .and(is_infinite(cx, r))
- .and(MaybeInfinite);
+ ExprKind::Binary(op, ref l, ref r) => {
+ if op.node.is_comparison() {
+ return is_infinite(cx, l).and(is_infinite(cx, r)).and(MaybeInfinite);
+ }
}, // TODO: ExprKind::Loop + Match
_ => (),
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! lint on inherent implementations
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_data_structures::fx::FxHashMap;
-use std::default::Default;
use crate::syntax_pos::Span;
use crate::utils::span_lint_and_then;
+use std::default::Default;
/// **What it does:** Checks for multiple inherent implementations of a struct
///
impl Default for Pass {
fn default() -> Self {
- Self { impls: FxHashMap::default() }
+ Self {
+ impls: FxHashMap::default(),
+ }
}
}
let mut impl_spans = impls
.iter()
.filter_map(|impl_def| self.impls.get(impl_def))
- .filter_map(|(span, generics)| if generics.params.len() == 0 {
- Some(span)
- } else {
- None
- });
+ .filter_map(|(span, generics)| if generics.params.len() == 0 { Some(span) } else { None });
if let Some(initial_span) = impl_spans.nth(0) {
impl_spans.for_each(|additional_span| {
span_lint_and_then(
*additional_span,
"Multiple implementations of this structure",
|db| {
- db.span_note(
- *initial_span,
- "First implementation here",
- );
+ db.span_note(*initial_span, "First implementation here");
},
)
})
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! checks for `#[inline]` on trait methods without bodies
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use crate::rustc::hir::*;
+use crate::rustc_errors::Applicability;
use crate::syntax::ast::{Attribute, Name};
use crate::utils::span_lint_and_then;
use crate::utils::sugg::DiagnosticBuilderExt;
-use crate::rustc_errors::Applicability;
/// **What it does:** Checks for `#[inline]` on trait methods without bodies
///
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! lint on blocks unnecessarily using >= with a + 1 or - 1
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
}
fn emit_warning(&self, cx: &EarlyContext<'_>, block: &Expr, recommendation: String) {
- span_lint_and_then(cx, INT_PLUS_ONE, block.span, "Unnecessary `>= y + 1` or `x - 1 >=`", |db| {
- db.span_suggestion_with_applicability(
- block.span,
- "change `>= y + 1` to `> y` as shown",
- recommendation,
- Applicability::MachineApplicable, // snippet
- );
- });
+ span_lint_and_then(
+ cx,
+ INT_PLUS_ONE,
+ block.span,
+ "Unnecessary `>= y + 1` or `x - 1 >=`",
+ |db| {
+ db.span_suggestion_with_applicability(
+ block.span,
+ "change `>= y + 1` to `> y` as shown",
+ recommendation,
+ Applicability::MachineApplicable, // snippet
+ );
+ },
+ );
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
use crate::rustc::ty;
-use crate::rustc::hir::*;
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::utils::{match_def_path, opt_def_id, paths, span_help_and_lint};
+use if_chain::if_chain;
/// **What it does:** Checks for creation of references to zeroed or uninitialized memory.
///
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! lint when items are used after statements
-use matches::matches;
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast::*;
use crate::utils::{in_macro, span_lint};
+use matches::matches;
/// **What it does:** Checks for items declared after some statement in a block.
///
}
// skip initial items
- let stmts = item.stmts
+ let stmts = item
+ .stmts
.iter()
.map(|stmt| &stmt.node)
.skip_while(|s| matches!(**s, StmtKind::Item(..)));
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! lint when there is a large size difference between variants on an enum
-use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc::hir::*;
-use crate::utils::{snippet_opt, span_lint_and_then};
+use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::ty::layout::LayoutOf;
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
+use crate::utils::{snippet_opt, span_lint_and_then};
/// **What it does:** Checks for large size differences between variants on
/// `enum`s.
/// **Example:**
/// ```rust
/// enum Test {
-/// A(i32),
-/// B([i32; 8000]),
+/// A(i32),
+/// B([i32; 8000]),
/// }
/// ```
declare_clippy_lint! {
let did = cx.tcx.hir.local_def_id(item.id);
if let ItemKind::Enum(ref def, _) = item.node {
let ty = cx.tcx.type_of(did);
- let adt = ty.ty_adt_def()
- .expect("already checked whether this is an enum");
+ 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;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir::def_id::DefId;
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
///
/// **Example:**
/// ```rust
-/// if x.len() == 0 { .. }
-/// if y.len() != 0 { .. }
+/// if x.len() == 0 {
+/// ..
+/// }
+/// if y.len() != 0 {
+/// ..
+/// }
/// ```
/// instead use
/// ```rust
-/// if x.len().is_empty() { .. }
-/// if !y.len().is_empty() { .. }
+/// if x.len().is_empty() {
+/// ..
+/// }
+/// if !y.len().is_empty() {
+/// ..
+/// }
/// ```
declare_clippy_lint! {
- pub LEN_ZERO,
- style,
- "checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` \
- could be used instead"
+pub LEN_ZERO,
+style,
+"checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` \
+ could be used instead"
}
/// **What it does:** Checks for items that implement `.len()` but not
/// **Example:**
/// ```rust
/// impl X {
-/// pub fn len(&self) -> usize { .. }
+/// pub fn len(&self) -> usize {
+/// ..
+/// }
/// }
/// ```
declare_clippy_lint! {
fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items: &[TraitItemRef]) {
fn is_named_self(cx: &LateContext<'_, '_>, item: &TraitItemRef, name: &str) -> bool {
- item.ident.name == name && if let AssociatedItemKind::Method { has_self } = item.kind {
- has_self && {
- let did = cx.tcx.hir.local_def_id(item.id.node_id);
- cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1
+ item.ident.name == name
+ && if let AssociatedItemKind::Method { has_self } = item.kind {
+ has_self && {
+ let did = cx.tcx.hir.local_def_id(item.id.node_id);
+ cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1
+ }
+ } else {
+ false
}
- } else {
- false
- }
}
// fill the set with current and super traits
.iter()
.flat_map(|&i| cx.tcx.associated_items(i))
.any(|i| {
- i.kind == ty::AssociatedKind::Method && i.method_has_self_argument && i.ident.name == "is_empty"
+ i.kind == ty::AssociatedKind::Method
+ && i.method_has_self_argument
+ && i.ident.name == "is_empty"
&& cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1
});
fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item, impl_items: &[ImplItemRef]) {
fn is_named_self(cx: &LateContext<'_, '_>, item: &ImplItemRef, name: &str) -> bool {
- item.ident.name == name && if let AssociatedItemKind::Method { has_self } = item.kind {
- has_self && {
- let did = cx.tcx.hir.local_def_id(item.id.node_id);
- cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1
+ item.ident.name == name
+ && if let AssociatedItemKind::Method { has_self } = item.kind {
+ has_self && {
+ let did = cx.tcx.hir.local_def_id(item.id.node_id);
+ cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1
+ }
+ } else {
+ false
}
- } else {
- false
- }
}
let is_empty = if let Some(is_empty) = impl_items.iter().find(|i| is_named_self(cx, i, "is_empty")) {
span,
&format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }),
"using `is_empty` is clearer and more explicit",
- format!("{}{}.is_empty()", op, snippet_with_applicability(cx, args[0].span, "_", &mut applicability)),
+ format!(
+ "{}{}.is_empty()",
+ op,
+ snippet_with_applicability(cx, args[0].span, "_", &mut applicability)
+ ),
applicability,
);
}
/// Check the inherent impl's items for an `is_empty(self)` method.
fn has_is_empty_impl(cx: &LateContext<'_, '_>, id: DefId) -> bool {
- cx.tcx.inherent_impls(id).iter().any(|imp| {
- cx.tcx
- .associated_items(*imp)
- .any(|item| is_is_empty(cx, &item))
- })
+ cx.tcx
+ .inherent_impls(id)
+ .iter()
+ .any(|imp| cx.tcx.associated_items(*imp).any(|item| is_is_empty(cx, &item)))
}
let ty = &walk_ptrs_ty(cx.tables.expr_ty(expr));
match ty.sty {
- ty::Dynamic(ref tt, ..) => cx.tcx
+ ty::Dynamic(ref tt, ..) => cx
+ .tcx
.associated_items(tt.principal().def_id())
.any(|item| is_is_empty(cx, &item)),
ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
use crate::rustc::hir;
-use crate::rustc::hir::BindingAnnotation;
use crate::rustc::hir::def::Def;
+use crate::rustc::hir::BindingAnnotation;
+use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
+use crate::rustc::{declare_tool_lint, lint_array};
+use crate::rustc_errors::Applicability;
use crate::syntax::ast;
use crate::utils::{snippet, span_lint_and_then};
-use crate::rustc_errors::Applicability;
+use if_chain::if_chain;
/// **What it does:** Checks for variable declarations immediately followed by a
/// conditional affectation.
}
fn used_in_expr<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, id: ast::NodeId, expr: &'tcx hir::Expr) -> bool {
- let mut v = UsedVisitor {
- cx,
- id,
- used: false,
- };
+ let mut v = UsedVisitor { cx, id, used: false };
hir::intravisit::walk_expr(&mut v, expr);
v.used
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
// error-pattern:cargo-clippy
#![feature(box_syntax)]
#![allow(clippy::missing_docs_in_private_items)]
#![recursion_limit = "256"]
#![feature(macro_at_most_once_rep)]
-
#![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)]
#![feature(crate_visibility_modifier)]
#![feature(try_from)]
crate use crate::syntax::ast::{Name, NodeId};
}
-pub fn register_pre_expansion_lints(session: &rustc::session::Session, store: &mut rustc::lint::LintStore, conf: &Conf) {
+pub fn register_pre_expansion_lints(
+ session: &rustc::session::Session,
+ store: &mut rustc::lint::LintStore,
+ conf: &Conf,
+) {
store.register_pre_expansion_pass(Some(session), box write::Pass);
store.register_pre_expansion_pass(Some(session), box redundant_field_names::RedundantFieldNames);
- store.register_pre_expansion_pass(Some(session), box non_expressive_names::NonExpressiveNames {
- single_char_binding_names_threshold: conf.single_char_binding_names_threshold,
- });
+ store.register_pre_expansion_pass(
+ Some(session),
+ box non_expressive_names::NonExpressiveNames {
+ single_char_binding_names_threshold: conf.single_char_binding_names_threshold,
+ },
+ );
store.register_pre_expansion_pass(Some(session), box attrs::CfgAttrPass);
}
match utils::conf::lookup_conf_file() {
Ok(path) => path,
Err(error) => {
- reg.sess.struct_err(&format!("error finding Clippy's configuration file: {}", error)).emit();
+ reg.sess
+ .struct_err(&format!("error finding Clippy's configuration file: {}", error))
+ .emit();
None
- }
+ },
}
};
- let file_name = file_name.map(|file_name| if file_name.is_relative() {
- reg.sess
- .local_crate_source_file
- .as_ref()
- .and_then(|file| std::path::Path::new(&file).parent().map(std::path::Path::to_path_buf))
- .unwrap_or_default()
- .join(file_name)
- } else {
- file_name
+ let file_name = file_name.map(|file_name| {
+ if file_name.is_relative() {
+ reg.sess
+ .local_crate_source_file
+ .as_ref()
+ .and_then(|file| std::path::Path::new(&file).parent().map(std::path::Path::to_path_buf))
+ .unwrap_or_default()
+ .join(file_name)
+ } else {
+ file_name
+ }
});
let (conf, errors) = utils::conf::read(file_name.as_ref().map(|p| p.as_ref()));
// all conf errors are non-fatal, we just use the default conf in case of error
for error in errors {
- reg.sess.struct_err(&format!("error reading Clippy's configuration file `{}`: {}", file_name.as_ref().and_then(|p| p.to_str()).unwrap_or(""), error)).emit();
+ reg.sess
+ .struct_err(&format!(
+ "error reading Clippy's configuration file `{}`: {}",
+ file_name.as_ref().and_then(|p| p.to_str()).unwrap_or(""),
+ error
+ ))
+ .emit();
}
conf
- }
+ },
Err((err, span)) => {
- reg.sess.struct_span_err(span, err)
- .span_note(span, "Clippy will use default configuration")
- .emit();
+ reg.sess
+ .struct_span_err(span, err)
+ .span_note(span, "Clippy will use default configuration")
+ .emit();
toml::from_str("").expect("we never error on empty config files")
- }
+ },
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::reexport::*;
-use matches::matches;
-use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext};
-use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc::hir::def::Def;
-use crate::rustc::hir::*;
use crate::rustc::hir::intravisit::*;
+use crate::rustc::hir::*;
+use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet};
use crate::syntax::source_map::Span;
-use crate::utils::{last_path_segment, span_lint};
use crate::syntax::symbol::keywords;
+use crate::utils::{last_path_segment, span_lint};
+use matches::matches;
/// **What it does:** Checks for lifetime annotations which can be removed by
/// relying on lifetime elision.
///
/// **Example:**
/// ```rust
-/// fn in_and_out<'a>(x: &'a u8, y: u8) -> &'a u8 { x }
+/// fn in_and_out<'a>(x: &'a u8, y: u8) -> &'a u8 {
+/// x
+/// }
/// ```
declare_clippy_lint! {
- pub NEEDLESS_LIFETIMES,
- complexity,
- "using explicit lifetimes for references in function arguments when elision rules \
- would allow omitting them"
+pub NEEDLESS_LIFETIMES,
+complexity,
+"using explicit lifetimes for references in function arguments when elision rules \
+ would allow omitting them"
}
/// **What it does:** Checks for lifetimes in generics that are never used
///
/// **Example:**
/// ```rust
-/// fn unused_lifetime<'a>(x: u8) { .. }
+/// fn unused_lifetime<'a>(x: u8) {
+/// ..
+/// }
/// ```
declare_clippy_lint! {
pub EXTRA_UNUSED_LIFETIMES,
cx,
NEEDLESS_LIFETIMES,
span,
- "explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)",
+ "explicit lifetimes given in parameter types where they could be elided \
+ (or replaced with `'_` if needed by type declaration)",
);
}
report_extra_lifetimes(cx, decl, generics);
// no output lifetimes, check distinctness of input lifetimes
// only unnamed and static, ok
- let unnamed_and_static = input_lts
- .iter()
- .all(|lt| *lt == RefLt::Unnamed || *lt == RefLt::Static);
+ let unnamed_and_static = input_lts.iter().all(|lt| *lt == RefLt::Unnamed || *lt == RefLt::Static);
if unnamed_and_static {
return false;
}
&& !last_path_segment.args.iter().any(|arg| match arg {
GenericArg::Lifetime(_) => true,
GenericArg::Type(_) => false,
- }) {
+ })
+ {
let hir_id = self.cx.tcx.hir.node_to_hir_id(ty.id);
match self.cx.tables.qpath_def(qpath, hir_id) {
Def::TyAlias(def_id) | Def::Struct(def_id) => {
self.record(&None);
},
TyKind::Path(ref path) => {
-
self.collect_anonymous_lifetimes(path, ty);
- }
+ },
TyKind::Def(item, _) => {
if let ItemKind::Existential(ref exist_ty) = self.cx.tcx.hir.expect_item(item.id).node {
for bound in &exist_ty.bounds {
unreachable!()
}
walk_ty(self, ty);
- }
+ },
TyKind::TraitObject(ref bounds, ref lt) => {
if !lt.is_elided() {
self.abort = true;
// and check that all lifetimes are allowed
match visitor.into_vec() {
None => return false,
- Some(lts) => for lt in lts {
- if !allowed_lts.contains(<) {
- return true;
+ Some(lts) => {
+ for lt in lts {
+ if !allowed_lts.contains(<) {
+ return true;
+ }
}
},
}
}
fn report_extra_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, func: &'tcx FnDecl, generics: &'tcx Generics) {
- let hs = generics.params.iter()
+ let hs = generics
+ .params
+ .iter()
.filter_map(|par| match par.kind {
GenericParamKind::Lifetime { .. } => Some((par.name.ident().name, par.span)),
_ => None,
walk_fn_decl(&mut checker, func);
for &v in checker.map.values() {
- span_lint(cx, EXTRA_UNUSED_LIFETIMES, v, "this lifetime isn't used in the function definition");
+ span_lint(
+ cx,
+ EXTRA_UNUSED_LIFETIMES,
+ v,
+ "this lifetime isn't used in the function definition",
+ );
}
}
parts[0].len(),
parts[1].len());
if !consistent {
- WarningType::InconsistentDigitGrouping.display(&digit_info.grouping_hint(),
- cx,
- lit.span);
+ WarningType::InconsistentDigitGrouping.display(
+ &digit_info.grouping_hint(),
+ cx,
+ lit.span,
+ );
}
})
.map_err(|warning_type| warning_type.display(&digit_info.grouping_hint(),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use itertools::Itertools;
use crate::reexport::*;
-use crate::rustc::hir::*;
use crate::rustc::hir::def::Def;
use crate::rustc::hir::def_id;
use crate::rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor};
-use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext};
+use crate::rustc::hir::*;
+use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
+use crate::rustc::middle::region;
use crate::rustc::{declare_tool_lint, lint_array};
use if_chain::if_chain;
-use crate::rustc::middle::region;
+use itertools::Itertools;
// use crate::rustc::middle::region::CodeExtent;
+use crate::consts::{constant, Constant};
use crate::rustc::middle::expr_use_visitor::*;
-use crate::rustc::middle::mem_categorization::Categorization;
use crate::rustc::middle::mem_categorization::cmt_;
-use crate::rustc::ty::{self, Ty};
+use crate::rustc::middle::mem_categorization::Categorization;
use crate::rustc::ty::subst::Subst;
-use crate::rustc_errors::Applicability;
+use crate::rustc::ty::{self, Ty};
use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use std::iter::{once, Iterator};
-use std::mem;
+use crate::rustc_errors::Applicability;
use crate::syntax::ast;
use crate::syntax::source_map::Span;
use crate::syntax_pos::BytePos;
-use crate::utils::{in_macro, sugg, sext};
use crate::utils::usage::mutated_variables;
-use crate::consts::{constant, Constant};
+use crate::utils::{in_macro, sext, sugg};
+use std::iter::{once, Iterator};
+use std::mem;
use crate::utils::paths;
use crate::utils::{
/// **Example:**
/// ```rust
/// // with `y` a `Vec` or slice:
-/// for x in y.iter() { .. }
+/// for x in y.iter() {
+/// ..
+/// }
/// ```
/// can be rewritten to
/// ```rust
-/// for x in &y { .. }
+/// for x in &y {
+/// ..
+/// }
/// ```
declare_clippy_lint! {
pub EXPLICIT_ITER_LOOP,
/// **Example:**
/// ```rust
/// // with `y` a `Vec` or slice:
-/// for x in y.into_iter() { .. }
+/// for x in y.into_iter() {
+/// ..
+/// }
/// ```
/// can be rewritten to
/// ```rust
-/// for x in y { .. }
+/// for x in y {
+/// ..
+/// }
/// ```
declare_clippy_lint! {
pub EXPLICIT_INTO_ITER_LOOP,
///
/// **Example:**
/// ```rust
-/// for x in y.next() { .. }
+/// for x in y.next() {
+/// ..
+/// }
/// ```
declare_clippy_lint! {
pub ITER_NEXT_LOOP,
///
/// **Example:**
/// ```rust
-/// for x in option { .. }
+/// for x in option {
+/// ..
+/// }
/// ```
///
/// This should be
/// ```rust
-/// if let Some(x) = option { .. }
+/// if let Some(x) = option {
+/// ..
+/// }
/// ```
declare_clippy_lint! {
pub FOR_LOOP_OVER_OPTION,
///
/// **Example:**
/// ```rust
-/// for x in result { .. }
+/// for x in result {
+/// ..
+/// }
/// ```
///
/// This should be
/// ```rust
-/// if let Ok(x) = result { .. }
+/// if let Ok(x) = result {
+/// ..
+/// }
/// ```
declare_clippy_lint! {
pub FOR_LOOP_OVER_RESULT,
declare_clippy_lint! {
pub UNUSED_COLLECT,
perf,
- "`collect()`ing an iterator without using the result; this is usually better \
- written as a for loop"
+ "`collect()`ing an iterator without using the result; this is usually better written as a for loop"
}
/// **What it does:** Checks for functions collecting an iterator when collect
///
/// **Example:**
/// ```rust
-/// for x in 5..10-5 { .. } // oops, stray `-`
+/// for x in 5..10 - 5 {
+/// ..
+/// } // oops, stray `-`
/// ```
declare_clippy_lint! {
pub REVERSE_RANGE_LOOP,
///
/// **Example:**
/// ```rust
-/// while let Some(val) = iter() { .. }
+/// while let Some(val) = iter() {
+/// ..
+/// }
/// ```
declare_clippy_lint! {
pub WHILE_LET_ON_ITERATOR,
///
/// **Example:**
/// ```rust
-/// for (k, _) in &map { .. }
+/// for (k, _) in &map {
+/// ..
+/// }
/// ```
///
/// could be replaced by
///
/// ```rust
-/// for k in map.keys() { .. }
+/// for k in map.keys() {
+/// ..
+/// }
/// ```
declare_clippy_lint! {
pub FOR_KV_MAP,
///
/// **Example:**
/// ```rust
-/// loop { ..; break; }
+/// loop {
+/// ..;
+/// break;
+/// }
/// ```
declare_clippy_lint! {
pub NEVER_LOOP,
/// ```rust
/// let i = 0;
/// while i > 10 {
-/// println!("let me loop forever!");
+/// println!("let me loop forever!");
/// }
/// ```
declare_clippy_lint! {
match expr.node {
ExprKind::While(_, ref block, _) | ExprKind::Loop(ref block, _, _) => {
match never_loop_block(block, expr.id) {
- NeverLoopResult::AlwaysBreak =>
- span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"),
+ NeverLoopResult::AlwaysBreak => {
+ span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops")
+ },
NeverLoopResult::MayContinueMainLoop | NeverLoopResult::Otherwise => (),
}
},
// ensure "if let" compatible match structure
match *source {
MatchSource::Normal | MatchSource::IfLetDesugar { .. } => {
- if arms.len() == 2 && arms[0].pats.len() == 1 && arms[0].guard.is_none()
- && arms[1].pats.len() == 1 && arms[1].guard.is_none()
+ if arms.len() == 2
+ && arms[0].pats.len() == 1
+ && arms[0].guard.is_none()
+ && arms[1].pats.len() == 1
+ && arms[1].guard.is_none()
&& is_simple_break_expr(&arms[1].body)
{
if in_external_macro(cx.sess(), expr.span) {
{
let iter_expr = &method_args[0];
let lhs_constructor = last_path_segment(qpath);
- if method_path.ident.name == "next" && match_trait_method(cx, match_expr, &paths::ITERATOR)
- && lhs_constructor.ident.name == "Some" && (
- pat_args.is_empty()
+ if method_path.ident.name == "next"
+ && match_trait_method(cx, match_expr, &paths::ITERATOR)
+ && lhs_constructor.ident.name == "Some"
+ && (pat_args.is_empty()
|| !is_refutable(cx, &pat_args[0])
- && !is_iterator_used_after_while_let(cx, iter_expr)
- && !is_nested(cx, expr, &method_args[0]))
+ && !is_iterator_used_after_while_let(cx, iter_expr)
+ && !is_nested(cx, expr, &method_args[0]))
{
let iterator = snippet(cx, method_args[0].span, "_");
let loop_var = if pat_args.is_empty() {
fn absorb_break(arg: &NeverLoopResult) -> NeverLoopResult {
match *arg {
- NeverLoopResult::AlwaysBreak |
- NeverLoopResult::Otherwise => NeverLoopResult::Otherwise,
+ NeverLoopResult::AlwaysBreak | NeverLoopResult::Otherwise => NeverLoopResult::Otherwise,
NeverLoopResult::MayContinueMainLoop => NeverLoopResult::MayContinueMainLoop,
}
}
// Combine two results where both parts are called but not necessarily in order.
fn combine_both(left: NeverLoopResult, right: NeverLoopResult) -> NeverLoopResult {
match (left, right) {
- (NeverLoopResult::MayContinueMainLoop, _) | (_, NeverLoopResult::MayContinueMainLoop) =>
- NeverLoopResult::MayContinueMainLoop,
- (NeverLoopResult::AlwaysBreak, _) | (_, NeverLoopResult::AlwaysBreak) =>
- NeverLoopResult::AlwaysBreak,
- (NeverLoopResult::Otherwise, NeverLoopResult::Otherwise) =>
- NeverLoopResult::Otherwise,
+ (NeverLoopResult::MayContinueMainLoop, _) | (_, NeverLoopResult::MayContinueMainLoop) => {
+ NeverLoopResult::MayContinueMainLoop
+ },
+ (NeverLoopResult::AlwaysBreak, _) | (_, NeverLoopResult::AlwaysBreak) => NeverLoopResult::AlwaysBreak,
+ (NeverLoopResult::Otherwise, NeverLoopResult::Otherwise) => NeverLoopResult::Otherwise,
}
}
// Combine two results where only one of the part may have been executed.
fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult) -> NeverLoopResult {
match (b1, b2) {
- (NeverLoopResult::AlwaysBreak, NeverLoopResult::AlwaysBreak) =>
- NeverLoopResult::AlwaysBreak,
- (NeverLoopResult::MayContinueMainLoop, _) | (_, NeverLoopResult::MayContinueMainLoop) =>
- NeverLoopResult::MayContinueMainLoop,
- (NeverLoopResult::Otherwise, _) | (_, NeverLoopResult::Otherwise) =>
- NeverLoopResult::Otherwise,
+ (NeverLoopResult::AlwaysBreak, NeverLoopResult::AlwaysBreak) => NeverLoopResult::AlwaysBreak,
+ (NeverLoopResult::MayContinueMainLoop, _) | (_, NeverLoopResult::MayContinueMainLoop) => {
+ NeverLoopResult::MayContinueMainLoop
+ },
+ (NeverLoopResult::Otherwise, _) | (_, NeverLoopResult::Otherwise) => NeverLoopResult::Otherwise,
}
}
fn never_loop_expr(expr: &Expr, main_loop_id: NodeId) -> NeverLoopResult {
match expr.node {
- ExprKind::Box(ref e) |
- ExprKind::Unary(_, ref e) |
- ExprKind::Cast(ref e, _) |
- ExprKind::Type(ref e, _) |
- ExprKind::Field(ref e, _) |
- ExprKind::AddrOf(_, ref e) |
- ExprKind::Struct(_, _, Some(ref e)) |
- ExprKind::Repeat(ref e, _) => never_loop_expr(e, main_loop_id),
+ ExprKind::Box(ref e)
+ | ExprKind::Unary(_, ref e)
+ | ExprKind::Cast(ref e, _)
+ | ExprKind::Type(ref e, _)
+ | ExprKind::Field(ref e, _)
+ | ExprKind::AddrOf(_, ref e)
+ | ExprKind::Struct(_, _, Some(ref e))
+ | ExprKind::Repeat(ref e, _) => never_loop_expr(e, main_loop_id),
ExprKind::Array(ref es) | ExprKind::MethodCall(_, _, ref es) | ExprKind::Tup(ref es) => {
never_loop_expr_all(&mut es.iter(), main_loop_id)
},
ExprKind::Call(ref e, ref es) => never_loop_expr_all(&mut once(&**e).chain(es.iter()), main_loop_id),
- ExprKind::Binary(_, ref e1, ref e2) |
- ExprKind::Assign(ref e1, ref e2) |
- ExprKind::AssignOp(_, ref e1, ref e2) |
- ExprKind::Index(ref e1, ref e2) => never_loop_expr_all(&mut [&**e1, &**e2].iter().cloned(), main_loop_id),
+ ExprKind::Binary(_, ref e1, ref e2)
+ | ExprKind::Assign(ref e1, ref e2)
+ | ExprKind::AssignOp(_, ref e1, ref e2)
+ | ExprKind::Index(ref e1, ref e2) => never_loop_expr_all(&mut [&**e1, &**e2].iter().cloned(), main_loop_id),
ExprKind::If(ref e, ref e2, ref e3) => {
let e1 = never_loop_expr(e, main_loop_id);
let e2 = never_loop_expr(e2, main_loop_id);
- let e3 = e3.as_ref().map_or(NeverLoopResult::Otherwise, |e| never_loop_expr(e, main_loop_id));
+ let e3 = e3
+ .as_ref()
+ .map_or(NeverLoopResult::Otherwise, |e| never_loop_expr(e, main_loop_id));
combine_seq(e1, combine_branches(e2, e3))
},
ExprKind::Loop(ref b, _, _) => {
},
ExprKind::Block(ref b, _) => never_loop_block(b, main_loop_id),
ExprKind::Continue(d) => {
- let id = d.target_id
+ let id = d
+ .target_id
.expect("target id can only be missing in the presence of compilation errors");
if id == main_loop_id {
NeverLoopResult::MayContinueMainLoop
NeverLoopResult::AlwaysBreak
}
},
- ExprKind::Break(_, _) => {
- NeverLoopResult::AlwaysBreak
- },
+ ExprKind::Break(_, _) => NeverLoopResult::AlwaysBreak,
ExprKind::Ret(ref e) => {
if let Some(ref e) = *e {
combine_seq(never_loop_expr(e, main_loop_id), NeverLoopResult::AlwaysBreak)
NeverLoopResult::AlwaysBreak
}
},
- ExprKind::Struct(_, _, None) |
- ExprKind::Yield(_) |
- ExprKind::Closure(_, _, _, _, _) |
- ExprKind::InlineAsm(_, _, _) |
- ExprKind::Path(_) |
- ExprKind::Lit(_) => NeverLoopResult::Otherwise,
+ ExprKind::Struct(_, _, None)
+ | ExprKind::Yield(_)
+ | ExprKind::Closure(_, _, _, _, _)
+ | ExprKind::InlineAsm(_, _, _)
+ | ExprKind::Path(_)
+ | ExprKind::Lit(_) => NeverLoopResult::Otherwise,
}
}
-fn never_loop_expr_seq<'a, T: Iterator<Item=&'a Expr>>(es: &mut T, main_loop_id: NodeId) -> NeverLoopResult {
+fn never_loop_expr_seq<'a, T: Iterator<Item = &'a Expr>>(es: &mut T, main_loop_id: NodeId) -> NeverLoopResult {
es.map(|e| never_loop_expr(e, main_loop_id))
.fold(NeverLoopResult::Otherwise, combine_seq)
}
-fn never_loop_expr_all<'a, T: Iterator<Item=&'a Expr>>(es: &mut T, main_loop_id: NodeId) -> NeverLoopResult {
+fn never_loop_expr_all<'a, T: Iterator<Item = &'a Expr>>(es: &mut T, main_loop_id: NodeId) -> NeverLoopResult {
es.map(|e| never_loop_expr(e, main_loop_id))
.fold(NeverLoopResult::Otherwise, combine_both)
}
-fn never_loop_expr_branch<'a, T: Iterator<Item=&'a Expr>>(e: &mut T, main_loop_id: NodeId) -> NeverLoopResult {
+fn never_loop_expr_branch<'a, T: Iterator<Item = &'a Expr>>(e: &mut T, main_loop_id: NodeId) -> NeverLoopResult {
e.map(|e| never_loop_expr(e, main_loop_id))
.fold(NeverLoopResult::AlwaysBreak, combine_branches)
}
impl Offset {
fn negative(s: String) -> Self {
- Self {
- value: s,
- negate: true,
- }
+ Self { value: s, negate: true }
}
fn positive(s: String) -> Self {
BinOpKind::Sub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative),
_ => None,
},
- ExprKind::Path(..) => if same_var(cx, idx, var) {
- Some(Offset::positive("0".into()))
- } else {
- None
+ ExprKind::Path(..) => {
+ if same_var(cx, idx, var) {
+ Some(Offset::positive("0".into()))
+ } else {
+ None
+ }
},
_ => None,
};
- offset.map(|o| {
- FixedOffsetVar {
- var_name: snippet_opt(cx, seqexpr.span).unwrap_or_else(|| "???".into()),
- offset: o,
- }
+ offset.map(|o| FixedOffsetVar {
+ var_name: snippet_opt(cx, seqexpr.span).unwrap_or_else(|| "???".into()),
+ offset: o,
})
} else {
None
var: ast::NodeId,
) -> Option<(FixedOffsetVar, FixedOffsetVar)> {
if let ExprKind::Assign(ref lhs, ref rhs) = e.node {
- match (get_fixed_offset_var(cx, lhs, var), fetch_cloned_fixed_offset_var(cx, rhs, var)) {
+ match (
+ get_fixed_offset_var(cx, lhs, var),
+ fetch_cloned_fixed_offset_var(cx, rhs, var),
+ ) {
(Some(offset_left), Some(offset_right)) => {
// Source and destination must be different
if offset_left.var_name == offset_right.var_name {
if let ExprKind::Block(ref b, _) = body.node {
let Block {
- ref stmts,
- ref expr,
- ..
+ ref stmts, ref expr, ..
} = **b;
stmts
StmtKind::Decl(..) => None,
StmtKind::Expr(ref e, _node_id) | StmtKind::Semi(ref e, _node_id) => Some(get_assignment(cx, e, var)),
})
- .chain(
- expr.as_ref()
- .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)
.collect::<Option<Vec<_>>>()
.unwrap_or_else(|| vec![])
}
};
- let print_limit = |end: &Option<&Expr>, offset: Offset, var_name: &str| if let Some(end) = *end {
- if_chain! {
- if let ExprKind::MethodCall(ref method, _, ref len_args) = end.node;
- if method.ident.name == "len";
- if len_args.len() == 1;
- if let Some(arg) = len_args.get(0);
- if snippet(cx, arg.span, "??") == var_name;
- then {
- return if offset.negate {
- format!("({} - {})", snippet(cx, end.span, "<src>.len()"), offset.value)
- } else {
- String::new()
- };
+ let print_limit = |end: &Option<&Expr>, offset: Offset, var_name: &str| {
+ if let Some(end) = *end {
+ if_chain! {
+ if let ExprKind::MethodCall(ref method, _, ref len_args) = end.node;
+ if method.ident.name == "len";
+ if len_args.len() == 1;
+ if let Some(arg) = len_args.get(0);
+ if snippet(cx, arg.span, "??") == var_name;
+ then {
+ return if offset.negate {
+ format!("({} - {})", snippet(cx, end.span, "<src>.len()"), offset.value)
+ } else {
+ String::new()
+ };
+ }
}
- }
- let end_str = match limits {
- ast::RangeLimits::Closed => {
- let end = sugg::Sugg::hir(cx, end, "<count>");
- format!("{}", end + sugg::ONE)
- },
- ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")),
- };
+ let end_str = match limits {
+ ast::RangeLimits::Closed => {
+ let end = sugg::Sugg::hir(cx, end, "<count>");
+ format!("{}", end + sugg::ONE)
+ },
+ ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")),
+ };
- print_sum(&Offset::positive(end_str), &offset)
- } else {
- "..".into()
+ print_sum(&Offset::positive(end_str), &offset)
+ } else {
+ "..".into()
+ }
};
// The only statements in the for loops can be indexed assignments from
format!("{}[{}..{}]", dst_var.var_name, dst_offset, dst_limit)
};
- format!("{}.clone_from_slice(&{}[{}..{}])", dst, src_var.var_name, src_offset, src_limit)
+ format!(
+ "{}.clone_from_slice(&{}[{}..{}])",
+ dst, src_var.var_name, src_offset, src_limit
+ )
})
.join("\n ");
"consider using an iterator".to_string(),
vec![
(pat.span, format!("({}, <item>)", ident.name)),
- (arg.span, format!("{}.{}().enumerate(){}{}", indexed, method, method_1, method_2)),
+ (
+ arg.span,
+ format!("{}.{}().enumerate(){}{}", indexed, method, method_1, method_2),
+ ),
],
);
},
cx,
NEEDLESS_RANGE_LOOP,
expr.span,
- &format!("the loop variable `{}` is only used to index `{}`.", ident.name, indexed),
+ &format!(
+ "the loop variable `{}` is only used to index `{}`.",
+ ident.name, indexed
+ ),
|db| {
multispan_sugg(
db,
false
}
-fn is_end_eq_array_len(
- cx: &LateContext<'_, '_>,
- end: &Expr,
- limits: ast::RangeLimits,
- indexed_ty: Ty<'_>,
-) -> bool {
+fn is_end_eq_array_len(cx: &LateContext<'_, '_>, end: &Expr, limits: ast::RangeLimits, indexed_ty: Ty<'_>) -> bool {
if_chain! {
if let ExprKind::Lit(ref lit) = end.node;
if let ast::LitKind::Int(end_int, _) = lit.node;
// smaller value.
let ty = cx.tables.expr_ty(start);
let (sup, eq) = match (start_idx, end_idx) {
- (
- Constant::Int(start_idx),
- Constant::Int(end_idx),
- ) => (match ty.sty {
- ty::Int(ity) => sext(cx.tcx, start_idx, ity) > sext(cx.tcx, end_idx, ity),
- ty::Uint(_) => start_idx > end_idx,
- _ => false,
- }, start_idx == end_idx),
+ (Constant::Int(start_idx), Constant::Int(end_idx)) => (
+ match ty.sty {
+ ty::Int(ity) => sext(cx.tcx, start_idx, ity) > sext(cx.tcx, end_idx, ity),
+ ty::Uint(_) => start_idx > end_idx,
+ _ => false,
+ },
+ start_idx == end_idx,
+ ),
_ => (false, false),
};
fn lint_iter_method(cx: &LateContext<'_, '_>, args: &[Expr], arg: &Expr, method_name: &str) {
let mut applicability = Applicability::MachineApplicable;
let object = snippet_with_applicability(cx, args[0].span, "_", &mut applicability);
- let muta = if method_name == "iter_mut" {
- "mut "
- } else {
- ""
- };
+ let muta = if method_name == "iter_mut" { "mut " } else { "" };
span_lint_and_sugg(
cx,
EXPLICIT_ITER_LOOP,
// For each candidate, check the parent block to see if
// it's initialized to zero at the start of the loop.
let map = &cx.tcx.hir;
- let parent_scope = map.get_enclosing_scope(expr.id)
+ let parent_scope = map
+ .get_enclosing_scope(expr.id)
.and_then(|id| map.get_enclosing_scope(id));
if let Some(parent_id) = parent_scope {
if let Node::Block(block) = map.get(parent_id) {
- for (id, _) in visitor
- .states
- .iter()
- .filter(|&(_, v)| *v == VarState::IncrOnce)
- {
+ for (id, _) in visitor.states.iter().filter(|&(_, v)| *v == VarState::IncrOnce) {
let mut visitor2 = InitializeVisitor {
cx,
end_expr: expr,
..
}) = higher::range(cx, arg)
{
- let mut_ids = vec![
- check_for_mutability(cx, start),
- check_for_mutability(cx, end),
- ];
+ let mut_ids = vec![check_for_mutability(cx, start), check_for_mutability(cx, end)];
if mut_ids[0].is_some() || mut_ids[1].is_some() {
let (span_low, span_high) = check_for_mutation(cx, body, &mut_ids);
mut_warn_with_span(cx, span_low);
None
}
-fn check_for_mutation(cx: &LateContext<'_, '_>, body: &Expr, bound_ids: &[Option<NodeId>]) -> (Option<Span>, Option<Span>) {
+fn check_for_mutation(
+ cx: &LateContext<'_, '_>,
+ body: &Expr,
+ bound_ids: &[Option<NodeId>],
+) -> (Option<Span>, Option<Span>) {
let mut delegate = MutatePairDelegate {
node_id_low: bound_ids[0],
node_id_high: bound_ids[1],
}
let old = self.prefer_mutable;
match expr.node {
- ExprKind::AssignOp(_, ref lhs, ref rhs) |
- ExprKind::Assign(ref lhs, ref rhs) => {
+ ExprKind::AssignOp(_, ref lhs, ref rhs) | ExprKind::Assign(ref lhs, ref rhs) => {
self.prefer_mutable = true;
self.visit_expr(lhs);
self.prefer_mutable = false;
}
}
-
/// Return true if the type of expr is one that provides `IntoIterator` impls
/// for `&T` and `&mut T`, such as `Vec`.
#[rustfmt::skip]
/// Scan a for loop for variables that are incremented exactly once.
struct IncrementVisitor<'a, 'tcx: 'a> {
- cx: &'a LateContext<'a, 'tcx>, // context reference
+ cx: &'a LateContext<'a, 'tcx>, // context reference
states: FxHashMap<NodeId, VarState>, // incremented variables
- depth: u32, // depth of conditional expressions
+ depth: u32, // depth of conditional expressions
done: bool,
}
return;
}
match expr.node {
- ExprKind::Assign(ref path, _) | ExprKind::AssignOp(_, ref path, _) => if match_var(path, self.iterator) {
- self.nesting = RuledOut;
+ ExprKind::Assign(ref path, _) | ExprKind::AssignOp(_, ref path, _) => {
+ if match_var(path, self.iterator) {
+ self.nesting = RuledOut;
+ }
},
_ => walk_expr(self, expr),
}
let no_cond_variable_mutated = if let Some(used_mutably) = mutated_variables(expr, cx) {
used_in_condition.is_disjoint(&used_mutably)
} else {
- return
+ return;
};
let mutable_static_in_cond = var_visitor.def_ids.iter().any(|(_, v)| *v);
if no_cond_variable_mutated && !mutable_static_in_cond {
cx,
WHILE_IMMUTABLE_CONDITION,
cond.span,
- "Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop.",
+ "Variable in the condition are not mutated in the loop body. \
+ This either leads to an infinite or to a never running loop.",
);
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast::Ident;
use crate::syntax::source_map::Span;
use crate::utils::paths;
-use crate::utils::{in_macro, match_trait_method, match_type, remove_blocks, snippet_with_applicability, span_lint_and_sugg};
+use crate::utils::{
+ in_macro, match_trait_method, match_type, remove_blocks, snippet_with_applicability, span_lint_and_sugg,
+};
use if_chain::if_chain;
#[derive(Clone)]
let closure_expr = remove_blocks(&closure_body.value);
then {
match closure_body.arguments[0].pat.node {
- hir::PatKind::Ref(ref inner, _) => if let hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) = inner.node {
+ hir::PatKind::Ref(ref inner, _) => if let hir::PatKind::Binding(
+ hir::BindingAnnotation::Unannotated, _, name, None
+ ) = inner.node {
lint(cx, e.span, args[0].span, name, closure_expr);
},
- hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => match closure_expr.node {
- hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner) if !cx.tables.expr_ty(inner).is_box() => lint(cx, e.span, args[0].span, name, inner),
- hir::ExprKind::MethodCall(ref method, _, ref obj) => if method.ident.as_str() == "clone" && match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) {
- lint(cx, e.span, args[0].span, name, &obj[0]);
+ hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => {
+ match closure_expr.node {
+ hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner) => {
+ if !cx.tables.expr_ty(inner).is_box() {
+ lint(cx, e.span, args[0].span, name, inner);
+ }
+ },
+ hir::ExprKind::MethodCall(ref method, _, ref obj) => {
+ if method.ident.as_str() == "clone"
+ && match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) {
+ lint(cx, e.span, args[0].span, name, &obj[0]);
+ }
+ },
+ _ => {},
}
- _ => {},
},
_ => {},
}
replace,
"You are using an explicit closure for cloning elements",
"Consider calling the dedicated `cloned` method",
- format!("{}.cloned()", snippet_with_applicability(cx, root, "..", &mut applicability)),
+ format!(
+ "{}.cloned()",
+ snippet_with_applicability(cx, root, "..", &mut applicability)
+ ),
applicability,
)
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
use crate::rustc::ty;
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
use crate::syntax::source_map::Span;
-use crate::utils::{in_macro, iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then};
use crate::utils::paths;
+use crate::utils::{in_macro, iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then};
+use if_chain::if_chain;
#[derive(Clone)]
pub struct Pass;
"using `result.map(f)`, where f is a function or closure that returns ()"
}
-
impl LintPass for Pass {
fn get_lints(&self) -> LintArray {
lint_array!(OPTION_MAP_UNIT_FN, RESULT_MAP_UNIT_FN)
}
match expr.node {
- hir::ExprKind::Call(_, _) |
- hir::ExprKind::MethodCall(_, _, _) => {
+ hir::ExprKind::Call(_, _) | hir::ExprKind::MethodCall(_, _, _) => {
// Calls can't be reduced any more
Some(expr.span)
},
//
// We do not attempt to build a suggestion for those right now.
None
- }
+ },
}
},
_ => None,
match &var_arg.node {
hir::ExprKind::Field(_, _) => snippet(cx, var_arg.span, "_").replace(".", "_"),
hir::ExprKind::Path(_) => format!("_{}", snippet(cx, var_arg.span, "")),
- _ => "_".to_string()
+ _ => "_".to_string(),
}
}
fn suggestion_msg(function_type: &str, map_type: &str) -> String {
format!(
"called `map(f)` on an {0} value where `f` is a unit {1}",
- map_type,
- function_type
+ map_type, function_type
)
}
let var_arg = &map_args[0];
let fn_arg = &map_args[1];
- let (map_type, variant, lint) =
- if match_type(cx, cx.tables.expr_ty(var_arg), &paths::OPTION) {
- ("Option", "Some", OPTION_MAP_UNIT_FN)
- } else if match_type(cx, cx.tables.expr_ty(var_arg), &paths::RESULT) {
- ("Result", "Ok", RESULT_MAP_UNIT_FN)
- } else {
- return
- };
+ let (map_type, variant, lint) = if match_type(cx, cx.tables.expr_ty(var_arg), &paths::OPTION) {
+ ("Option", "Some", OPTION_MAP_UNIT_FN)
+ } else if match_type(cx, cx.tables.expr_ty(var_arg), &paths::RESULT) {
+ ("Result", "Ok", RESULT_MAP_UNIT_FN)
+ } else {
+ return;
+ };
if is_unit_function(cx, fn_arg) {
let msg = suggestion_msg("function", map_type);
- let suggestion = format!("if let {0}({1}) = {2} {{ {3}(...) }}",
- variant,
- let_binding_name(cx, var_arg),
- snippet(cx, var_arg.span, "_"),
- snippet(cx, fn_arg.span, "_"));
+ let suggestion = format!(
+ "if let {0}({1}) = {2} {{ {3}(...) }}",
+ variant,
+ let_binding_name(cx, var_arg),
+ snippet(cx, var_arg.span, "_"),
+ snippet(cx, fn_arg.span, "_")
+ );
span_lint_and_then(cx, lint, expr.span, &msg, |db| {
- db.span_suggestion_with_applicability(stmt.span,
- "try this",
- suggestion,
- Applicability::Unspecified);
+ db.span_suggestion_with_applicability(stmt.span, "try this", suggestion, Applicability::Unspecified);
});
} else if let Some((binding, closure_expr)) = unit_closure(cx, fn_arg) {
let msg = suggestion_msg("closure", map_type);
span_lint_and_then(cx, lint, expr.span, &msg, |db| {
if let Some(reduced_expr_span) = reduce_unit_expression(cx, closure_expr) {
- let suggestion = format!("if let {0}({1}) = {2} {{ {3} }}",
- variant,
- snippet(cx, binding.pat.span, "_"),
- snippet(cx, var_arg.span, "_"),
- snippet(cx, reduced_expr_span, "_"));
+ let suggestion = format!(
+ "if let {0}({1}) = {2} {{ {3} }}",
+ variant,
+ snippet(cx, binding.pat.span, "_"),
+ snippet(cx, var_arg.span, "_"),
+ snippet(cx, reduced_expr_span, "_")
+ );
db.span_suggestion_with_applicability(
stmt.span,
"try this",
Applicability::MachineApplicable, // snippet
);
} else {
- let suggestion = format!("if let {0}({1}) = {2} {{ ... }}",
- variant,
- snippet(cx, binding.pat.span, "_"),
- snippet(cx, var_arg.span, "_"));
- db.span_suggestion_with_applicability(
- stmt.span,
- "try this",
- suggestion,
- Applicability::Unspecified,
+ let suggestion = format!(
+ "if let {0}({1}) = {2} {{ ... }}",
+ variant,
+ snippet(cx, binding.pat.span, "_"),
+ snippet(cx, var_arg.span, "_")
);
+ db.span_suggestion_with_applicability(stmt.span, "try this", suggestion, Applicability::Unspecified);
}
});
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::consts::{constant, Constant};
use crate::rustc::hir::*;
-use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext};
-use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
+use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
use crate::rustc::ty::{self, Ty};
-use std::cmp::Ordering;
-use std::collections::Bound;
+use crate::rustc::{declare_tool_lint, lint_array};
+use crate::rustc_errors::Applicability;
use crate::syntax::ast::LitKind;
use crate::syntax::source_map::Span;
use crate::utils::paths;
-use crate::utils::{expr_block, in_macro, is_allowed, is_expn_of, match_qpath, match_type,
- multispan_sugg, remove_blocks, snippet, snippet_with_applicability, span_lint_and_sugg, span_lint_and_then,
- span_note_and_lint, walk_ptrs_ty};
use crate::utils::sugg::Sugg;
-use crate::consts::{constant, Constant};
-use crate::rustc_errors::Applicability;
+use crate::utils::{
+ expr_block, in_macro, is_allowed, is_expn_of, match_qpath, match_type, multispan_sugg, remove_blocks, snippet,
+ snippet_with_applicability, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty,
+};
+use if_chain::if_chain;
+use std::cmp::Ordering;
+use std::collections::Bound;
/// **What it does:** Checks for matches with a single arm where an `if let`
/// will usually suffice.
/// ```rust
/// match x {
/// Some(ref foo) => bar(foo),
-/// _ => ()
+/// _ => (),
/// }
/// ```
declare_clippy_lint! {
pub SINGLE_MATCH,
style,
- "a match statement with a single nontrivial arm (i.e. where the other arm \
- is `_ => {}`) instead of `if let`"
+ "a match statement with a single nontrivial arm (i.e. where the other arm is `_ => {}`) instead of `if let`"
}
/// **What it does:** Checks for matches with a two arms where an `if let` will
declare_clippy_lint! {
pub SINGLE_MATCH_ELSE,
pedantic,
- "a match statement with a two arms where the second arm's pattern is a wildcard \
- instead of `if let`"
+ "a match statement with a two arms where the second arm's pattern is a wildcard instead of `if let`"
}
/// **What it does:** Checks for matches where all arms match a reference,
/// ```rust
/// let x = 5;
/// match x {
-/// 1 ... 10 => println!("1 ... 10"),
-/// 5 ... 15 => println!("5 ... 15"),
+/// 1...10 => println!("1 ... 10"),
+/// 5...15 => println!("5 ... 15"),
/// _ => (),
/// }
/// ```
///
/// **Example:**
/// ```rust
-/// let x : Result(i32, &str) = Ok(3);
+/// let x: Result(i32, &str) = Ok(3);
/// match x {
/// Ok(_) => println!("ok"),
/// Err(_) => panic!("err"),
/// ```rust
/// let x: Option<()> = None;
/// let r: Option<&()> = match x {
-/// None => None,
-/// Some(ref v) => Some(v),
+/// None => None,
+/// Some(ref v) => Some(v),
/// };
/// ```
declare_clippy_lint! {
}
}
-fn check_single_match_single_pattern(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr, els: Option<&Expr>) {
+fn check_single_match_single_pattern(
+ cx: &LateContext<'_, '_>,
+ ex: &Expr,
+ arms: &[Arm],
+ expr: &Expr,
+ els: Option<&Expr>,
+) {
if is_wild(&arms[1].pats[0]) {
report_single_match_single_pattern(cx, ex, arms, expr, els);
}
}
-fn report_single_match_single_pattern(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr, els: Option<&Expr>) {
- let lint = if els.is_some() {
- SINGLE_MATCH_ELSE
- } else {
- SINGLE_MATCH
- };
- let els_str = els.map_or(String::new(), |els| format!(" else {}", expr_block(cx, els, None, "..")));
+fn report_single_match_single_pattern(
+ cx: &LateContext<'_, '_>,
+ ex: &Expr,
+ arms: &[Arm],
+ expr: &Expr,
+ els: Option<&Expr>,
+) {
+ let lint = if els.is_some() { SINGLE_MATCH_ELSE } else { SINGLE_MATCH };
+ let els_str = els.map_or(String::new(), |els| {
+ format!(" else {}", expr_block(cx, els, None, ".."))
+ });
span_lint_and_sugg(
cx,
lint,
);
}
-fn check_single_match_opt_like(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr, ty: Ty<'_>, els: Option<&Expr>) {
+fn check_single_match_opt_like(
+ cx: &LateContext<'_, '_>,
+ ex: &Expr,
+ arms: &[Arm],
+ expr: &Expr,
+ ty: Ty<'_>,
+ els: Option<&Expr>,
+) {
// list of candidate Enums we know will never get any more members
let candidates = &[
(&paths::COW, "Borrowed"),
}
fn check_match_as_ref(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &Expr) {
- if arms.len() == 2 &&
- arms[0].pats.len() == 1 && arms[0].guard.is_none() &&
- arms[1].pats.len() == 1 && arms[1].guard.is_none() {
+ if arms.len() == 2
+ && arms[0].pats.len() == 1
+ && arms[0].guard.is_none()
+ && arms[1].pats.len() == 1
+ && arms[1].guard.is_none()
+ {
let arm_ref: Option<BindingAnnotation> = if is_none_arm(&arms[0]) {
is_ref_some_arm(&arms[1])
} else if is_none_arm(&arms[1]) {
None
};
if let Some(rb) = arm_ref {
- let suggestion = if rb == BindingAnnotation::Ref { "as_ref" } else { "as_mut" };
+ let suggestion = if rb == BindingAnnotation::Ref {
+ "as_ref"
+ } else {
+ "as_mut"
+ };
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(
cx,
expr.span,
&format!("use {}() instead", suggestion),
"try this",
- format!("{}.{}()", snippet_with_applicability(cx, ex.span, "_", &mut applicability), suggestion),
+ format!(
+ "{}.{}()",
+ snippet_with_applicability(cx, ex.span, "_", &mut applicability),
+ suggestion
+ ),
applicability,
)
}
}
/// Get all arms that are unbounded `PatRange`s.
-fn all_ranges<'a, 'tcx>(
- cx: &LateContext<'a, 'tcx>,
- arms: &'tcx [Arm],
-) -> Vec<SpannedRange<Constant>> {
+fn all_ranges<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arms: &'tcx [Arm]) -> Vec<SpannedRange<Constant>> {
arms.iter()
.flat_map(|arm| {
if let Arm {
- ref pats,
- guard: None,
- ..
+ ref pats, guard: None, ..
} = *arm
{
pats.iter()
} else {
[].iter()
- }.filter_map(|pat| {
+ }
+ .filter_map(|pat| {
if let PatKind::Range(ref lhs, ref rhs, ref range_end) = pat.node {
let lhs = constant(cx, cx.tables, lhs)?.0;
let rhs = constant(cx, cx.tables, rhs)?.0;
RangeEnd::Included => Bound::Included(rhs),
RangeEnd::Excluded => Bound::Excluded(rhs),
};
- return Some(SpannedRange { span: pat.span, node: (lhs, rhs) });
+ return Some(SpannedRange {
+ span: pat.span,
+ node: (lhs, rhs),
+ });
}
if let PatKind::Lit(ref value) = pat.node {
let value = constant(cx, cx.tables, value)?.0;
- return Some(SpannedRange { span: pat.span, node: (value.clone(), Bound::Included(value)) });
+ return Some(SpannedRange {
+ span: pat.span,
+ node: (value.clone(), Bound::Included(value)),
+ });
}
None
ranges
.iter()
.filter_map(|range| match range.node {
- (
- Constant::Int(start),
- Bound::Included(Constant::Int(end)),
- ) => Some(SpannedRange {
+ (Constant::Int(start), Bound::Included(Constant::Int(end))) => Some(SpannedRange {
span: range.span,
node: (start, Bound::Included(end)),
}),
- (
- Constant::Int(start),
- Bound::Excluded(Constant::Int(end)),
- ) => Some(SpannedRange {
+ (Constant::Int(start), Bound::Excluded(Constant::Int(end))) => Some(SpannedRange {
span: range.span,
node: (start, Bound::Excluded(end)),
}),
- (
- Constant::Int(start),
- Bound::Unbounded,
- ) => Some(SpannedRange {
+ (Constant::Int(start), Bound::Unbounded) => Some(SpannedRange {
span: range.span,
node: (start, Bound::Unbounded),
}),
}
fn has_only_ref_pats(arms: &[Arm]) -> bool {
- let mapped = arms.iter()
+ let mapped = arms
+ .iter()
.flat_map(|a| &a.pats)
.map(|p| {
match p.node {
for (a, b) in values.iter().zip(values.iter().skip(1)) {
match (a, b) {
- (&Kind::Start(_, ra), &Kind::End(_, rb)) => if ra.node != rb.node {
- return Some((ra, rb));
+ (&Kind::Start(_, ra), &Kind::End(_, rb)) => {
+ if ra.node != rb.node {
+ return Some((ra, rb));
+ }
},
(&Kind::End(a, _), &Kind::Start(b, _)) if a != Bound::Included(b) => (),
_ => return Some((a.range(), b.range())),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir::{Expr, ExprKind};
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::{Expr, ExprKind};
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use crate::rustc::hir::{Expr, ExprKind};
use crate::utils::{match_def_path, opt_def_id, paths, span_lint};
/// **What it does:** Checks for usage of `std::mem::forget(t)` where `t` is
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir::{Expr, ExprKind, MutMutable, QPath};
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir;
use crate::rustc::hir::def::Def;
use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, Lint, LintArray, LintContext, LintPass};
-use crate::rustc::ty::{self, Ty, TyKind, Predicate};
+use crate::rustc::ty::{self, Predicate, Ty, TyKind};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
use crate::syntax::ast;
get_arg_name, get_trait_def_id, implements_trait, in_macro, is_copy, is_expn_of, is_self, is_self_ty,
iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type,
match_var, method_calls, method_chain_args, remove_blocks, return_ty, same_tys, single_segment_path, snippet,
- snippet_with_macro_callsite, snippet_with_applicability, span_lint, span_lint_and_sugg, span_lint_and_then,
+ snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_sugg, span_lint_and_then,
span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq,
};
use if_chain::if_chain;
/// ```rust
/// struct X;
/// impl X {
-/// fn add(&self, other: &X) -> X { .. }
+/// fn add(&self, other: &X) -> X {
+/// ..
+/// }
/// }
/// ```
declare_clippy_lint! {
/// **Example:**
/// ```rust
/// impl X {
-/// fn as_str(self) -> &str { .. }
+/// fn as_str(self) -> &str {
+/// ..
+/// }
/// }
/// ```
declare_clippy_lint! {
pub WRONG_SELF_CONVENTION,
style,
- "defining a method named with an established prefix (like \"into_\") that takes \
- `self` with the wrong convention"
+ "defining a method named with an established prefix (like \"into_\") that takes `self` with the wrong convention"
}
/// **What it does:** This is the same as
/// **Example:**
/// ```rust
/// impl X {
-/// pub fn as_str(self) -> &str { .. }
+/// pub fn as_str(self) -> &str {
+/// ..
+/// }
/// }
/// ```
declare_clippy_lint! {
pub WRONG_PUB_SELF_CONVENTION,
restriction,
- "defining a public method named with an established prefix (like \"into_\") that takes \
- `self` with the wrong convention"
+ "defining a public method named with an established prefix (like \"into_\") that takes `self` with the wrong convention"
}
/// **What it does:** Checks for usage of `ok().expect(..)`.
declare_clippy_lint! {
pub OK_EXPECT,
style,
- "using `ok().expect()`, which gives worse error messages than \
- calling `expect` directly on the Result"
+ "using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result"
}
/// **What it does:** Checks for usage of `_.map(_).unwrap_or(_)`.
/// x.map(|a| a + 1).unwrap_or(0)
/// ```
declare_clippy_lint! {
- pub OPTION_MAP_UNWRAP_OR,
- pedantic,
- "using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as \
- `map_or(a, f)`"
+pub OPTION_MAP_UNWRAP_OR,
+pedantic,
+"using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as \
+ `map_or(a, f)`"
}
/// **What it does:** Checks for usage of `_.map(_).unwrap_or_else(_)`.
declare_clippy_lint! {
pub OPTION_MAP_UNWRAP_OR_ELSE,
pedantic,
- "using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \
- `map_or_else(g, f)`"
+ "using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)`"
}
/// **What it does:** Checks for usage of `result.map(_).unwrap_or_else(_)`.
declare_clippy_lint! {
pub RESULT_MAP_UNWRAP_OR_ELSE,
pedantic,
- "using `Result.map(f).unwrap_or_else(g)`, which is more succinctly expressed as \
- `.ok().map_or_else(g, f)`"
+ "using `Result.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `.ok().map_or_else(g, f)`"
}
/// **What it does:** Checks for usage of `_.map_or(None, _)`.
declare_clippy_lint! {
pub OPTION_MAP_OR_NONE,
style,
- "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)`"
}
/// **What it does:** Checks for usage of `_.filter(_).next()`.
declare_clippy_lint! {
pub MAP_FLATTEN,
pedantic,
- "using combinations of `flatten` and `map` which can usually be written as a \
- single method call"
+ "using combinations of `flatten` and `map` which can usually be written as a single method call"
}
/// **What it does:** Checks for usage of `_.filter(_).map(_)`,
declare_clippy_lint! {
pub FILTER_MAP,
pedantic,
- "using combinations of `filter`, `map`, `filter_map` and `flat_map` which can \
- usually be written as a single method call"
+ "using combinations of `filter`, `map`, `filter_map` and `flat_map` which can usually be written as a single method call"
}
/// **What it does:** Checks for an iterator search (such as `find()`,
declare_clippy_lint! {
pub SEARCH_IS_SOME,
complexity,
- "using an iterator search followed by `is_some()`, which is more succinctly \
- expressed as a call to `any()`"
+ "using an iterator search followed by `is_some()`, which is more succinctly expressed as a call to `any()`"
}
/// **What it does:** Checks for usage of `.chars().next()` on a `str` to check
/// **Example:**
/// ```rust
/// fn main() {
-/// let x = vec![1];
-/// let y = &&x;
-/// let z = y.clone();
-/// println!("{:p} {:p}",*y, z); // prints out the same pointer
+/// let x = vec![1];
+/// let y = &&x;
+/// let z = y.clone();
+/// println!("{:p} {:p}", *y, z); // prints out the same pointer
/// }
/// ```
declare_clippy_lint! {
declare_clippy_lint! {
pub SINGLE_CHAR_PATTERN,
perf,
- "using a single-character str where a char could be used, e.g. \
- `_.split(\"x\")`"
+ "using a single-character str where a char could be used, e.g. `_.split(\"x\")`"
}
/// **What it does:** Checks for getting the inner pointer of a temporary
///
/// **Example:**
/// ```rust
-/// let s = [1,2,3,4,5];
-/// let s2 : Vec<isize> = s[..].iter().cloned().collect();
+/// let s = [1, 2, 3, 4, 5];
+/// let s2: Vec<isize> = s[..].iter().cloned().collect();
/// ```
/// The better use would be:
/// ```rust
-/// let s = [1,2,3,4,5];
-/// let s2 : Vec<isize> = s.to_vec();
+/// let s = [1, 2, 3, 4, 5];
+/// let s2: Vec<isize> = s.to_vec();
/// ```
declare_clippy_lint! {
pub ITER_CLONED_COLLECT,
///
/// **Example:**
/// ```rust
-/// let x: &[i32] = &[1,2,3,4,5];
+/// let x: &[i32] = &[1, 2, 3, 4, 5];
/// do_stuff(x.as_ref());
/// ```
/// The correct use would be:
/// ```rust
-/// let x: &[i32] = &[1,2,3,4,5];
+/// let x: &[i32] = &[1, 2, 3, 4, 5];
/// do_stuff(x);
/// ```
declare_clippy_lint! {
"using `as_ref` where the types before and after the call are the same"
}
-
/// **What it does:** Checks for using `fold` when a more succinct alternative exists.
/// Specifically, this checks for `fold`s which could be replaced by `any`, `all`,
/// `sum` or `product`.
"using `fold` when a more succinct alternative exists"
}
-
/// **What it does:** Checks for `filter_map` calls which could be replaced by `filter` or `map`.
/// More specifically it checks if the closure provided is only performing one of the
/// filter or map operations and suggests the appropriate option.
["as_mut", ..] => lint_asref(cx, expr, "as_mut", arg_lists[0]),
["fold", ..] => lint_unnecessary_fold(cx, expr, arg_lists[0]),
["filter_map", ..] => unnecessary_filter_map::lint(cx, expr, arg_lists[0]),
- _ => {}
+ _ => {},
}
match expr.node {
hir::ExprKind::MethodCall(ref method_call, ref method_span, ref args) => {
-
lint_or_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args);
lint_expect_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args);
}
match self_ty.sty {
- ty::Ref(_, ty, _) if ty.sty == ty::Str => for &(method, pos) in &PATTERN_METHODS {
- if method_call.ident.name == method && args.len() > pos {
- lint_single_char_pattern(cx, expr, &args[pos]);
+ ty::Ref(_, ty, _) if ty.sty == ty::Str => {
+ for &(method, pos) in &PATTERN_METHODS {
+ if method_call.ident.name == method && args.len() > pos {
+ lint_single_char_pattern(cx, expr, &args[pos]);
+ }
}
},
ty::Ref(..) if method_call.ident.name == "into_iter" => {
_ => (),
}
},
- hir::ExprKind::Binary(op, ref lhs, ref rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => {
+ hir::ExprKind::Binary(op, ref lhs, ref rhs)
+ if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne =>
+ {
let mut info = BinaryExprInfo {
expr,
chain: lhs,
eq: op.node == hir::BinOpKind::Eq,
};
lint_binary_expr_with_method_call(cx, &mut info);
- },
+ }
_ => (),
}
}
.join(" or ")));
}
- // Only check the first convention to match (CONVENTIONS should be listed from most to least specific)
+ // Only check the first convention to match (CONVENTIONS should be listed from most to least
+ // specific)
break;
}
}
// walk the return type and check for Self (this does not check associated types)
for inner_type in ret_ty.walk() {
- if same_tys(cx, ty, inner_type) { return; }
+ if same_tys(cx, ty, inner_type) {
+ return;
+ }
}
// if return type is impl trait, check the associated types
if let TyKind::Opaque(def_id, _) = ret_ty.sty {
-
// one of the associated types must be Self
for predicate in &cx.tcx.predicates_of(def_id).predicates {
match predicate {
let associated_type_is_self_type = same_tys(cx, ty, associated_type);
// if the associated type is self, early return and do not trigger lint
- if associated_type_is_self_type { return; }
+ if associated_type_is_self_type {
+ return;
+ }
},
(_, _) => {},
}
}
if name == "new" && !same_tys(cx, ret_ty, ty) {
- span_lint(cx,
- NEW_RET_NO_SELF,
- implitem.span,
- "methods called `new` usually return `Self`");
+ span_lint(
+ cx,
+ NEW_RET_NO_SELF,
+ implitem.span,
+ "methods called `new` usually return `Self`",
+ );
}
}
}
span,
&format!("use of `{}` followed by a call to `{}`", name, path),
"try this",
- format!("{}.unwrap_or_default()", snippet_with_applicability(cx, self_expr.span, "_", &mut applicability)),
+ format!(
+ "{}.unwrap_or_default()",
+ snippet_with_applicability(cx, self_expr.span, "_", &mut applicability)
+ ),
applicability,
);
return true;
hir::ExprKind::Call(ref fun, ref or_args) => {
let or_has_args = !or_args.is_empty();
if !check_unwrap_or_default(cx, name, fun, &args[0], &args[1], or_has_args, expr.span) {
- check_general_case(cx, name, method_span, fun.span, &args[0], &args[1], or_has_args, expr.span);
+ check_general_case(
+ cx,
+ name,
+ method_span,
+ fun.span,
+ &args[0],
+ &args[1],
+ or_has_args,
+ expr.span,
+ );
}
},
- hir::ExprKind::MethodCall(_, span, ref or_args) => {
- check_general_case(cx, name, method_span, span, &args[0], &args[1], !or_args.is_empty(), expr.span)
- },
+ hir::ExprKind::MethodCall(_, span, ref or_args) => check_general_case(
+ cx,
+ name,
+ method_span,
+ span,
+ &args[0],
+ &args[1],
+ !or_args.is_empty(),
+ expr.span,
+ ),
_ => {},
}
}
/// Checks for the `EXPECT_FUN_CALL` lint.
fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) {
fn extract_format_args(arg: &hir::Expr) -> Option<&hir::HirVec<hir::Expr>> {
- let arg = match &arg.node {
- hir::ExprKind::AddrOf(_, expr)=> expr,
+ let arg = match &arg.node {
+ hir::ExprKind::AddrOf(_, expr) => expr,
hir::ExprKind::MethodCall(method_name, _, args)
- if method_name.ident.name == "as_str" ||
- method_name.ident.name == "as_ref"
- => &args[0],
+ if method_name.ident.name == "as_str" || method_name.ident.name == "as_ref" =>
+ {
+ &args[0]
+ },
_ => arg,
};
if let hir::ExprKind::AddrOf(_, ref format_arg) = a.node {
if let hir::ExprKind::Match(ref format_arg_expr, _, _) = format_arg.node {
if let hir::ExprKind::Tup(ref format_arg_expr_tup) = format_arg_expr.node {
- return snippet_with_applicability(cx, format_arg_expr_tup[0].span, "..", applicability).into_owned();
+ return snippet_with_applicability(cx, format_arg_expr_tup[0].span, "..", applicability)
+ .into_owned();
}
}
};
return;
}
- let closure = if match_type(cx, self_type, &paths::OPTION) { "||" } else { "|_|" };
+ let closure = if match_type(cx, self_type, &paths::OPTION) {
+ "||"
+ } else {
+ "|_|"
+ };
let span_replace_word = method_span.with_hi(span.hi());
if let Some(format_args) = extract_format_args(arg) {
expr.span,
"using `clone` on a double-reference; \
this will copy the reference instead of cloning the inner type",
- |db| if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) {
- let mut ty = innermost;
- let mut n = 0;
- while let ty::Ref(_, inner, _) = ty.sty {
- ty = inner;
- n += 1;
+ |db| {
+ if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) {
+ let mut ty = innermost;
+ let mut n = 0;
+ while let ty::Ref(_, inner, _) = ty.sty {
+ ty = inner;
+ n += 1;
+ }
+ let refs: String = iter::repeat('&').take(n + 1).collect();
+ let derefs: String = iter::repeat('*').take(n).collect();
+ let explicit = format!("{}{}::clone({})", refs, ty, snip);
+ db.span_suggestion_with_applicability(
+ expr.span,
+ "try dereferencing it",
+ format!("{}({}{}).clone()", refs, derefs, snip.deref()),
+ Applicability::MaybeIncorrect,
+ );
+ db.span_suggestion_with_applicability(
+ expr.span,
+ "or try being explicit about what type to clone",
+ explicit,
+ Applicability::MaybeIncorrect,
+ );
}
- let refs: String = iter::repeat('&').take(n + 1).collect();
- let derefs: String = iter::repeat('*').take(n).collect();
- let explicit = format!("{}{}::clone({})", refs, ty, snip);
- db.span_suggestion_with_applicability(
- expr.span,
- "try dereferencing it",
- format!("{}({}{}).clone()", refs, derefs, snip.deref()),
- Applicability::MaybeIncorrect,
- );
- db.span_suggestion_with_applicability(
- expr.span,
- "or try being explicit about what type to clone",
- explicit,
- Applicability::MaybeIncorrect,
- );
},
);
return; // don't report clone_on_copy
// (*x).func() is useless, x.clone().func() can work in case func borrows mutably
hir::ExprKind::MethodCall(..) => return,
_ => {},
- }
+ },
hir::Node::Stmt(stmt) => {
if let hir::StmtKind::Decl(ref decl, _) = stmt.node {
if let hir::DeclKind::Local(ref loc) = decl.node {
}
span_lint_and_then(cx, CLONE_ON_COPY, expr.span, "using `clone` on a `Copy` type", |db| {
if let Some((text, snip)) = snip {
- db.span_suggestion_with_applicability(
- expr.span,
- text,
- snip,
- Applicability::Unspecified,
- );
+ db.span_suggestion_with_applicability(expr.span, text, snip, Applicability::Unspecified);
}
});
}
expr.span,
"using '.clone()' on a ref-counted pointer",
"try this",
- format!("{}::<{}>::clone(&{})", caller_type, subst.type_at(0), snippet(cx, arg.span, "_")),
+ format!(
+ "{}::<{}>::clone(&{})",
+ caller_type,
+ subst.type_at(0),
+ snippet(cx, arg.span, "_")
+ ),
Applicability::Unspecified, // Sometimes unnecessary ::<_> after Rc/Arc/Weak
);
}
}
-
fn lint_string_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) {
let arg = &args[1];
if let Some(arglists) = method_chain_args(arg, &["chars"]) {
fold_args: &[hir::Expr],
op: hir::BinOpKind,
replacement_method_name: &str,
- replacement_has_args: bool) {
-
+ replacement_has_args: bool,
+ ) {
if_chain! {
// Extract the body of the closure passed to fold
if let hir::ExprKind::Closure(_, _, body_id, _, _) = fold_args[2].node;
return;
}
- assert!(fold_args.len() == 3,
- "Expected fold_args to have three entries - the receiver, the initial value and the closure");
+ assert!(
+ fold_args.len() == 3,
+ "Expected fold_args to have three entries - the receiver, the initial value and the closure"
+ );
// Check if the first argument to .fold is a suitable literal
match fold_args[1].node {
- hir::ExprKind::Lit(ref lit) => {
- match lit.node {
- ast::LitKind::Bool(false) => check_fold_with_op(
- cx, fold_args, hir::BinOpKind::Or, "any", true
- ),
- ast::LitKind::Bool(true) => check_fold_with_op(
- cx, fold_args, hir::BinOpKind::And, "all", true
- ),
- ast::LitKind::Int(0, _) => check_fold_with_op(
- cx, fold_args, hir::BinOpKind::Add, "sum", false
- ),
- ast::LitKind::Int(1, _) => check_fold_with_op(
- cx, fold_args, hir::BinOpKind::Mul, "product", false
- ),
- _ => return
- }
- }
- _ => return
+ hir::ExprKind::Lit(ref lit) => match lit.node {
+ ast::LitKind::Bool(false) => check_fold_with_op(cx, fold_args, hir::BinOpKind::Or, "any", true),
+ ast::LitKind::Bool(true) => check_fold_with_op(cx, fold_args, hir::BinOpKind::And, "all", true),
+ ast::LitKind::Int(0, _) => check_fold_with_op(cx, fold_args, hir::BinOpKind::Add, "sum", false),
+ ast::LitKind::Int(1, _) => check_fold_with_op(cx, fold_args, hir::BinOpKind::Mul, "product", false),
+ _ => return,
+ },
+ _ => return,
};
}
expr.span,
&format!(
"called `.iter{0}().nth()` on a {1}. Calling `.get{0}()` is both faster and more readable",
- mut_str,
- caller_type
+ mut_str, caller_type
),
);
}
};
let mut_str = if is_mut { "_mut" } else { "" };
- let borrow_str = if !needs_ref { "" } else if is_mut { "&mut " } else { "&" };
+ let borrow_str = if !needs_ref {
+ ""
+ } else if is_mut {
+ "&mut "
+ } else {
+ "&"
+ };
span_lint_and_sugg(
cx,
GET_UNWRAP,
expr.span,
&format!(
"called `.get{0}().unwrap()` on a {1}. Using `[]` is more clear and more concise",
- mut_str,
- caller_type
+ mut_str, caller_type
),
"try this",
format!(
match ty.sty {
ty::Slice(_) => sugg::Sugg::hir_opt(cx, expr),
ty::Adt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => sugg::Sugg::hir_opt(cx, expr),
- ty::Ref(_, inner, _) => if may_slice(cx, inner) {
- sugg::Sugg::hir_opt(cx, expr)
- } else {
- None
+ ty::Ref(_, inner, _) => {
+ if may_slice(cx, inner) {
+ sugg::Sugg::hir_opt(cx, expr)
+ } else {
+ None
+ }
},
_ => None,
}
"used unwrap() on {} value. If you don't want to handle the {} case gracefully, consider \
using expect() to provide a better panic \
message",
- kind,
- none_value
+ kind, none_value
),
);
}
// lint message
// comparing the snippet from source to raw text ("None") below is safe
// because we already have checked the type.
- let arg = if unwrap_snippet == "None" {
- "None"
- } else {
- "a"
- };
+ let arg = if unwrap_snippet == "None" { "None" } else { "a" };
let suggest = if unwrap_snippet == "None" {
"and_then(f)"
} else {
let msg = &format!(
"called `map(f).unwrap_or({})` on an Option value. \
This can be done more directly by calling `{}` instead",
- arg,
- suggest
+ arg, suggest
);
// lint, with note if neither arg is > 1 line and both map() and
// unwrap_or() have the same span
};
let note = format!(
"replace `map({}).unwrap_or({})` with `{}`",
- map_snippet,
- unwrap_snippet,
- suggest
+ map_snippet, unwrap_snippet, suggest
);
span_note_and_lint(cx, OPTION_MAP_UNWRAP_OR, expr.span, msg, expr.span, ¬e);
} else if same_span && multiline {
}
/// lint use of `map().flatten()` for `Iterators`
-fn lint_map_flatten<'a, 'tcx>(
- cx: &LateContext<'a, 'tcx>,
- expr: &'tcx hir::Expr,
- map_args: &'tcx [hir::Expr],
-) {
+fn lint_map_flatten<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, map_args: &'tcx [hir::Expr]) {
// lint if caller of `.map().flatten()` is an Iterator
if match_trait_method(cx, expr, &paths::ITERATOR) {
let msg = "called `map(..).flatten()` on an `Iterator`. \
expr.span,
&msg,
expr.span,
- &format!("replace `{0}({1}).is_some()` with `any({1})`", search_method, search_snippet),
+ &format!(
+ "replace `{0}({1}).is_some()` with `any({1})`",
+ search_method, search_snippet
+ ),
);
} else {
span_lint(cx, SEARCH_IS_SOME, expr.span, &msg);
return;
}
}
- }
+ };
}
lint_with_both_lhs_and_rhs!(lint_chars_next_cmp, cx, info);
}
}
-fn ty_has_iter_method(cx: &LateContext<'_, '_>, self_ref_ty: ty::Ty<'_>) -> Option<(&'static Lint, &'static str, &'static str)> {
+fn ty_has_iter_method(
+ cx: &LateContext<'_, '_>,
+ self_ref_ty: ty::Ty<'_>,
+) -> Option<(&'static Lint, &'static str, &'static str)> {
// FIXME: instead of this hard-coded list, we should check if `<adt>::iter`
// exists and has the desired signature. Unfortunately FnCtxt is not exported
// so we can't use its `lookup_method` method.
for (lint, path) in &INTO_ITER_COLLECTIONS {
if match_def_path(cx.tcx, def_id, path) {
- return Some((lint, path.last().unwrap(), method_name))
+ return Some((lint, path.last().unwrap(), method_name));
}
}
None
method_span,
&format!(
"this .into_iter() call is equivalent to .{}() and will not move the {}",
- method_name,
- kind,
+ method_name, kind,
),
"call directly",
method_name.to_string(),
}
}
-
/// Given a `Result<T, E>` type, return its error type (`E`).
fn get_error_type<'a>(cx: &LateContext<'_, '_>, ty: Ty<'a>) -> Option<Ty<'a>> {
if let ty::Adt(_, substs) = ty.sty {
("trim_right_matches", 1),
];
-
#[derive(Clone, Copy, PartialEq, Debug)]
enum SelfKind {
Value,
single_segment_ty(ty).map_or(false, |seg| {
generics.params.iter().any(|param| match param.kind {
hir::GenericParamKind::Type { .. } => {
- param.name.ident().name == seg.ident.name && param.bounds.iter().any(|bound| {
- if let hir::GenericBound::Trait(ref ptr, ..) = *bound {
- let path = &ptr.trait_ref.path;
- match_path(path, name) && path.segments.last().map_or(false, |s| {
- if let Some(ref params) = s.args {
- if params.parenthesized {
- false
- } else {
- // FIXME(flip1995): messy, improve if there is a better option
- // in the compiler
- let types: Vec<_> = params.args.iter().filter_map(|arg| match arg {
- hir::GenericArg::Type(ty) => Some(ty),
- _ => None,
- }).collect();
- types.len() == 1
- && (is_self_ty(&types[0]) || is_ty(&*types[0], self_ty))
- }
- } else {
- false
- }
- })
- } else {
- false
- }
- })
+ param.name.ident().name == seg.ident.name
+ && param.bounds.iter().any(|bound| {
+ if let hir::GenericBound::Trait(ref ptr, ..) = *bound {
+ let path = &ptr.trait_ref.path;
+ match_path(path, name)
+ && path.segments.last().map_or(false, |s| {
+ if let Some(ref params) = s.args {
+ if params.parenthesized {
+ false
+ } else {
+ // FIXME(flip1995): messy, improve if there is a better option
+ // in the compiler
+ let types: Vec<_> = params
+ .args
+ .iter()
+ .filter_map(|arg| match arg {
+ hir::GenericArg::Type(ty) => Some(ty),
+ _ => None,
+ })
+ .collect();
+ types.len() == 1 && (is_self_ty(&types[0]) || is_ty(&*types[0], self_ty))
+ }
+ } else {
+ false
+ }
+ })
+ } else {
+ false
+ }
+ })
},
_ => false,
})
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir;
use crate::rustc::hir::def::Def;
use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::consts::{constant_simple, Constant};
-use crate::utils::{match_def_path, opt_def_id, paths, span_lint};
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
+use crate::utils::{match_def_path, opt_def_id, paths, span_lint};
use std::cmp::Ordering;
/// **What it does:** Checks for expressions where `std::cmp::min` and `max` are
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::consts::{constant, Constant};
use crate::reexport::*;
-use matches::matches;
-use crate::rustc::hir::*;
use crate::rustc::hir::intravisit::FnKind;
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
use crate::rustc::ty;
+use crate::rustc::{declare_tool_lint, lint_array};
+use crate::rustc_errors::Applicability;
+use crate::syntax::ast::LitKind;
use crate::syntax::source_map::{ExpnFormat, Span};
-use crate::utils::{get_item_name, get_parent_expr, implements_trait, in_constant, in_macro, is_integer_literal,
- iter_input_pats, last_path_segment, match_qpath, match_trait_method, paths, snippet, span_lint,
- span_lint_and_then, walk_ptrs_ty, SpanlessEq};
use crate::utils::sugg::Sugg;
-use crate::syntax::ast::LitKind;
-use crate::consts::{constant, Constant};
-use crate::rustc_errors::Applicability;
+use crate::utils::{
+ get_item_name, get_parent_expr, implements_trait, in_constant, in_macro, is_integer_literal, iter_input_pats,
+ last_path_segment, match_qpath, match_trait_method, paths, snippet, span_lint, span_lint_and_then, walk_ptrs_ty,
+ SpanlessEq,
+};
+use if_chain::if_chain;
+use matches::matches;
/// **What it does:** Checks for function arguments and let bindings denoted as
/// `ref`.
///
/// **Example:**
/// ```rust
-/// fn foo(ref x: u8) -> bool { .. }
+/// fn foo(ref x: u8) -> bool {
+/// ..
+/// }
/// ```
declare_clippy_lint! {
pub TOPLEVEL_REF_ARG,
/// ```rust
/// match v {
/// Some(x) => (),
-/// y @ _ => (), // easier written as `y`,
+/// y @ _ => (), // easier written as `y`,
/// }
/// ```
declare_clippy_lint! {
///
/// **Example:**
/// ```rust
-/// f() && g(); // We should write `if f() { g(); }`.
+/// f() && g(); // We should write `if f() { g(); }`.
/// ```
declare_clippy_lint! {
pub SHORT_CIRCUIT_STATEMENT,
}
for arg in iter_input_pats(decl, body) {
match arg.pat.node {
- PatKind::Binding(BindingAnnotation::Ref, _, _, _) |
- PatKind::Binding(BindingAnnotation::RefMut, _, _, _) => {
+ PatKind::Binding(BindingAnnotation::Ref, _, _, _)
+ | PatKind::Binding(BindingAnnotation::RefMut, _, _, _) => {
span_lint(
cx,
TOPLEVEL_REF_ARG,
}
if let Some(name) = get_item_name(cx, expr) {
let name = name.as_str();
- if name == "eq" || name == "ne" || name == "is_nan" || name.starts_with("eq_")
+ if name == "eq"
+ || name == "ne"
+ || name == "is_nan"
+ || name.starts_with("eq_")
|| name.ends_with("_eq")
{
return;
cx,
REDUNDANT_PATTERN,
pat.span,
- &format!("the `{} @ _` pattern can be written as just `{}`", ident.name, ident.name),
+ &format!(
+ "the `{} @ _` pattern can be written as just `{}`",
+ ident.name, ident.name
+ ),
);
}
}
CMP_NAN,
expr.span,
"doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead",
- );
+ );
}
}
}
if let Some((_, res)) = constant(cx, cx.tables, expr) {
res
} else {
- false
+ false
}
}
return;
}
},
- ExprKind::Call(ref path, ref v) if v.len() == 1 => if let ExprKind::Path(ref path) = path.node {
- if match_qpath(path, &["String", "from_str"]) || match_qpath(path, &["String", "from"]) {
- (cx.tables.expr_ty_adjusted(&v[0]), snippet(cx, v[0].span, ".."))
+ ExprKind::Call(ref path, ref v) if v.len() == 1 => {
+ if let ExprKind::Path(ref path) = path.node {
+ if match_qpath(path, &["String", "from_str"]) || match_qpath(path, &["String", "from"]) {
+ (cx.tables.expr_ty_adjusted(&v[0]), snippet(cx, v[0].span, ".."))
+ } else {
+ return;
+ }
} else {
return;
}
- } else {
- return;
},
_ => return,
};
None => return,
};
- let deref_arg_impl_partial_eq_other = arg_ty
- .builtin_deref(true)
- .map_or(false, |tam| implements_trait(cx, tam.ty, partial_eq_trait_id, &[other_ty.into()]));
- let arg_impl_partial_eq_deref_other = other_ty
- .builtin_deref(true)
- .map_or(false, |tam| implements_trait(cx, arg_ty, partial_eq_trait_id, &[tam.ty.into()]));
+ let deref_arg_impl_partial_eq_other = arg_ty.builtin_deref(true).map_or(false, |tam| {
+ implements_trait(cx, tam.ty, partial_eq_trait_id, &[other_ty.into()])
+ });
+ let arg_impl_partial_eq_deref_other = other_ty.builtin_deref(true).map_or(false, |tam| {
+ implements_trait(cx, arg_ty, partial_eq_trait_id, &[tam.ty.into()])
+ });
let arg_impl_partial_eq_other = implements_trait(cx, arg_ty, partial_eq_trait_id, &[other_ty.into()]);
- if !deref_arg_impl_partial_eq_other
- && !arg_impl_partial_eq_deref_other
- && !arg_impl_partial_eq_other
- {
+ if !deref_arg_impl_partial_eq_other && !arg_impl_partial_eq_deref_other && !arg_impl_partial_eq_other {
return;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, LintContext, in_external_macro};
+use crate::rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_data_structures::fx::FxHashMap;
-use if_chain::if_chain;
-use std::char;
+use crate::rustc_errors::Applicability;
use crate::syntax::ast::*;
use crate::syntax::source_map::Span;
-use crate::syntax::visit::{FnKind, Visitor, walk_expr};
+use crate::syntax::visit::{walk_expr, FnKind, Visitor};
use crate::utils::{constants, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_then};
-use crate::rustc_errors::Applicability;
+use if_chain::if_chain;
+use std::char;
/// **What it does:** Checks for structure field patterns bound to wildcards.
///
impl ReturnVisitor {
fn new() -> Self {
- Self {
- found_return: false,
- }
+ Self { found_return: false }
}
}
fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat, _: &mut bool) {
if let PatKind::Struct(ref npat, ref pfields, _) = pat.node {
let mut wilds = 0;
- let type_name = npat.segments
+ let type_name = npat
+ .segments
.last()
.expect("A path must have at least one segment")
.ident
for field in pfields {
match field.node.pat.node {
PatKind::Wild => {},
- _ => if let Ok(n) = cx.sess().source_map().span_to_snippet(field.span) {
- normal.push(n);
+ _ => {
+ if let Ok(n) = cx.sess().source_map().span_to_snippet(field.span) {
+ normal.push(n);
+ }
},
}
}
return;
}
match expr.node {
- ExprKind::Call(ref paren, _) => if let ExprKind::Paren(ref closure) = paren.node {
- if let ExprKind::Closure(_, _, _, ref decl, ref block, _) = closure.node {
- let mut visitor = ReturnVisitor::new();
- visitor.visit_expr(block);
- if !visitor.found_return {
- span_lint_and_then(
- cx,
- REDUNDANT_CLOSURE_CALL,
- expr.span,
- "Try not to call a closure in the expression where it is declared.",
- |db| if decl.inputs.is_empty() {
- let hint = snippet(cx, block.span, "..").into_owned();
- db.span_suggestion_with_applicability(
- expr.span,
- "Try doing something like: ",
- hint,
- Applicability::MachineApplicable, // snippet
- );
- },
- );
+ ExprKind::Call(ref paren, _) => {
+ if let ExprKind::Paren(ref closure) = paren.node {
+ if let ExprKind::Closure(_, _, _, ref decl, ref block, _) = closure.node {
+ let mut visitor = ReturnVisitor::new();
+ visitor.visit_expr(block);
+ if !visitor.found_return {
+ span_lint_and_then(
+ cx,
+ REDUNDANT_CLOSURE_CALL,
+ expr.span,
+ "Try not to call a closure in the expression where it is declared.",
+ |db| {
+ if decl.inputs.is_empty() {
+ let hint = snippet(cx, block.span, "..").into_owned();
+ db.span_suggestion_with_applicability(
+ expr.span,
+ "Try doing something like: ",
+ hint,
+ Applicability::MachineApplicable, // snippet
+ );
+ }
+ },
+ );
+ }
}
}
},
- ExprKind::Unary(UnOp::Neg, ref inner) => if let ExprKind::Unary(UnOp::Neg, _) = inner.node {
- span_lint(
- cx,
- DOUBLE_NEG,
- expr.span,
- "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op",
- );
+ ExprKind::Unary(UnOp::Neg, ref inner) => {
+ if let ExprKind::Unary(UnOp::Neg, _) = inner.node {
+ span_lint(
+ cx,
+ DOUBLE_NEG,
+ expr.span,
+ "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op",
+ );
+ }
},
ExprKind::Lit(ref lit) => self.check_lit(cx, lit),
_ => (),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
// This file incorporates work covered by the following copyright and
// permission notice:
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
//
use crate::rustc::hir;
-use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, LintContext};
-use crate::rustc::{declare_tool_lint, lint_array};
+use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
use crate::rustc::ty;
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast;
use crate::syntax::attr;
use crate::syntax::source_map::Span;
-use crate::utils::{span_lint, in_macro};
+use crate::utils::{in_macro, span_lint};
/// **What it does:** Warns if there is missing doc for any documentable item
/// (public or private).
}
fn doc_hidden(&self) -> bool {
- *self.doc_hidden_stack
- .last()
- .expect("empty doc_hidden_stack")
+ *self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
}
- fn check_missing_docs_attrs(&self, cx: &LateContext<'_, '_>, attrs: &[ast::Attribute], sp: Span, desc: &'static str) {
+ fn check_missing_docs_attrs(
+ &self,
+ cx: &LateContext<'_, '_>,
+ attrs: &[ast::Attribute],
+ sp: Span,
+ desc: &'static str,
+ ) {
// If we're building a test harness, then warning about
// documentation is probably not really relevant right now.
if cx.sess().opts.test {
return;
}
- let has_doc = attrs
- .iter()
- .any(|a| a.is_value_str() && a.name() == "doc");
+ let has_doc = attrs.iter().any(|a| a.is_value_str() && a.name() == "doc");
if !has_doc {
span_lint(
cx,
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
fn enter_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, attrs: &'tcx [ast::Attribute]) {
- let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| {
- attr.check_name("doc") && match attr.meta_item_list() {
- None => false,
- Some(l) => attr::list_contains_name(&l[..], "hidden"),
- }
- });
+ let doc_hidden = self.doc_hidden()
+ || attrs.iter().any(|attr| {
+ attr.check_name("doc")
+ && match attr.meta_item_list() {
+ None => false,
+ Some(l) => attr::list_contains_name(&l[..], "hidden"),
+ }
+ });
self.doc_hidden_stack.push(doc_hidden);
}
hir::ItemKind::Ty(..) => "a type alias",
hir::ItemKind::Union(..) => "a union",
hir::ItemKind::Existential(..) => "an existential type",
- hir::ItemKind::ExternCrate(..) |
- hir::ItemKind::ForeignMod(..) |
- hir::ItemKind::Impl(..) |
- hir::ItemKind::Use(..) => return,
+ hir::ItemKind::ExternCrate(..)
+ | hir::ItemKind::ForeignMod(..)
+ | hir::ItemKind::Impl(..)
+ | hir::ItemKind::Use(..) => return,
};
self.check_missing_docs_attrs(cx, &it.attrs, it.span, desc);
let def_id = cx.tcx.hir.local_def_id(impl_item.id);
match cx.tcx.associated_item(def_id).container {
ty::TraitContainer(_) => return,
- ty::ImplContainer(cid) => if cx.tcx.impl_trait_ref(cid).is_some() {
- return;
+ ty::ImplContainer(cid) => {
+ if cx.tcx.impl_trait_ref(cid).is_some() {
+ return;
+ }
},
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
/// crates when that's profitable as long as any form of LTO is used. When LTO is disabled,
/// functions that are not `#[inline]` cannot be inlined across crates. Certain types of crates
/// might intend for most of the methods in their public API to be able to be inlined across
-/// crates even when LTO is disabled. For these types of crates, enabling this lint might make sense.
-/// It allows the crate to require all exported methods to be `#[inline]` by default, and then opt
-/// out for specific methods where this might not make sense.
+/// crates even when LTO is disabled. For these types of crates, enabling this lint might make
+/// sense. It allows the crate to require all exported methods to be `#[inline]` by default, and
+/// then opt out for specific methods where this might not make sense.
///
/// **Known problems:** None.
///
pub struct MissingInline;
-fn check_missing_inline_attrs(cx: &LateContext<'_, '_>,
- attrs: &[ast::Attribute], sp: Span, desc: &'static str) {
- let has_inline = attrs
- .iter()
- .any(|a| a.name() == "inline" );
+fn check_missing_inline_attrs(cx: &LateContext<'_, '_>, attrs: &[ast::Attribute], sp: Span, desc: &'static str) {
+ let has_inline = attrs.iter().any(|a| a.name() == "inline");
if !has_inline {
span_lint(
cx,
fn is_executable<'a, 'tcx>(cx: &LateContext<'a, 'tcx>) -> bool {
use crate::rustc::session::config::CrateType;
- cx.tcx.sess.crate_types.get().iter().any(|t: &CrateType| {
- match t {
- CrateType::Executable => true,
- _ => false,
- }
+ cx.tcx.sess.crate_types.get().iter().any(|t: &CrateType| match t {
+ CrateType::Executable => true,
+ _ => false,
})
}
let desc = "a function";
check_missing_inline_attrs(cx, &it.attrs, it.span, desc);
},
- hir::ItemKind::Trait(ref _is_auto, ref _unsafe, ref _generics,
- ref _bounds, ref trait_items) => {
+ hir::ItemKind::Trait(ref _is_auto, ref _unsafe, ref _generics, ref _bounds, ref trait_items) => {
// note: we need to check if the trait is exported so we can't use
// `LateLintPass::check_trait_item` here.
for tit in trait_items {
let tit_ = cx.tcx.hir.trait_item(tit.id);
match tit_.node {
- hir::TraitItemKind::Const(..) |
- hir::TraitItemKind::Type(..) => {},
+ hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => {},
hir::TraitItemKind::Method(..) => {
if tit.defaultness.has_value() {
// trait method with default body needs inline in case
// an impl is not provided
let desc = "a default trait method";
let item = cx.tcx.hir.expect_trait_item(tit.id.node_id);
- check_missing_inline_attrs(cx, &item.attrs,
- item.span, desc);
+ check_missing_inline_attrs(cx, &item.attrs, item.span, desc);
}
},
}
}
- }
- hir::ItemKind::Const(..) |
- hir::ItemKind::Enum(..) |
- hir::ItemKind::Mod(..) |
- hir::ItemKind::Static(..) |
- hir::ItemKind::Struct(..) |
- hir::ItemKind::TraitAlias(..) |
- hir::ItemKind::GlobalAsm(..) |
- hir::ItemKind::Ty(..) |
- hir::ItemKind::Union(..) |
- hir::ItemKind::Existential(..) |
- hir::ItemKind::ExternCrate(..) |
- hir::ItemKind::ForeignMod(..) |
- hir::ItemKind::Impl(..) |
- hir::ItemKind::Use(..) => {},
+ },
+ hir::ItemKind::Const(..)
+ | hir::ItemKind::Enum(..)
+ | hir::ItemKind::Mod(..)
+ | hir::ItemKind::Static(..)
+ | hir::ItemKind::Struct(..)
+ | hir::ItemKind::TraitAlias(..)
+ | hir::ItemKind::GlobalAsm(..)
+ | hir::ItemKind::Ty(..)
+ | hir::ItemKind::Union(..)
+ | hir::ItemKind::Existential(..)
+ | hir::ItemKind::ExternCrate(..)
+ | hir::ItemKind::ForeignMod(..)
+ | hir::ItemKind::Impl(..)
+ | hir::ItemKind::Use(..) => {},
};
}
fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem) {
- use crate::rustc::ty::{TraitContainer, ImplContainer};
+ use crate::rustc::ty::{ImplContainer, TraitContainer};
if is_executable(cx) {
return;
}
let desc = match impl_item.node {
hir::ImplItemKind::Method(..) => "a method",
- hir::ImplItemKind::Const(..) |
- hir::ImplItemKind::Type(_) |
- hir::ImplItemKind::Existential(_) => return,
+ hir::ImplItemKind::Const(..) | hir::ImplItemKind::Type(_) | hir::ImplItemKind::Existential(_) => return,
};
let def_id = cx.tcx.hir.local_def_id(impl_item.id);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir;
use crate::rustc::hir::intravisit;
-use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext};
-use crate::rustc::{declare_tool_lint, lint_array};
+use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
use crate::rustc::ty;
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::utils::{higher, span_lint};
/// **What it does:** Checks for instances of `mut mut` references.
expr.span,
"generally you want to avoid `&mut &mut _` if possible",
);
- } else if let ty::Ref(
- _,
- _,
- hir::MutMutable,
- ) = self.cx.tables.expr_ty(e).sty
- {
+ } else if let ty::Ref(_, _, hir::MutMutable) = self.cx.tables.expr_ty(e).sty {
span_lint(
self.cx,
MUT_MUT,
if let hir::TyKind::Rptr(
_,
hir::MutTy {
- mutbl: hir::MutMutable,
- ..
+ mutbl: hir::MutMutable, ..
},
) = pty.node
{
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
-use crate::rustc::ty::{self, Ty};
use crate::rustc::ty::subst::Subst;
-use crate::rustc::hir::*;
+use crate::rustc::ty::{self, Ty};
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::utils::span_lint;
/// **What it does:** Detects giving a mutable reference to a function that only
declare_clippy_lint! {
pub UNNECESSARY_MUT_PASSED,
style,
- "an argument passed as a mutable reference although the callee only demands an \
- immutable reference"
+ "an argument passed as a mutable reference although the callee only demands an immutable reference"
}
-
#[derive(Copy, Clone)]
pub struct UnnecessaryMutPassed;
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
match e.node {
- ExprKind::Call(ref fn_expr, ref arguments) => if let ExprKind::Path(ref path) = fn_expr.node {
- check_arguments(
- cx,
- arguments,
- cx.tables.expr_ty(fn_expr),
- &print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)),
- );
+ ExprKind::Call(ref fn_expr, ref arguments) => {
+ if let ExprKind::Path(ref path) = fn_expr.node {
+ check_arguments(
+ cx,
+ arguments,
+ cx.tables.expr_ty(fn_expr),
+ &print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)),
+ );
+ }
},
ExprKind::MethodCall(ref path, _, ref arguments) => {
let def_id = cx.tables.type_dependent_defs()[e.hir_id].def_id();
let parameters = type_definition.fn_sig(cx.tcx).skip_binder().inputs();
for (argument, parameter) in arguments.iter().zip(parameters.iter()) {
match parameter.sty {
- ty::Ref(
- _,
- _,
- MutImmutable,
- ) |
- ty::RawPtr(ty::TypeAndMut {
- mutbl: MutImmutable,
- ..
- }) => if let ExprKind::AddrOf(MutMutable, _) = argument.node {
- span_lint(
- cx,
- UNNECESSARY_MUT_PASSED,
- argument.span,
- &format!("The function/method `{}` doesn't need a mutable reference", name),
- );
+ ty::Ref(_, _, MutImmutable)
+ | ty::RawPtr(ty::TypeAndMut {
+ mutbl: MutImmutable, ..
+ }) => {
+ if let ExprKind::AddrOf(MutMutable, _) = argument.node {
+ span_lint(
+ cx,
+ UNNECESSARY_MUT_PASSED,
+ argument.span,
+ &format!("The function/method `{}` doesn't need a mutable reference", name),
+ );
+ }
},
_ => (),
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! Checks for uses of mutex where an atomic value could be used
//!
//! This lint is **warn** by default
+use crate::rustc::hir::Expr;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc::ty::{self, Ty};
-use crate::rustc::hir::Expr;
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast;
use crate::utils::{match_type, paths, span_lint};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! Checks for needless boolean results of if-else expressions
//!
//! This lint is **warn** by default
///
/// **Example:**
/// ```rust
-/// if x { false } else { true }
+/// if x {
+/// false
+/// } else {
+/// true
+/// }
/// ```
declare_clippy_lint! {
pub NEEDLESS_BOOL,
complexity,
- "if-statements with plain booleans in the then- and else-clause, e.g. \
- `if p { true } else { false }`"
+ "if-statements with plain booleans in the then- and else-clause, e.g. `if p { true } else { false }`"
}
/// **What it does:** Checks for expressions of the form `x == true` (or vice
///
/// **Example:**
/// ```rust
-/// if x == true { } // could be `if x { }`
+/// if x == true {} // could be `if x { }`
/// ```
declare_clippy_lint! {
pub BOOL_COMPARISON,
return;
}
- if let ExprKind::Binary(Spanned { node: BinOpKind::Eq, .. }, ref left_side, ref right_side) = e.node {
+ if let ExprKind::Binary(
+ Spanned {
+ node: BinOpKind::Eq, ..
+ },
+ ref left_side,
+ ref right_side,
+ ) = e.node
+ {
let mut applicability = Applicability::MachineApplicable;
match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) {
(Bool(true), Other) => {
fn fetch_bool_block(block: &Block) -> Expression {
match (&*block.stmts, block.expr.as_ref()) {
(&[], Some(e)) => fetch_bool_expr(&**e),
- (&[ref e], None) => if let StmtKind::Semi(ref e, _) = e.node {
- if let ExprKind::Ret(_) = e.node {
- fetch_bool_expr(&**e)
+ (&[ref e], None) => {
+ if let StmtKind::Semi(ref e, _) = e.node {
+ if let ExprKind::Ret(_) = e.node {
+ fetch_bool_expr(&**e)
+ } else {
+ Expression::Other
+ }
} else {
Expression::Other
}
- } else {
- Expression::Other
},
_ => Expression::Other,
}
fn fetch_bool_expr(expr: &Expr) -> Expression {
match expr.node {
ExprKind::Block(ref block, _) => fetch_bool_block(block),
- ExprKind::Lit(ref lit_ptr) => if let LitKind::Bool(value) = lit_ptr.node {
- Expression::Bool(value)
- } else {
- Expression::Other
+ ExprKind::Lit(ref lit_ptr) => {
+ if let LitKind::Bool(value) = lit_ptr.node {
+ Expression::Bool(value)
+ } else {
+ Expression::Other
+ }
},
ExprKind::Ret(Some(ref expr)) => match fetch_bool_expr(expr) {
Expression::Bool(value) => Expression::RetBool(value),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! Checks for needless address of operations (`&`)
//!
//! This lint is **warn** by default
use crate::rustc::ty::adjustment::{Adjust, Adjustment};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
-use crate::utils::{in_macro, snippet_opt, span_lint_and_then};
use crate::syntax::ast::NodeId;
+use crate::utils::{in_macro, snippet_opt, span_lint_and_then};
use if_chain::if_chain;
/// **What it does:** Checks for address of operations (`&`) that are going to
if let ty::Ref(..) = cx.tables.expr_ty(inner).sty {
for adj3 in cx.tables.expr_adjustments(e).windows(3) {
if let [Adjustment {
- kind: Adjust::Deref(_),
- ..
+ kind: Adjust::Deref(_), ..
}, Adjustment {
- kind: Adjust::Deref(_),
- ..
+ kind: Adjust::Deref(_), ..
}, Adjustment {
kind: Adjust::Borrow(_),
..
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! Checks for useless borrowed references.
//!
//! This lint is **warn** by default
+use crate::rustc::hir::{BindingAnnotation, MutImmutable, Pat, PatKind};
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
-use crate::rustc::hir::{BindingAnnotation, MutImmutable, Pat, PatKind};
-use crate::utils::{in_macro, snippet, span_lint_and_then};
use crate::rustc_errors::Applicability;
+use crate::utils::{in_macro, snippet, span_lint_and_then};
+use if_chain::if_chain;
/// **What it does:** Checks for useless borrowed references.
///
///
/// **Example:**
/// ```rust
-/// let mut v = Vec::<String>::new();
-/// let _ = v.iter_mut().filter(|&ref a| a.is_empty());
+/// let mut v = Vec::<String>::new();
+/// let _ = v.iter_mut().filter(|&ref a| a.is_empty());
/// ```
/// This closure takes a reference on something that has been matched as a
/// reference and
|db| {
let hint = snippet(cx, spanned_name.span, "..").into_owned();
db.span_suggestion_with_applicability(
- pat.span,
+ pat.span,
"try removing the `&ref` part and just keep",
hint,
Applicability::MachineApplicable, // snippet
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! Checks for continue statements in loops that are redundant.
//!
//! For example, the lint would catch
/// - The expression is a `continue` node.
/// - The expression node is a block with the first statement being a
/// `continue`.
-///
fn needless_continue_in_else(else_expr: &ast::Expr) -> bool {
match else_expr.node {
ast::ExprKind::Block(ref else_block, _) => is_first_block_stmt_continue(else_block),
fn is_first_block_stmt_continue(block: &ast::Block) -> bool {
block.stmts.get(0).map_or(false, |stmt| match stmt.node {
- ast::StmtKind::Semi(ref e) | ast::StmtKind::Expr(ref e) => if let ast::ExprKind::Continue(_) = e.node {
- true
- } else {
- false
+ ast::StmtKind::Semi(ref e) | ast::StmtKind::Expr(ref e) => {
+ if let ast::ExprKind::Continue(_) = e.node {
+ true
+ } else {
+ false
+ }
},
_ => false,
})
F: FnMut(&ast::Block),
{
match expr.node {
- ast::ExprKind::While(_, ref loop_block, _) |
- ast::ExprKind::WhileLet(_, _, ref loop_block, _) |
- ast::ExprKind::ForLoop(_, _, ref loop_block, _) |
- ast::ExprKind::Loop(ref loop_block, _) => func(loop_block),
+ ast::ExprKind::While(_, ref loop_block, _)
+ | ast::ExprKind::WhileLet(_, _, ref loop_block, _)
+ | ast::ExprKind::ForLoop(_, _, ref loop_block, _)
+ | ast::ExprKind::Loop(ref loop_block, _) => func(loop_block),
_ => {},
}
}
/// - The `if` condition expression,
/// - The `then` block, and
/// - The `else` expression.
-///
fn with_if_expr<F>(stmt: &ast::Stmt, mut func: F)
where
F: FnMut(&ast::Expr, &ast::Expr, &ast::Block, &ast::Expr),
const DROP_ELSE_BLOCK_MSG: &str = "Consider dropping the else clause, and moving out the code in the else \
block, like so:\n";
-
fn emit_warning<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str, typ: LintType) {
// snip is the whole *help* message that appears after the warning.
// message is the warning message.
span_help_and_lint(ctx, NEEDLESS_CONTINUE, expr.span, message, &snip);
}
-fn suggestion_snippet_for_continue_inside_if<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str) -> String {
+fn suggestion_snippet_for_continue_inside_if<'a>(
+ ctx: &EarlyContext<'_>,
+ data: &'a LintData<'_>,
+ header: &str,
+) -> String {
let cond_code = snippet(ctx, data.if_cond.span, "..");
let if_code = format!("if {} {{\n continue;\n}}\n", cond_code);
ret
}
-fn suggestion_snippet_for_continue_inside_else<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str) -> String {
+fn suggestion_snippet_for_continue_inside_else<'a>(
+ ctx: &EarlyContext<'_>,
+ data: &'a LintData<'_>,
+ header: &str,
+) -> String {
let cond_code = snippet(ctx, data.if_cond.span, "..");
let mut if_code = format!("if {} {{\n", cond_code);
block_stmts: &loop_block.stmts,
};
if needless_continue_in_else(else_expr) {
- emit_warning(ctx, data, DROP_ELSE_BLOCK_AND_MERGE_MSG, LintType::ContinueInsideElseBlock);
+ emit_warning(
+ ctx,
+ data,
+ DROP_ELSE_BLOCK_AND_MERGE_MSG,
+ LintType::ContinueInsideElseBlock,
+ );
} else if is_first_block_stmt_continue(then_block) {
emit_warning(ctx, data, DROP_ELSE_BLOCK_MSG, LintType::ContinueInsideThenBlock);
}
/// e.g., the string
///
/// ```
-/// {
-/// let x = 5;
-/// }
+/// {
+/// let x = 5;
+/// }
/// ```
///
/// is transformed to
/// inside_a_block();
/// }
/// ```
-///
pub fn erode_from_front(s: &str) -> String {
s.chars()
.skip_while(|c| c.is_whitespace())
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use matches::matches;
-use crate::rustc::hir::*;
use crate::rustc::hir::intravisit::FnKind;
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
-use crate::rustc::ty::{self, RegionKind, TypeFoldable};
-use crate::rustc::traits;
use crate::rustc::middle::expr_use_visitor as euv;
use crate::rustc::middle::mem_categorization as mc;
-use crate::rustc_target::spec::abi::Abi;
+use crate::rustc::traits;
+use crate::rustc::ty::{self, RegionKind, TypeFoldable};
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use crate::rustc_errors::Applicability;
+use crate::rustc_target::spec::abi::Abi;
use crate::syntax::ast::NodeId;
-use crate::syntax_pos::Span;
use crate::syntax::errors::DiagnosticBuilder;
-use crate::utils::{get_trait_def_id, implements_trait, in_macro, is_copy, is_self, match_type, multispan_sugg, paths,
- snippet, snippet_opt, span_lint_and_then};
+use crate::syntax_pos::Span;
use crate::utils::ptr::get_spans;
+use crate::utils::{
+ get_trait_def_id, implements_trait, in_macro, is_copy, is_self, match_type, multispan_sugg, paths, snippet,
+ snippet_opt, span_lint_and_then,
+};
+use if_chain::if_chain;
+use matches::matches;
use std::borrow::Cow;
-use crate::rustc_errors::Applicability;
/// **What it does:** Checks for functions taking arguments by value, but not
/// consuming them in its
}
macro_rules! need {
- ($e: expr) => { if let Some(x) = $e { x } else { return; } };
+ ($e: expr) => {
+ if let Some(x) = $e {
+ x
+ } else {
+ return;
+ }
+ };
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
need!(cx.tcx.lang_items().fn_trait()),
need!(cx.tcx.lang_items().fn_once_trait()),
need!(cx.tcx.lang_items().fn_mut_trait()),
- need!(get_trait_def_id(cx, &paths::RANGE_ARGUMENT_TRAIT))
+ need!(get_trait_def_id(cx, &paths::RANGE_ARGUMENT_TRAIT)),
];
let sized_trait = need!(cx.tcx.lang_items().sized_trait());
.filter(|p| !p.is_global())
.filter_map(|pred| {
if let ty::Predicate::Trait(poly_trait_ref) = pred {
- 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;
}
Some(poly_trait_ref)
let fn_sig = cx.tcx.fn_sig(fn_def_id);
let fn_sig = cx.tcx.erase_late_bound_regions(&fn_sig);
- for (idx, ((input, &ty), arg)) in decl.inputs
- .iter()
- .zip(fn_sig.inputs())
- .zip(&body.arguments)
- .enumerate()
- {
+ for (idx, ((input, &ty), arg)) in decl.inputs.iter().zip(fn_sig.inputs()).zip(&body.arguments).enumerate() {
// All spans generated from a proc-macro invocation are the same...
if span == input.span {
return;
}
}
+ //
// * Exclude a type that is specifically bounded by `Borrow`.
- // * Exclude a type whose reference also fulfills its bound.
- // (e.g. `std::convert::AsRef`, `serde::Serialize`)
+ // * Exclude a type whose reference also fulfills its bound. (e.g. `std::convert::AsRef`,
+ // `serde::Serialize`)
let (implements_borrow_trait, all_borrowable_trait) = {
let preds = preds
.iter()
(
preds.iter().any(|t| t.def_id() == borrow_trait),
- !preds.is_empty() && preds.iter().all(|t| {
- let ty_params = &t.skip_binder().trait_ref.substs.iter().skip(1)
- .cloned()
- .collect::<Vec<_>>();
- implements_trait(
- cx,
- cx.tcx.mk_imm_ref(&RegionKind::ReErased, ty),
- t.def_id(),
- ty_params
- )
- }),
+ !preds.is_empty()
+ && preds.iter().all(|t| {
+ let ty_params = &t
+ .skip_binder()
+ .trait_ref
+ .substs
+ .iter()
+ .skip(1)
+ .cloned()
+ .collect::<Vec<_>>();
+ implements_trait(cx, cx.tcx.mk_imm_ref(&RegionKind::ReErased, ty), t.def_id(), ty_params)
+ }),
)
};
}
}
- fn borrow(&mut self, _: NodeId, _: Span, _: &mc::cmt_<'tcx>, _: ty::Region<'_>, _: ty::BorrowKind, _: euv::LoanCause) {}
+ fn borrow(
+ &mut self,
+ _: NodeId,
+ _: Span,
+ _: &mc::cmt_<'tcx>,
+ _: ty::Region<'_>,
+ _: ty::BorrowKind,
+ _: euv::LoanCause,
+ ) {
+ }
fn mutate(&mut self, _: NodeId, _: Span, _: &mc::cmt_<'tcx>, _: euv::MutateMode) {}
fn decl_without_init(&mut self, _: NodeId, _: Span) {}
}
-
fn unwrap_downcast_or_interior<'a, 'tcx>(mut cmt: &'a mc::cmt_<'tcx>) -> mc::cmt_<'tcx> {
loop {
match cmt.cat {
},
_ => return (*cmt).clone(),
}
- };
+ }
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::{Expr, ExprKind};
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc::ty;
-use crate::rustc::hir::{Expr, ExprKind};
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::utils::span_lint;
/// **What it does:** Checks for needlessly including a base struct on update
///
/// **Example:**
/// ```rust
-/// Point { x: 1, y: 0, ..zero_point }
+/// Point {
+/// x: 1,
+/// y: 0,
+/// ..zero_point
+/// }
/// ```
declare_clippy_lint! {
pub NEEDLESS_UPDATE,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir::*;
-use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext};
+use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use if_chain::if_chain;
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd {
-
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if_chain! {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
use crate::syntax::source_map::{Span, Spanned};
+use if_chain::if_chain;
use crate::consts::{self, Constant};
use crate::utils::span_lint;
#[allow(clippy::match_same_arms)]
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NegMultiply {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
- if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref l, ref r) = e.node {
+ if let ExprKind::Binary(
+ Spanned {
+ node: BinOpKind::Mul, ..
+ },
+ ref l,
+ ref r,
+ ) = e.node
+ {
match (&l.node, &r.node) {
(&ExprKind::Unary(..), &ExprKind::Unary(..)) => (),
(&ExprKind::Unary(UnNeg, ref lit), _) => check_mul(cx, e.span, lit, r),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use crate::rustc::hir::def_id::DefId;
use crate::rustc::hir;
-use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext};
+use crate::rustc::hir::def_id::DefId;
+use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
+use crate::rustc::ty::{self, Ty};
use crate::rustc::util::nodemap::NodeSet;
use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
-use crate::rustc::ty::{self, Ty};
+use crate::rustc_errors::Applicability;
use crate::syntax::source_map::Span;
use crate::utils::paths;
-use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_and_then};
use crate::utils::sugg::DiagnosticBuilderExt;
-use crate::rustc_errors::Applicability;
+use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_and_then};
+use if_chain::if_chain;
/// **What it does:** Checks for types with a `fn new() -> Self` method and no
/// implementation of
}
if impl_item.generics.params.iter().any(|gen| match gen.kind {
hir::GenericParamKind::Type { .. } => true,
- _ => false
+ _ => false,
}) {
// when the result of `new()` depends on a type parameter we should not require
// an
}
if sig.decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) {
let self_did = cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id));
- let self_ty = cx.tcx
- .type_of(self_did);
+ let self_ty = cx.tcx.type_of(self_did);
if_chain! {
if same_tys(cx, self_ty, return_ty(cx, id));
if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT);
cx,
NEW_WITHOUT_DEFAULT_DERIVE,
impl_item.span,
- &format!("you should consider deriving a `Default` implementation for `{}`", self_ty),
+ &format!(
+ "you should consider deriving a `Default` implementation for `{}`",
+ self_ty
+ ),
|db| {
db.suggest_item_with_attr(
cx,
cx,
NEW_WITHOUT_DEFAULT,
impl_item.span,
- &format!("you should consider adding a `Default` implementation for `{}`", self_ty),
+ &format!(
+ "you should consider adding a `Default` implementation for `{}`",
+ self_ty
+ ),
|db| {
db.suggest_prepend_item(
cx,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir::def::Def;
use crate::rustc::hir::{BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource};
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
has_no_effect(cx, a) && has_no_effect(cx, b)
},
ExprKind::Array(ref v) | ExprKind::Tup(ref v) => v.iter().all(|val| has_no_effect(cx, val)),
- ExprKind::Repeat(ref inner, _) |
- ExprKind::Cast(ref inner, _) |
- ExprKind::Type(ref inner, _) |
- ExprKind::Unary(_, ref inner) |
- ExprKind::Field(ref inner, _) |
- ExprKind::AddrOf(_, ref inner) |
- ExprKind::Box(ref inner) => has_no_effect(cx, inner),
+ ExprKind::Repeat(ref inner, _)
+ | ExprKind::Cast(ref inner, _)
+ | ExprKind::Type(ref inner, _)
+ | ExprKind::Unary(_, ref inner)
+ | ExprKind::Field(ref inner, _)
+ | ExprKind::AddrOf(_, ref inner)
+ | ExprKind::Box(ref inner) => has_no_effect(cx, inner),
ExprKind::Struct(_, ref fields, ref base) => {
- !has_drop(cx, expr) && fields.iter().all(|field| has_no_effect(cx, &field.expr)) && match *base {
- Some(ref base) => has_no_effect(cx, base),
- None => true,
- }
- },
- ExprKind::Call(ref callee, ref args) => if let ExprKind::Path(ref qpath) = callee.node {
- let def = cx.tables.qpath_def(qpath, callee.hir_id);
- match def {
- Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) => {
- !has_drop(cx, expr) && args.iter().all(|arg| has_no_effect(cx, arg))
- },
- _ => false,
- }
- } else {
- false
+ !has_drop(cx, expr)
+ && fields.iter().all(|field| has_no_effect(cx, &field.expr))
+ && match *base {
+ Some(ref base) => has_no_effect(cx, base),
+ None => true,
+ }
},
- ExprKind::Block(ref block, _) => {
- block.stmts.is_empty() && if let Some(ref expr) = block.expr {
- has_no_effect(cx, expr)
+ ExprKind::Call(ref callee, ref args) => {
+ if let ExprKind::Path(ref qpath) = callee.node {
+ let def = cx.tables.qpath_def(qpath, callee.hir_id);
+ match def {
+ Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) => {
+ !has_drop(cx, expr) && args.iter().all(|arg| has_no_effect(cx, arg))
+ },
+ _ => false,
+ }
} else {
false
}
},
+ ExprKind::Block(ref block, _) => {
+ block.stmts.is_empty()
+ && if let Some(ref expr) = block.expr {
+ has_no_effect(cx, expr)
+ } else {
+ false
+ }
+ },
_ => false,
}
}
}
}
-
fn reduce_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<Vec<&'a Expr>> {
if in_macro(expr.span) {
return None;
Some(vec![&**a, &**b])
},
ExprKind::Array(ref v) | ExprKind::Tup(ref v) => Some(v.iter().collect()),
- ExprKind::Repeat(ref inner, _) |
- ExprKind::Cast(ref inner, _) |
- ExprKind::Type(ref inner, _) |
- ExprKind::Unary(_, ref inner) |
- ExprKind::Field(ref inner, _) |
- ExprKind::AddrOf(_, ref inner) |
- ExprKind::Box(ref inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])),
- ExprKind::Struct(_, ref fields, ref base) => if has_drop(cx, expr) {
- None
- } else {
- Some(
- fields
- .iter()
- .map(|f| &f.expr)
- .chain(base)
- .map(Deref::deref)
- .collect(),
- )
+ ExprKind::Repeat(ref inner, _)
+ | ExprKind::Cast(ref inner, _)
+ | ExprKind::Type(ref inner, _)
+ | ExprKind::Unary(_, ref inner)
+ | ExprKind::Field(ref inner, _)
+ | ExprKind::AddrOf(_, ref inner)
+ | ExprKind::Box(ref inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])),
+ ExprKind::Struct(_, ref fields, ref base) => {
+ if has_drop(cx, expr) {
+ None
+ } else {
+ Some(fields.iter().map(|f| &f.expr).chain(base).map(Deref::deref).collect())
+ }
},
- ExprKind::Call(ref callee, ref args) => if let ExprKind::Path(ref qpath) = callee.node {
- let def = cx.tables.qpath_def(qpath, callee.hir_id);
- match def {
- Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..)
- if !has_drop(cx, expr) =>
- {
- Some(args.iter().collect())
- },
- _ => None,
+ ExprKind::Call(ref callee, ref args) => {
+ if let ExprKind::Path(ref qpath) = callee.node {
+ let def = cx.tables.qpath_def(qpath, callee.hir_id);
+ match def {
+ Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..)
+ if !has_drop(cx, expr) =>
+ {
+ Some(args.iter().collect())
+ },
+ _ => None,
+ }
+ } else {
+ None
}
- } else {
- None
},
ExprKind::Block(ref block, _) => {
if block.stmts.is_empty() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! Checks for uses of const which the type is not Freeze (Cell-free).
//!
//! This lint is **deny** by default.
-use crate::rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
-use crate::rustc::hir::*;
use crate::rustc::hir::def::Def;
-use crate::rustc::ty::{self, TypeFlags};
+use crate::rustc::hir::*;
+use crate::rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass};
use crate::rustc::ty::adjustment::Adjust;
+use crate::rustc::ty::{self, TypeFlags};
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
use crate::rustc_typeck::hir_ty_to_ty;
-use crate::syntax_pos::{DUMMY_SP, Span};
-use std::ptr;
+use crate::syntax_pos::{Span, DUMMY_SP};
use crate::utils::{in_constant, in_macro, is_copy, span_lint_and_then};
+use std::ptr;
/// **What it does:** Checks for declaration of `const` items which is interior
/// mutable (e.g. contains a `Cell`, `Mutex`, `AtomicXxxx` etc).
///
/// **Example:**
/// ```rust
-/// use std::sync::atomic::{Ordering::SeqCst, AtomicUsize};
+/// use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
///
/// // Bad.
/// const CONST_ATOM: AtomicUsize = AtomicUsize::new(12);
-/// CONST_ATOM.store(6, SeqCst); // the content of the atomic is unchanged
+/// CONST_ATOM.store(6, SeqCst); // the content of the atomic is unchanged
/// assert_eq!(CONST_ATOM.load(SeqCst), 12); // because the CONST_ATOM in these lines are distinct
///
/// // Good.
///
/// **Example:**
/// ```rust
-/// use std::sync::atomic::{Ordering::SeqCst, AtomicUsize};
+/// use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
/// const CONST_ATOM: AtomicUsize = AtomicUsize::new(12);
///
/// // Bad.
-/// CONST_ATOM.store(6, SeqCst); // the content of the atomic is unchanged
+/// CONST_ATOM.store(6, SeqCst); // the content of the atomic is unchanged
/// assert_eq!(CONST_ATOM.load(SeqCst), 12); // because the CONST_ATOM in these lines are distinct
///
/// // Good.
#[derive(Copy, Clone)]
enum Source {
- Item {
- item: Span,
- },
- Assoc {
- item: Span,
- ty: Span,
- },
- Expr {
- expr: Span,
- },
+ Item { item: Span },
+ Assoc { item: Span, ty: Span },
+ Expr { expr: Span },
}
impl Source {
}
}
-fn verify_ty_bound<'a, 'tcx>(
- cx: &LateContext<'a, 'tcx>,
- ty: ty::Ty<'tcx>,
- source: Source,
-) {
+fn verify_ty_bound<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, source: Source) {
if ty.is_freeze(cx.tcx, cx.param_env, DUMMY_SP) || is_copy(cx, ty) {
// an UnsafeCell is !Copy, and an UnsafeCell is also the only type which
// is !Freeze, thus if our type is Copy we can be sure it must be Freeze
"static".to_string(),
Applicability::MachineApplicable,
);
- }
+ },
Source::Assoc { ty: ty_span, .. } => {
if ty.flags.contains(TypeFlags::HAS_FREE_LOCAL_NAMES) {
db.span_help(ty_span, &format!("consider requiring `{}` to be `Copy`", ty));
}
- }
+ },
Source::Expr { .. } => {
- db.help(
- "assign this const to a local or static variable, and use the variable here",
- );
- }
+ db.help("assign this const to a local or static variable, and use the variable here");
+ },
}
});
}
-
pub struct NonCopyConst;
impl LintPass for NonCopyConst {
fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, trait_item: &'tcx TraitItem) {
if let TraitItemKind::Const(hir_ty, ..) = &trait_item.node {
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
- verify_ty_bound(cx, ty, Source::Assoc { ty: hir_ty.span, item: trait_item.span });
+ verify_ty_bound(
+ cx,
+ ty,
+ Source::Assoc {
+ ty: hir_ty.span,
+ item: trait_item.span,
+ },
+ );
}
}
// ensure the impl is an inherent impl.
if let ItemKind::Impl(_, _, _, _, None, _, _) = item.node {
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
- verify_ty_bound(cx, ty, Source::Assoc { ty: hir_ty.span, item: impl_item.span });
+ verify_ty_bound(
+ cx,
+ ty,
+ Source::Assoc {
+ ty: hir_ty.span,
+ item: impl_item.span,
+ },
+ );
}
}
}
ExprKind::AddrOf(..) => {
// `&e` => `e` must be referenced
needs_check_adjustment = false;
- }
+ },
ExprKind::Field(..) => {
dereferenced_expr = parent_expr;
needs_check_adjustment = true;
- }
+ },
ExprKind::Index(e, _) if ptr::eq(&**e, cur_expr) => {
// `e[i]` => desugared to `*Index::index(&e, i)`,
// meaning `e` must be referenced.
// no need to go further up since a method call is involved now.
needs_check_adjustment = false;
break;
- }
+ },
ExprKind::Unary(UnDeref, _) => {
// `*e` => desugared to `*Deref::deref(&e)`,
// meaning `e` must be referenced.
// no need to go further up since a method call is involved now.
needs_check_adjustment = false;
break;
- }
+ },
_ => break,
}
cur_expr = parent_expr;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use crate::rustc::lint::{LintArray, LintPass, EarlyContext, EarlyLintPass};
+use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use crate::syntax::source_map::Span;
-use crate::syntax::symbol::LocalInternedString;
use crate::syntax::ast::*;
use crate::syntax::attr;
+use crate::syntax::source_map::Span;
+use crate::syntax::symbol::LocalInternedString;
use crate::syntax::visit::{walk_block, walk_expr, walk_pat, Visitor};
use crate::utils::{span_lint, span_lint_and_then};
fn visit_pat(&mut self, pat: &'tcx Pat) {
match pat.node {
PatKind::Ident(_, ident, _) => self.check_name(ident.span, ident.name),
- PatKind::Struct(_, ref fields, _) => for field in fields {
- if !field.node.is_shorthand {
- self.visit_pat(&field.node.pat);
+ PatKind::Struct(_, ref fields, _) => {
+ for field in fields {
+ if !field.node.is_shorthand {
+ self.visit_pat(&field.node.pat);
+ }
}
},
_ => walk_pat(self, pat),
self.0.cx,
MANY_SINGLE_CHAR_NAMES,
span,
- &format!("{}th binding whose name is just one char", self.0.single_char_names.len()),
+ &format!(
+ "{}th binding whose name is just one char",
+ self.0.single_char_names.len()
+ ),
);
}
}
} else {
let mut interned_chars = interned_name.chars();
let mut existing_chars = existing_name.interned.chars();
- let first_i = interned_chars
- .next()
- .expect("we know we have at least one char");
- let first_e = existing_chars
- .next()
- .expect("we know we have at least one char");
+ let first_i = interned_chars.next().expect("we know we have at least one char");
+ let first_e = existing_chars.next().expect("we know we have at least one char");
let eq_or_numeric = |(a, b): (char, char)| a == b || a.is_numeric() && b.is_numeric();
if eq_or_numeric((first_i, first_e)) {
- let last_i = interned_chars
- .next_back()
- .expect("we know we have at least two chars");
- let last_e = existing_chars
- .next_back()
- .expect("we know we have at least two chars");
+ let last_i = interned_chars.next_back().expect("we know we have at least two chars");
+ let last_e = existing_chars.next_back().expect("we know we have at least two chars");
if eq_or_numeric((last_i, last_e)) {
if interned_chars
.zip(existing_chars)
.filter(|&ie| !eq_or_numeric(ie))
- .count() != 1
+ .count()
+ != 1
{
continue;
}
let second_last_e = existing_chars
.next_back()
.expect("we know we have at least three chars");
- if !eq_or_numeric((second_last_i, second_last_e)) || second_last_i == '_'
+ if !eq_or_numeric((second_last_i, second_last_e))
+ || second_last_i == '_'
|| !interned_chars.zip(existing_chars).all(eq_or_numeric)
{
// allowed similarity foo_x, foo_y
split_at = interned_name.char_indices().rev().next().map(|(i, _)| i);
}
} else {
- let second_i = interned_chars
- .next()
- .expect("we know we have at least two chars");
- let second_e = existing_chars
- .next()
- .expect("we know we have at least two chars");
- if !eq_or_numeric((second_i, second_e)) || second_i == '_'
+ let second_i = interned_chars.next().expect("we know we have at least two chars");
+ let second_e = existing_chars.next().expect("we know we have at least two chars");
+ if !eq_or_numeric((second_i, second_e))
+ || second_i == '_'
|| !interned_chars.zip(existing_chars).all(eq_or_numeric)
{
// allowed similarity x_foo, y_foo
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
-use crate::rustc::hir::*;
use crate::utils::{match_type, method_chain_args, paths, snippet, span_help_and_lint};
+use if_chain::if_chain;
/// **What it does:*** Checks for unnecessary `ok()` in if let.
///
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir::{Expr, ExprKind};
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
}
if read && truncate && read_arg && truncate_arg && !(write && write_arg) {
- span_lint(cx, NONSENSICAL_OPEN_OPTIONS, span, "file opened with \"truncate\" and \"read\"");
+ span_lint(
+ cx,
+ NONSENSICAL_OPEN_OPTIONS,
+ span,
+ "file opened with \"truncate\" and \"read\"",
+ );
}
if append && truncate && append_arg && truncate_arg {
span_lint(
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
-use crate::rustc::hir::*;
use crate::utils::{span_lint, SpanlessEq};
+use if_chain::if_chain;
/// **What it does:** Detects classic underflow/overflow checks.
///
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
use crate::syntax::ast::LitKind;
-use crate::syntax::ptr::P;
use crate::syntax::ext::quote::rt::Span;
+use crate::syntax::ptr::P;
use crate::utils::{is_direct_expn_of, is_expn_of, match_def_path, opt_def_id, paths, resolve_node, span_lint};
+use if_chain::if_chain;
/// **What it does:** Checks for missing parameters in `panic!`.
///
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
-use crate::rustc::hir::*;
use crate::utils::{is_automatically_derived, span_lint};
+use if_chain::if_chain;
/// **What it does:** Checks for manual re-implementations of `PartialEq::ne`.
///
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
expr.span,
"unary minus has lower precedence than method call",
"consider adding parentheses to clarify your intent",
- format!("-({})", snippet_with_applicability(cx, rhs.span, "..", &mut applicability)),
+ format!(
+ "-({})",
+ snippet_with_applicability(cx, rhs.span, "..", &mut applicability)
+ ),
applicability,
);
},
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! Checks for usage of `&Vec[_]` and `&String`.
-use std::borrow::Cow;
-use crate::rustc::hir::*;
use crate::rustc::hir::QPath;
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
use crate::rustc::ty;
+use crate::rustc::{declare_tool_lint, lint_array};
+use crate::rustc_errors::Applicability;
use crate::syntax::ast::NodeId;
use crate::syntax::source_map::Span;
use crate::syntax_pos::MultiSpan;
-use crate::utils::{match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_then, walk_ptrs_hir_ty};
use crate::utils::ptr::get_spans;
-use crate::rustc_errors::Applicability;
+use crate::utils::{match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_then, walk_ptrs_hir_ty};
+use if_chain::if_chain;
+use std::borrow::Cow;
/// **What it does:** This lint checks for function arguments of type `&String`
/// or `&Vec` unless the references are mutable. It will also suggest you
declare_clippy_lint! {
pub PTR_ARG,
style,
- "fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` \
- instead, respectively"
+ "fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively"
}
/// **What it does:** This lint checks for equality comparisons with `ptr::null`
///
/// **Example:**
/// ```rust
-/// if x == ptr::null { .. }
+/// if x == ptr::null {
+/// ..
+/// }
/// ```
declare_clippy_lint! {
pub CMP_NULL,
let fn_ty = sig.skip_binder();
for (idx, (arg, ty)) in decl.inputs.iter().zip(fn_ty.inputs()).enumerate() {
- if let ty::Ref(
- _,
- ty,
- MutImmutable
- ) = ty.sty
- {
+ if let ty::Ref(_, ty, MutImmutable) = ty.sty {
if match_type(cx, ty, &paths::VEC) {
let mut ty_snippet = None;
if_chain! {
|db| {
if let Some(ref snippet) = ty_snippet {
db.span_suggestion_with_applicability(
- arg.span,
- "change this to",
- format!("&[{}]", snippet),
- Applicability::Unspecified,
- );
+ arg.span,
+ "change this to",
+ format!("&[{}]", snippet),
+ Applicability::Unspecified,
+ );
}
for (clonespan, suggestion) in spans {
db.span_suggestion_with_applicability(
clonespan,
- &snippet_opt(cx, clonespan).map_or(
- "change the call to".into(),
- |x| Cow::Owned(format!("change `{}` to", x)),
- ),
+ &snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| {
+ Cow::Owned(format!("change `{}` to", x))
+ }),
suggestion.into(),
Applicability::Unspecified,
);
for (clonespan, suggestion) in spans {
db.span_suggestion_short_with_applicability(
clonespan,
- &snippet_opt(cx, clonespan).map_or(
- "change the call to".into(),
- |x| Cow::Owned(format!("change `{}` to", x)),
- ),
+ &snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| {
+ Cow::Owned(format!("change `{}` to", x))
+ }),
suggestion.into(),
Applicability::Unspecified,
);
if let FunctionRetTy::Return(ref ty) = decl.output {
if let Some((out, MutMutable, _)) = get_rptr_lm(ty) {
let mut immutables = vec![];
- for (_, ref mutbl, ref argspan) in decl.inputs
+ for (_, ref mutbl, ref argspan) in decl
+ .inputs
.iter()
.filter_map(|ty| get_rptr_lm(ty))
.filter(|&(lt, _, _)| lt.name == out.name)
if immutables.is_empty() {
return;
}
- span_lint_and_then(cx, MUT_FROM_REF, ty.span, "mutable borrow from immutable input(s)", |db| {
- let ms = MultiSpan::from_spans(immutables);
- db.span_note(ms, "immutable borrow here");
- });
+ span_lint_and_then(
+ cx,
+ MUT_FROM_REF,
+ ty.span,
+ "mutable borrow from immutable input(s)",
+ |db| {
+ let ms = MultiSpan::from_spans(immutables);
+ db.span_note(ms, "immutable borrow here");
+ },
+ );
}
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::{declare_tool_lint, hir, lint, lint_array};
use crate::rustc_errors::Applicability;
use crate::utils;
/// let ptr = vec.as_ptr();
/// let offset = 1_usize;
///
-/// unsafe { ptr.offset(offset as isize); }
+/// unsafe {
+/// ptr.offset(offset as isize);
+/// }
/// ```
///
/// Could be written:
/// let ptr = vec.as_ptr();
/// let offset = 1_usize;
///
-/// unsafe { ptr.add(offset); }
+/// unsafe {
+/// ptr.add(offset);
+/// }
/// ```
declare_clippy_lint! {
pub PTR_OFFSET_WITH_CAST,
} else {
utils::span_lint(cx, PTR_OFFSET_WITH_CAST, expr.span, &msg);
}
-
}
}
}
// Is the type of the expression a usize?
-fn is_expr_ty_usize<'a, 'tcx>(
- cx: &lint::LateContext<'a, 'tcx>,
- expr: &hir::Expr,
-) -> bool {
+fn is_expr_ty_usize<'a, 'tcx>(cx: &lint::LateContext<'a, 'tcx>, expr: &hir::Expr) -> bool {
cx.tables.expr_ty(expr) == cx.tcx.types.usize
}
// Is the type of the expression a raw pointer?
-fn is_expr_ty_raw_ptr<'a, 'tcx>(
- cx: &lint::LateContext<'a, 'tcx>,
- expr: &hir::Expr,
-) -> bool {
+fn is_expr_ty_raw_ptr<'a, 'tcx>(cx: &lint::LateContext<'a, 'tcx>, expr: &hir::Expr) -> bool {
cx.tables.expr_ty(expr).is_unsafe_ptr()
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::def::Def;
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
-use crate::rustc::hir::*;
-use crate::rustc::hir::def::Def;
-use crate::utils::sugg::Sugg;
use crate::syntax::ptr::P;
+use crate::utils::sugg::Sugg;
+use if_chain::if_chain;
-use crate::utils::{match_def_path, match_type, span_lint_and_then};
-use crate::utils::paths::*;
use crate::rustc_errors::Applicability;
+use crate::utils::paths::*;
+use crate::utils::{match_def_path, match_type, span_lint_and_then};
/// **What it does:** Checks for expressions that could be replaced by the question mark operator
///
/// ```rust
/// option?;
/// ```
-declare_clippy_lint!{
+declare_clippy_lint! {
pub QUESTION_MARK,
style,
"checks for expressions that could be replaced by the question mark operator"
false
},
- ExprKind::Ret(Some(ref expr)) => {
- Self::expression_returns_none(cx, expr)
- },
+ ExprKind::Ret(Some(ref expr)) => Self::expression_returns_none(cx, expr),
ExprKind::Path(ref qp) => {
if let Def::VariantCtor(def_id, _) = cx.tables.qpath_def(qp, expression.hir_id) {
- return match_def_path(cx.tcx, def_id, &OPTION_NONE);
+ return match_def_path(cx.tcx, def_id, &OPTION_NONE);
}
false
},
- _ => false
+ _ => false,
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
-use crate::rustc::hir::*;
+use crate::rustc_errors::Applicability;
use crate::syntax::ast::RangeLimits;
use crate::syntax::source_map::Spanned;
-use crate::utils::{is_integer_literal, paths, snippet, span_lint, span_lint_and_then, snippet_opt};
-use crate::utils::{get_trait_def_id, higher, implements_trait, SpanlessEq};
use crate::utils::sugg::Sugg;
-use crate::rustc_errors::Applicability;
+use crate::utils::{get_trait_def_id, higher, implements_trait, SpanlessEq};
+use crate::utils::{is_integer_literal, paths, snippet, snippet_opt, span_lint, span_lint_and_then};
+use if_chain::if_chain;
/// **What it does:** Checks for calling `.step_by(0)` on iterators,
/// which never terminates.
///
/// **Example:**
/// ```rust
-/// for x in (5..5).step_by(0) { .. }
+/// for x in (5..5).step_by(0) {
+/// ..
+/// }
/// ```
declare_clippy_lint! {
pub ITERATOR_STEP_BY_ZERO,
impl LintPass for Pass {
fn get_lints(&self) -> LintArray {
- lint_array!(ITERATOR_STEP_BY_ZERO, RANGE_ZIP_WITH_LEN, RANGE_PLUS_ONE, RANGE_MINUS_ONE)
+ lint_array!(
+ ITERATOR_STEP_BY_ZERO,
+ RANGE_ZIP_WITH_LEN,
+ RANGE_PLUS_ONE,
+ RANGE_MINUS_ONE
+ )
}
}
// exclusive range plus one: x..(y+1)
if_chain! {
- if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::HalfOpen }) = higher::range(cx, expr);
+ if let Some(higher::Range {
+ start,
+ end: Some(end),
+ limits: RangeLimits::HalfOpen
+ }) = higher::range(cx, expr);
if let Some(y) = y_plus_one(end);
then {
span_lint_and_then(
fn y_plus_one(expr: &Expr) -> Option<&Expr> {
match expr.node {
- ExprKind::Binary(Spanned { node: BinOpKind::Add, .. }, ref lhs, ref rhs) => if is_integer_literal(lhs, 1) {
- Some(rhs)
- } else if is_integer_literal(rhs, 1) {
- Some(lhs)
- } else {
- None
+ ExprKind::Binary(
+ Spanned {
+ node: BinOpKind::Add, ..
+ },
+ ref lhs,
+ ref rhs,
+ ) => {
+ if is_integer_literal(lhs, 1) {
+ Some(rhs)
+ } else if is_integer_literal(rhs, 1) {
+ Some(lhs)
+ } else {
+ None
+ }
},
_ => None,
}
fn y_minus_one(expr: &Expr) -> Option<&Expr> {
match expr.node {
- ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, ref lhs, ref rhs) if is_integer_literal(rhs, 1) => Some(lhs),
+ ExprKind::Binary(
+ Spanned {
+ node: BinOpKind::Sub, ..
+ },
+ ref lhs,
+ ref rhs,
+ ) if is_integer_literal(rhs, 1) => Some(lhs),
_ => None,
}
}
fn visit_local(&mut self, local: &mir::Local, ctx: PlaceContext<'tcx>, _: mir::Location) {
match ctx {
- PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(NonUseContext::StorageDead) => return,
+ PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(NonUseContext::StorageDead) => {
+ return
+ },
_ => {},
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
use crate::syntax::ast::*;
-use crate::utils::{span_lint_and_sugg};
+use crate::utils::span_lint_and_sugg;
/// **What it does:** Checks for fields in struct literals where shorthands
/// could be used.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use crate::rustc::hir::*;
-use crate::syntax::ptr::P;
+use crate::rustc_errors::Applicability;
use crate::syntax::ast::LitKind;
+use crate::syntax::ptr::P;
use crate::utils::{match_qpath, paths, snippet, span_lint_and_then};
-use crate::rustc_errors::Applicability;
/// **What it does:** Lint for redundant pattern matching over `Result` or
/// `Option`
/// if Some(42).is_some() {}
/// Ok::<i32, i32>(42).is_ok();
/// ```
-///
declare_clippy_lint! {
pub REDUNDANT_PATTERN_MATCHING,
style,
}
}
-fn find_sugg_for_if_let<'a, 'tcx>(
- cx: &LateContext<'a, 'tcx>,
- expr: &'tcx Expr,
- op: &P<Expr>,
- arms: &HirVec<Arm>
-) {
+fn find_sugg_for_if_let<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, op: &P<Expr>, arms: &HirVec<Arm>) {
if arms[0].pats.len() == 1 {
let good_method = match arms[0].pats[0].node {
PatKind::TupleStruct(ref path, ref patterns, _) if patterns.len() == 1 => {
}
}
-fn find_sugg_for_match<'a, 'tcx>(
- cx: &LateContext<'a, 'tcx>,
- expr: &'tcx Expr,
- op: &P<Expr>,
- arms: &HirVec<Arm>
-) {
+fn find_sugg_for_match<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, op: &P<Expr>, arms: &HirVec<Arm>) {
if arms.len() == 2 {
let node_pair = (&arms[0].pats[0].node, &arms[1].pats[0].node);
let found_good_method = match node_pair {
(
PatKind::TupleStruct(ref path_left, ref patterns_left, _),
- PatKind::TupleStruct(ref path_right, ref patterns_right, _)
+ PatKind::TupleStruct(ref path_right, ref patterns_right, _),
) if patterns_left.len() == 1 && patterns_right.len() == 1 => {
if let (PatKind::Wild, PatKind::Wild) = (&patterns_left[0].node, &patterns_right[0].node) {
find_good_method_for_match(
&paths::RESULT_OK,
&paths::RESULT_ERR,
"is_ok()",
- "is_err()"
+ "is_err()",
)
} else {
None
}
},
- (
- PatKind::TupleStruct(ref path_left, ref patterns, _),
- PatKind::Path(ref path_right)
- ) | (
- PatKind::Path(ref path_left),
- PatKind::TupleStruct(ref path_right, ref patterns, _)
- ) if patterns.len() == 1 => {
+ (PatKind::TupleStruct(ref path_left, ref patterns, _), PatKind::Path(ref path_right))
+ | (PatKind::Path(ref path_left), PatKind::TupleStruct(ref path_right, ref patterns, _))
+ if patterns.len() == 1 =>
+ {
if let PatKind::Wild = patterns[0].node {
find_good_method_for_match(
arms,
&paths::OPTION_SOME,
&paths::OPTION_NONE,
"is_some()",
- "is_none()"
+ "is_none()",
)
} else {
None
expected_left: &[&str],
expected_right: &[&str],
should_be_left: &'a str,
- should_be_right: &'a str
+ should_be_right: &'a str,
) -> Option<&'a str> {
let body_node_pair = if match_qpath(path_left, expected_left) && match_qpath(path_right, expected_right) {
(&(*arms[0].body).node, &(*arms[1].body).node)
};
match body_node_pair {
- (ExprKind::Lit(ref lit_left), ExprKind::Lit(ref lit_right)) => {
- match (&lit_left.node, &lit_right.node) {
- (LitKind::Bool(true), LitKind::Bool(false)) => Some(should_be_left),
- (LitKind::Bool(false), LitKind::Bool(true)) => Some(should_be_right),
- _ => None,
- }
+ (ExprKind::Lit(ref lit_left), ExprKind::Lit(ref lit_right)) => match (&lit_left.node, &lit_right.node) {
+ (LitKind::Bool(true), LitKind::Bool(false)) => Some(should_be_left),
+ (LitKind::Bool(false), LitKind::Bool(true)) => Some(should_be_right),
+ _ => None,
},
_ => None,
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use regex_syntax;
+use crate::consts::{constant, Constant};
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_data_structures::fx::FxHashSet;
-use if_chain::if_chain;
use crate::syntax::ast::{LitKind, NodeId, StrStyle};
use crate::syntax::source_map::{BytePos, Span};
use crate::utils::{is_expn_of, match_def_path, match_type, opt_def_id, paths, span_help_and_lint, span_lint};
-use crate::consts::{constant, Constant};
+use if_chain::if_chain;
+use regex_syntax;
use std::convert::TryFrom;
/// **What it does:** Checks [regex](https://crates.io/crates/regex) creation
}
fn is_trivial_regex(s: ®ex_syntax::hir::Hir) -> Option<&'static str> {
- use regex_syntax::hir::HirKind::*;
use regex_syntax::hir::Anchor::*;
+ use regex_syntax::hir::HirKind::*;
- let is_literal = |e: &[regex_syntax::hir::Hir]| e.iter().all(|e| match *e.kind() {
- Literal(_) => true,
- _ => false,
- });
+ let is_literal = |e: &[regex_syntax::hir::Hir]| {
+ e.iter().all(|e| match *e.kind() {
+ Literal(_) => true,
+ _ => false,
+ })
+ };
match *s.kind() {
- Empty |
- Anchor(_) => Some("the regex is unlikely to be useful as it is"),
+ Empty | Anchor(_) => Some("the regex is unlikely to be useful as it is"),
Literal(_) => Some("consider using `str::contains`"),
- Alternation(ref exprs) => if exprs.iter().all(|e| e.kind().is_empty()) {
- Some("the regex is unlikely to be useful as it is")
- } else {
- None
+ Alternation(ref exprs) => {
+ if exprs.iter().all(|e| e.kind().is_empty()) {
+ Some("the regex is unlikely to be useful as it is")
+ } else {
+ None
+ }
},
Concat(ref exprs) => match (exprs[0].kind(), exprs[exprs.len() - 1].kind()) {
- (&Anchor(StartText), &Anchor(EndText)) if exprs[1..(exprs.len() - 1)].is_empty() => Some("consider using `str::is_empty`"),
- (&Anchor(StartText), &Anchor(EndText)) if is_literal(&exprs[1..(exprs.len() - 1)]) => Some("consider using `==` on `str`s"),
+ (&Anchor(StartText), &Anchor(EndText)) if exprs[1..(exprs.len() - 1)].is_empty() => {
+ Some("consider using `str::is_empty`")
+ },
+ (&Anchor(StartText), &Anchor(EndText)) if is_literal(&exprs[1..(exprs.len() - 1)]) => {
+ Some("consider using `==` on `str`s")
+ },
(&Anchor(StartText), &Literal(_)) if is_literal(&exprs[1..]) => Some("consider using `str::starts_with`"),
- (&Literal(_), &Anchor(EndText)) if is_literal(&exprs[1..(exprs.len() - 1)]) => Some("consider using `str::ends_with`"),
+ (&Literal(_), &Anchor(EndText)) if is_literal(&exprs[1..(exprs.len() - 1)]) => {
+ Some("consider using `str::ends_with`")
+ },
_ if is_literal(exprs) => Some("consider using `str::contains`"),
_ => None,
},
let r = &r.as_str();
let offset = if let StrStyle::Raw(n) = style { 2 + n } else { 1 };
match parser.parse(r) {
- Ok(r) => if let Some(repl) = is_trivial_regex(&r) {
- span_help_and_lint(
- cx,
- TRIVIAL_REGEX,
- expr.span,
- "trivial regex",
- repl,
- );
+ Ok(r) => {
+ if let Some(repl) = is_trivial_regex(&r) {
+ span_help_and_lint(cx, TRIVIAL_REGEX, expr.span, "trivial regex", repl);
+ }
},
Err(regex_syntax::Error::Parse(e)) => {
span_lint(
);
},
Err(e) => {
- span_lint(
- cx,
- INVALID_REGEX,
- expr.span,
- &format!("regex syntax error: {}", e),
- );
+ span_lint(cx, INVALID_REGEX, expr.span, &format!("regex syntax error: {}", e));
},
}
}
} else if let Some(r) = const_str(cx, expr) {
match parser.parse(&r) {
- Ok(r) => if let Some(repl) = is_trivial_regex(&r) {
- span_help_and_lint(
- cx,
- TRIVIAL_REGEX,
- expr.span,
- "trivial regex",
- repl,
- );
+ Ok(r) => {
+ if let Some(repl) = is_trivial_regex(&r) {
+ span_help_and_lint(cx, TRIVIAL_REGEX, expr.span, "trivial regex", repl);
+ }
},
Err(regex_syntax::Error::Parse(e)) => {
span_lint(
);
},
Err(e) => {
- span_lint(
- cx,
- INVALID_REGEX,
- expr.span,
- &format!("regex syntax error: {}", e),
- );
+ span_lint(cx, INVALID_REGEX, expr.span, &format!("regex syntax error: {}", e));
},
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir;
use crate::rustc::hir::def::Def;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
const REPLACEMENTS: &[(&[&str], &str)] = &[
// Once
- (&["core", "sync", "ONCE_INIT"], "Once::new()"),
+ (&["core", "sync", "ONCE_INIT"], "Once::new()"),
// Atomic
- (&["core", "sync", "atomic", "ATOMIC_BOOL_INIT"], "AtomicBool::new(false)"),
+ (
+ &["core", "sync", "atomic", "ATOMIC_BOOL_INIT"],
+ "AtomicBool::new(false)",
+ ),
(&["core", "sync", "atomic", "ATOMIC_ISIZE_INIT"], "AtomicIsize::new(0)"),
- (&["core", "sync", "atomic", "ATOMIC_I8_INIT"], "AtomicI8::new(0)"),
- (&["core", "sync", "atomic", "ATOMIC_I16_INIT"], "AtomicI16::new(0)"),
- (&["core", "sync", "atomic", "ATOMIC_I32_INIT"], "AtomicI32::new(0)"),
- (&["core", "sync", "atomic", "ATOMIC_I64_INIT"], "AtomicI64::new(0)"),
+ (&["core", "sync", "atomic", "ATOMIC_I8_INIT"], "AtomicI8::new(0)"),
+ (&["core", "sync", "atomic", "ATOMIC_I16_INIT"], "AtomicI16::new(0)"),
+ (&["core", "sync", "atomic", "ATOMIC_I32_INIT"], "AtomicI32::new(0)"),
+ (&["core", "sync", "atomic", "ATOMIC_I64_INIT"], "AtomicI64::new(0)"),
(&["core", "sync", "atomic", "ATOMIC_USIZE_INIT"], "AtomicUsize::new(0)"),
- (&["core", "sync", "atomic", "ATOMIC_U8_INIT"], "AtomicU8::new(0)"),
- (&["core", "sync", "atomic", "ATOMIC_U16_INIT"], "AtomicU16::new(0)"),
- (&["core", "sync", "atomic", "ATOMIC_U32_INIT"], "AtomicU32::new(0)"),
- (&["core", "sync", "atomic", "ATOMIC_U64_INIT"], "AtomicU64::new(0)"),
+ (&["core", "sync", "atomic", "ATOMIC_U8_INIT"], "AtomicU8::new(0)"),
+ (&["core", "sync", "atomic", "ATOMIC_U16_INIT"], "AtomicU16::new(0)"),
+ (&["core", "sync", "atomic", "ATOMIC_U32_INIT"], "AtomicU32::new(0)"),
+ (&["core", "sync", "atomic", "ATOMIC_U64_INIT"], "AtomicU64::new(0)"),
// Min
(&["core", "isize", "MIN"], "isize::min_value()"),
- (&["core", "i8", "MIN"], "i8::min_value()"),
- (&["core", "i16", "MIN"], "i16::min_value()"),
- (&["core", "i32", "MIN"], "i32::min_value()"),
- (&["core", "i64", "MIN"], "i64::min_value()"),
- (&["core", "i128", "MIN"], "i128::min_value()"),
+ (&["core", "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()"),
+ (&["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", "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()"),
+ (&["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()"),
];
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass, in_external_macro, LintContext};
+use crate::rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
+use crate::rustc_errors::Applicability;
use crate::syntax::ast;
use crate::syntax::source_map::Span;
use crate::syntax::visit::FnKind;
use crate::syntax_pos::BytePos;
-use crate::rustc_errors::Applicability;
use crate::utils::{in_macro, match_path_ast, snippet_opt, span_lint_and_then, span_note_and_lint};
+use if_chain::if_chain;
/// **What it does:** Checks for return statements at the end of a block.
///
///
/// **Example:**
/// ```rust
-/// fn foo(x: usize) { return x; }
+/// fn foo(x: usize) {
+/// return x;
+/// }
/// ```
/// simplify to
/// ```rust
-/// fn foo(x: usize) { x }
+/// fn foo(x: usize) {
+/// x
+/// }
/// ```
declare_clippy_lint! {
pub NEEDLESS_RETURN,
/// **Example:**
/// ```rust
/// fn foo() -> String {
-/// let x = String::new();
-/// x
-///}
+/// let x = String::new();
+/// x
+/// }
/// ```
/// instead, use
/// ```
/// fn foo() -> String {
-/// String::new()
-///}
+/// String::new()
+/// }
/// ```
declare_clippy_lint! {
pub LET_AND_RETURN,
style,
- "creating a let-binding and then immediately returning it like `let x = expr; x` at \
- the end of a block"
+ "creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block"
}
/// **What it does:** Checks for unit (`()`) expressions that can be removed.
///
/// **Example:**
/// ```rust
-/// fn return_unit() -> () { () }
+/// fn return_unit() -> () {
+/// ()
+/// }
/// ```
declare_clippy_lint! {
pub UNUSED_UNIT,
self.check_final_expr(cx, elsexpr, None);
},
// a match expr, check all arms
- ast::ExprKind::Match(_, ref arms) => for arm in arms {
- self.check_final_expr(cx, &arm.body, Some(arm.body.span));
+ ast::ExprKind::Match(_, ref arms) => {
+ for arm in arms {
+ self.check_final_expr(cx, &arm.body, Some(arm.body.span));
+ }
},
_ => (),
}
);
});
}
- }
- _ => ()
+ },
+ _ => (),
}
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use crate::rustc::hir::*;
use crate::utils::{get_trait_def_id, paths, span_lint};
/// **What it does:** Checks for mis-uses of the serde API.
"various things that will negatively affect your serde experience"
}
-
#[derive(Copy, Clone)]
pub struct Serde;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::reexport::*;
-use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, in_external_macro, LintContext};
-use crate::rustc::{declare_tool_lint, lint_array};
-use crate::rustc::hir::*;
use crate::rustc::hir::intravisit::FnKind;
+use crate::rustc::hir::*;
+use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
use crate::rustc::ty;
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::source_map::Span;
use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then};
declare_clippy_lint! {
pub SHADOW_REUSE,
restriction,
- "rebinding a name to an expression that re-uses the original value, e.g. \
- `let x = x + 1`"
+ "rebinding a name to an expression that re-uses the original value, e.g. `let x = x + 1`"
}
/// **What it does:** Checks for bindings that shadow other bindings already in
///
/// **Example:**
/// ```rust
-/// let x = y; let x = z; // shadows the earlier binding
+/// let x = y;
+/// let x = z; // shadows the earlier binding
/// ```
declare_clippy_lint! {
pub SHADOW_UNRELATED,
check_pat(cx, p, init, span, bindings);
}
},
- PatKind::Struct(_, ref pfields, _) => if let Some(init_struct) = init {
- if let ExprKind::Struct(_, ref efields, _) = init_struct.node {
- for field in pfields {
- let name = field.node.ident.name;
- let efield = efields
- .iter()
- .find(|f| f.ident.name == name)
- .map(|f| &*f.expr);
- check_pat(cx, &field.node.pat, efield, span, bindings);
+ PatKind::Struct(_, ref pfields, _) => {
+ if let Some(init_struct) = init {
+ if let ExprKind::Struct(_, ref efields, _) = init_struct.node {
+ for field in pfields {
+ let name = field.node.ident.name;
+ let efield = efields.iter().find(|f| f.ident.name == name).map(|f| &*f.expr);
+ check_pat(cx, &field.node.pat, efield, span, bindings);
+ }
+ } else {
+ for field in pfields {
+ check_pat(cx, &field.node.pat, init, span, bindings);
+ }
}
} else {
for field in pfields {
- check_pat(cx, &field.node.pat, init, span, bindings);
+ check_pat(cx, &field.node.pat, None, span, bindings);
}
}
- } else {
- for field in pfields {
- check_pat(cx, &field.node.pat, None, span, bindings);
- }
},
- PatKind::Tuple(ref inner, _) => if let Some(init_tup) = init {
- if let ExprKind::Tup(ref tup) = init_tup.node {
- for (i, p) in inner.iter().enumerate() {
- check_pat(cx, p, Some(&tup[i]), p.span, bindings);
+ PatKind::Tuple(ref inner, _) => {
+ if let Some(init_tup) = init {
+ if let ExprKind::Tup(ref tup) = init_tup.node {
+ for (i, p) in inner.iter().enumerate() {
+ check_pat(cx, p, Some(&tup[i]), p.span, bindings);
+ }
+ } else {
+ for p in inner {
+ check_pat(cx, p, init, span, bindings);
+ }
}
} else {
for p in inner {
- check_pat(cx, p, init, span, bindings);
+ check_pat(cx, p, None, span, bindings);
}
}
- } else {
- for p in inner {
- check_pat(cx, p, None, span, bindings);
- }
},
- PatKind::Box(ref inner) => if let Some(initp) = init {
- if let ExprKind::Box(ref inner_init) = initp.node {
- check_pat(cx, inner, Some(&**inner_init), span, bindings);
+ PatKind::Box(ref inner) => {
+ if let Some(initp) = init {
+ if let ExprKind::Box(ref inner_init) = initp.node {
+ check_pat(cx, inner, Some(&**inner_init), span, bindings);
+ } else {
+ check_pat(cx, inner, init, span, bindings);
+ }
} else {
check_pat(cx, inner, init, span, bindings);
}
- } else {
- check_pat(cx, inner, init, span, bindings);
},
PatKind::Ref(ref inner, _) => check_pat(cx, inner, init, span, bindings),
// PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>),
ExprKind::Block(ref block, _) | ExprKind::Loop(ref block, _, _) => check_block(cx, block, bindings),
// ExprKind::Call
// ExprKind::MethodCall
- ExprKind::Array(ref v) | ExprKind::Tup(ref v) => for e in v {
- check_expr(cx, e, bindings)
+ ExprKind::Array(ref v) | ExprKind::Tup(ref v) => {
+ for e in v {
+ check_expr(cx, e, bindings)
+ }
},
ExprKind::If(ref cond, ref then, ref otherwise) => {
check_expr(cx, cond, bindings);
check_ty(cx, fty, bindings);
check_expr(cx, &cx.tcx.hir.body(anon_const.body).value, bindings);
},
- TyKind::Ptr(MutTy { ty: ref mty, .. }) | TyKind::Rptr(_, MutTy { ty: ref mty, .. }) => check_ty(cx, mty, bindings),
- TyKind::Tup(ref tup) => for t in tup {
- check_ty(cx, t, bindings)
+ TyKind::Ptr(MutTy { ty: ref mty, .. }) | TyKind::Rptr(_, MutTy { ty: ref mty, .. }) => {
+ check_ty(cx, mty, bindings)
+ },
+ TyKind::Tup(ref tup) => {
+ for t in tup {
+ check_ty(cx, t, bindings)
+ }
},
TyKind::Typeof(ref anon_const) => check_expr(cx, &cx.tcx.hir.body(anon_const.body).value, bindings),
_ => (),
match expr.node {
ExprKind::Box(ref inner) | ExprKind::AddrOf(_, ref inner) => is_self_shadow(name, inner),
ExprKind::Block(ref block, _) => {
- block.stmts.is_empty()
- && block
- .expr
- .as_ref()
- .map_or(false, |e| is_self_shadow(name, e))
+ block.stmts.is_empty() && block.expr.as_ref().map_or(false, |e| is_self_shadow(name, e))
},
ExprKind::Unary(op, ref inner) => (UnDeref == op) && is_self_shadow(name, inner),
ExprKind::Path(QPath::Resolved(_, ref path)) => path_eq_name(name, path),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use crate::rustc::hir::intravisit::{walk_expr, walk_stmt, walk_block, NestedVisitorMap, Visitor};
-use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, Lint};
-use crate::rustc::{declare_tool_lint, lint_array};
+use crate::rustc::hir::intravisit::{walk_block, walk_expr, walk_stmt, NestedVisitorMap, Visitor};
use crate::rustc::hir::*;
-use if_chain::if_chain;
-use crate::syntax_pos::symbol::Symbol;
+use crate::rustc::lint::{LateContext, LateLintPass, Lint, LintArray, LintPass};
+use crate::rustc::{declare_tool_lint, lint_array};
+use crate::rustc_errors::Applicability;
use crate::syntax::ast::{LitKind, NodeId};
-use crate::utils::{match_qpath, span_lint_and_then, SpanlessEq, get_enclosing_block};
+use crate::syntax_pos::symbol::Symbol;
use crate::utils::sugg::Sugg;
-use crate::rustc_errors::{Applicability};
+use crate::utils::{get_enclosing_block, match_qpath, span_lint_and_then, SpanlessEq};
+use if_chain::if_chain;
/// **What it does:** Checks slow zero-filled vector initialization
///
/// **Example:**
/// ```rust
/// let mut vec1 = Vec::with_capacity(len);
-/// unsafe { vec1.set_len(len); }
+/// unsafe {
+/// vec1.set_len(len);
+/// }
/// ```
declare_clippy_lint! {
pub UNSAFE_VECTOR_INITIALIZATION,
impl LintPass for Pass {
fn get_lints(&self) -> LintArray {
- lint_array!(
- SLOW_VECTOR_INITIALIZATION,
- UNSAFE_VECTOR_INITIALIZATION,
- )
+ lint_array!(SLOW_VECTOR_INITIALIZATION, UNSAFE_VECTOR_INITIALIZATION,)
}
}
}
/// Search initialization for the given vector
- fn search_initialization<'tcx>(
- cx: &LateContext<'_, 'tcx>,
- vec_alloc: VecAllocation<'tcx>,
- parent_node: NodeId
- ) {
+ fn search_initialization<'tcx>(cx: &LateContext<'_, 'tcx>, vec_alloc: VecAllocation<'tcx>, parent_node: NodeId) {
let enclosing_body = get_enclosing_block(cx, parent_node);
if enclosing_body.is_none() {
}
}
- fn lint_initialization<'tcx>(cx: &LateContext<'_, 'tcx>, initialization: &InitializationType<'tcx>, vec_alloc: &VecAllocation<'_>) {
+ fn lint_initialization<'tcx>(
+ cx: &LateContext<'_, 'tcx>,
+ initialization: &InitializationType<'tcx>,
+ vec_alloc: &VecAllocation<'_>,
+ ) {
match initialization {
- InitializationType::UnsafeSetLen(e) =>
- Self::emit_lint(
- cx,
- e,
- vec_alloc,
- "unsafe vector initialization",
- UNSAFE_VECTOR_INITIALIZATION
- ),
-
- InitializationType::Extend(e) |
- InitializationType::Resize(e) =>
- Self::emit_lint(
- cx,
- e,
- vec_alloc,
- "slow zero-filling initialization",
- SLOW_VECTOR_INITIALIZATION
- )
+ InitializationType::UnsafeSetLen(e) => Self::emit_lint(
+ cx,
+ e,
+ vec_alloc,
+ "unsafe vector initialization",
+ UNSAFE_VECTOR_INITIALIZATION,
+ ),
+
+ InitializationType::Extend(e) | InitializationType::Resize(e) => Self::emit_lint(
+ cx,
+ e,
+ vec_alloc,
+ "slow zero-filling initialization",
+ SLOW_VECTOR_INITIALIZATION,
+ ),
};
}
slow_fill: &Expr,
vec_alloc: &VecAllocation<'_>,
msg: &str,
- lint: &'static Lint
+ lint: &'static Lint,
) {
let len_expr = Sugg::hir(cx, vec_alloc.len_expr, "len");
- span_lint_and_then(
- cx,
- lint,
- slow_fill.span,
- msg,
- |db| {
- db.span_suggestion_with_applicability(
- vec_alloc.allocation_expr.span,
- "consider replace allocation with",
- format!("vec![0; {}]", len_expr),
- Applicability::Unspecified
- );
- }
- );
+ span_lint_and_then(cx, lint, slow_fill.span, msg, |db| {
+ db.span_suggestion_with_applicability(
+ vec_alloc.allocation_expr.span,
+ "consider replace allocation with",
+ format!("vec![0; {}]", len_expr),
+ Applicability::Unspecified,
+ );
+ });
}
}
fn visit_stmt(&mut self, stmt: &'tcx Stmt) {
if self.initialization_found {
match stmt.node {
- StmtKind::Expr(ref expr, _) |
- StmtKind::Semi(ref expr, _) => {
+ StmtKind::Expr(ref expr, _) | StmtKind::Semi(ref expr, _) => {
self.search_slow_extend_filling(expr);
self.search_slow_resize_filling(expr);
self.search_unsafe_set_len(expr);
fn visit_block(&mut self, block: &'tcx Block) {
if self.initialization_found {
if let Some(ref s) = block.stmts.get(0) {
- self.visit_stmt( s)
+ self.visit_stmt(s)
}
self.initialization_found = false;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
use crate::rustc::hir;
use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
+use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast;
use crate::utils::{get_trait_def_id, span_lint};
+use if_chain::if_chain;
/// **What it does:** Lints for suspicious operations in impls of arithmetic operators, e.g.
/// subtracting elements in an Add impl.
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
if let hir::ExprKind::Binary(binop, _, _) = expr.node {
match binop.node {
- | hir::BinOpKind::Eq
+ hir::BinOpKind::Eq
| hir::BinOpKind::Lt
| hir::BinOpKind::Le
| hir::BinOpKind::Ne
| hir::BinOpKind::Ge
- | hir::BinOpKind::Gt
- => return,
+ | hir::BinOpKind::Gt => return,
_ => {},
}
// Check if the binary expression is part of another bi/unary expression
parent_expr = cx.tcx.hir.get_parent_node(parent_expr);
}
// as a parent node
- let mut visitor = BinaryExprVisitor {
- in_binary_expr: false,
- };
+ let mut visitor = BinaryExprVisitor { in_binary_expr: false };
walk_expr(&mut visitor, expr);
if visitor.in_binary_expr {
cx,
SUSPICIOUS_ARITHMETIC_IMPL,
binop.span,
- &format!(
- r#"Suspicious use of binary operator in `{}` impl"#,
- impl_trait
- ),
+ &format!(r#"Suspicious use of binary operator in `{}` impl"#, impl_trait),
);
}
cx,
SUSPICIOUS_OP_ASSIGN_IMPL,
binop.span,
- &format!(
- r#"Suspicious use of binary operator in `{}` impl"#,
- impl_trait
- ),
+ &format!(r#"Suspicious use of binary operator in `{}` impl"#, impl_trait),
);
}
}
match expr.node {
hir::ExprKind::Binary(..)
| hir::ExprKind::Unary(hir::UnOp::UnNot, _)
- | hir::ExprKind::Unary(hir::UnOp::UnNeg, _) => {
- self.in_binary_expr = true
- },
+ | hir::ExprKind::Unary(hir::UnOp::UnNeg, _) => self.in_binary_expr = true,
_ => {},
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use matches::matches;
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
use crate::rustc::ty;
-use crate::utils::{differing_macro_contexts, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty, SpanlessEq};
-use crate::utils::sugg::Sugg;
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
+use crate::utils::sugg::Sugg;
+use crate::utils::{
+ differing_macro_contexts, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty, SpanlessEq,
+};
+use if_chain::if_chain;
+use matches::matches;
/// **What it does:** Checks for manual swapping.
///
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::{Expr, ExprKind};
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use crate::rustc::hir::{Expr, ExprKind};
use crate::utils::is_adjusted;
use crate::utils::span_lint;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
use crate::rustc::ty::{self, Ty};
-use crate::rustc::hir::*;
-use std::borrow::Cow;
+use crate::rustc::{declare_tool_lint, lint_array};
+use crate::rustc_errors::Applicability;
use crate::syntax::ast;
use crate::utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then};
use crate::utils::{opt_def_id, sugg};
-use crate::rustc_errors::Applicability;
+use if_chain::if_chain;
+use std::borrow::Cow;
/// **What it does:** Checks for transmutes that can't ever be correct on any
/// architecture.
/// **Example:**
/// ```rust
/// core::intrinsics::transmute(t) // where the result type is the same as
-/// // `*t` or `&t`'s
+/// // `*t` or `&t`'s
/// ```
declare_clippy_lint! {
pub CROSSPOINTER_TRANSMUTE,
/// **Example:**
/// ```rust
/// let _: &T = std::mem::transmute(p); // where p: *const T
+///
/// // can be written:
/// let _: &T = &*p;
/// ```
/// **Example:**
/// ```rust
/// let _: char = std::mem::transmute(x); // where x: u32
+///
/// // should be:
/// let _ = std::char::from_u32(x).unwrap();
/// ```
/// **Example:**
/// ```rust
/// let _: &str = std::mem::transmute(b); // where b: &[u8]
+///
/// // should be:
/// let _ = std::str::from_utf8(b).unwrap();
/// ```
/// **Example:**
/// ```rust
/// let _: bool = std::mem::transmute(x); // where x: u8
+///
/// // should be:
/// let _: bool = x != 0;
/// ```
/// **Example:**
/// ```rust
/// let _: f32 = std::mem::transmute(x); // where x: u32
+///
/// // should be:
/// let _: f32 = f32::from_bits(x);
/// ```
USELESS_TRANSMUTE,
e.span,
"transmute from a reference to a pointer",
- |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) {
- let rty_and_mut = ty::TypeAndMut { ty: rty, mutbl: rty_mutbl };
+ |db| {
+ if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) {
+ let rty_and_mut = ty::TypeAndMut {
+ ty: rty,
+ mutbl: rty_mutbl,
+ };
- let sugg = if ptr_ty == rty_and_mut {
- arg.as_ty(to_ty)
- } else {
- arg.as_ty(cx.tcx.mk_ptr(rty_and_mut)).as_ty(to_ty)
- };
+ let sugg = if ptr_ty == rty_and_mut {
+ arg.as_ty(to_ty)
+ } else {
+ arg.as_ty(cx.tcx.mk_ptr(rty_and_mut)).as_ty(to_ty)
+ };
- db.span_suggestion_with_applicability(
- e.span,
- "try",
- sugg.to_string(),
- Applicability::Unspecified,
- );
+ db.span_suggestion_with_applicability(
+ e.span,
+ "try",
+ sugg.to_string(),
+ Applicability::Unspecified,
+ );
+ }
},
),
- (&ty::Int(_), &ty::RawPtr(_)) | (&ty::Uint(_), &ty::RawPtr(_)) => {
- span_lint_and_then(
- cx,
- USELESS_TRANSMUTE,
- e.span,
- "transmute from an integer to a pointer",
- |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) {
+ (&ty::Int(_), &ty::RawPtr(_)) | (&ty::Uint(_), &ty::RawPtr(_)) => span_lint_and_then(
+ cx,
+ USELESS_TRANSMUTE,
+ e.span,
+ "transmute from an integer to a pointer",
+ |db| {
+ if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) {
db.span_suggestion_with_applicability(
e.span,
"try",
arg.as_ty(&to_ty.to_string()).to_string(),
Applicability::Unspecified,
);
- },
- )
- },
- (&ty::Float(_), &ty::Ref(..)) |
- (&ty::Float(_), &ty::RawPtr(_)) |
- (&ty::Char, &ty::Ref(..)) |
- (&ty::Char, &ty::RawPtr(_)) => span_lint(
+ }
+ },
+ ),
+ (&ty::Float(_), &ty::Ref(..))
+ | (&ty::Float(_), &ty::RawPtr(_))
+ | (&ty::Char, &ty::Ref(..))
+ | (&ty::Char, &ty::RawPtr(_)) => span_lint(
cx,
WRONG_TRANSMUTE,
e.span,
e.span,
&format!(
"transmute from a type (`{}`) to the type that it points to (`{}`)",
- from_ty,
- to_ty
+ from_ty, to_ty
),
),
(_, &ty::RawPtr(to_ptr)) if to_ptr.ty == from_ty => span_lint(
e.span,
&format!(
"transmute from a type (`{}`) to a pointer to that type (`{}`)",
- from_ty,
- to_ty
+ from_ty, to_ty
),
),
(&ty::RawPtr(from_pty), &ty::Ref(_, to_ref_ty, mutbl)) => span_lint_and_then(
&format!(
"transmute from a pointer type (`{}`) to a reference type \
(`{}`)",
- from_ty,
- to_ty
+ from_ty, to_ty
),
|db| {
let arg = sugg::Sugg::hir(cx, &args[0], "..");
);
},
),
- (&ty::Int(ast::IntTy::I32), &ty::Char) |
- (&ty::Uint(ast::UintTy::U32), &ty::Char) => span_lint_and_then(
- cx,
- TRANSMUTE_INT_TO_CHAR,
- e.span,
- &format!("transmute from a `{}` to a `char`", from_ty),
- |db| {
- let arg = sugg::Sugg::hir(cx, &args[0], "..");
- let arg = if let ty::Int(_) = from_ty.sty {
- arg.as_ty(ty::Uint(ast::UintTy::U32))
- } else {
- arg
- };
- db.span_suggestion_with_applicability(
- e.span,
- "consider using",
- format!("std::char::from_u32({}).unwrap()", arg.to_string()),
- Applicability::Unspecified,
- );
- },
- ),
+ (&ty::Int(ast::IntTy::I32), &ty::Char) | (&ty::Uint(ast::UintTy::U32), &ty::Char) => {
+ span_lint_and_then(
+ cx,
+ TRANSMUTE_INT_TO_CHAR,
+ e.span,
+ &format!("transmute from a `{}` to a `char`", from_ty),
+ |db| {
+ let arg = sugg::Sugg::hir(cx, &args[0], "..");
+ let arg = if let ty::Int(_) = from_ty.sty {
+ arg.as_ty(ty::Uint(ast::UintTy::U32))
+ } else {
+ arg
+ };
+ db.span_suggestion_with_applicability(
+ e.span,
+ "consider using",
+ format!("std::char::from_u32({}).unwrap()", arg.to_string()),
+ Applicability::Unspecified,
+ );
+ },
+ )
+ },
(&ty::Ref(_, ty_from, from_mutbl), &ty::Ref(_, ty_to, to_mutbl)) => {
if_chain! {
if let (&ty::Slice(slice_ty), &ty::Str) = (&ty_from.sty, &ty_to.sty);
e.span,
"transmute from a reference to a reference",
|db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) {
- let ty_from_and_mut = ty::TypeAndMut { ty: ty_from, mutbl: from_mutbl };
+ let ty_from_and_mut = ty::TypeAndMut {
+ ty: ty_from,
+ mutbl: from_mutbl
+ };
let ty_to_and_mut = ty::TypeAndMut { ty: ty_to, mutbl: to_mutbl };
- let sugg_paren = arg.as_ty(cx.tcx.mk_ptr(ty_from_and_mut)).as_ty(cx.tcx.mk_ptr(ty_to_and_mut));
+ let sugg_paren = arg
+ .as_ty(cx.tcx.mk_ptr(ty_from_and_mut))
+ .as_ty(cx.tcx.mk_ptr(ty_to_and_mut));
let sugg = if to_mutbl == Mutability::MutMutable {
sugg_paren.mut_addr_deref()
} else {
TRANSMUTE_PTR_TO_PTR,
e.span,
"transmute from a pointer to a pointer",
- |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) {
- let sugg = arg.as_ty(cx.tcx.mk_ptr(to_ty));
- db.span_suggestion_with_applicability(
- e.span,
- "try",
- sugg.to_string(),
- Applicability::Unspecified,
- );
+ |db| {
+ if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) {
+ let sugg = arg.as_ty(cx.tcx.mk_ptr(to_ty));
+ db.span_suggestion_with_applicability(
+ e.span,
+ "try",
+ sugg.to_string(),
+ Applicability::Unspecified,
+ );
+ }
},
),
(&ty::Int(ast::IntTy::I8), &ty::Bool) | (&ty::Uint(ast::UintTy::U8), &ty::Bool) => {
},
)
},
- (&ty::Int(_), &ty::Float(_)) | (&ty::Uint(_), &ty::Float(_)) => {
- span_lint_and_then(
- cx,
- TRANSMUTE_INT_TO_FLOAT,
- e.span,
- &format!("transmute from a `{}` to a `{}`", from_ty, to_ty),
- |db| {
- let arg = sugg::Sugg::hir(cx, &args[0], "..");
- let arg = if let ty::Int(int_ty) = from_ty.sty {
- arg.as_ty(format!(
- "u{}",
- int_ty
- .bit_width()
- .map_or_else(|| "size".to_string(), |v| v.to_string())
- ))
- } else {
- arg
- };
- db.span_suggestion_with_applicability(
- e.span,
- "consider using",
- format!("{}::from_bits({})", to_ty, arg.to_string()),
- Applicability::Unspecified,
- );
- },
- )
- },
+ (&ty::Int(_), &ty::Float(_)) | (&ty::Uint(_), &ty::Float(_)) => span_lint_and_then(
+ cx,
+ TRANSMUTE_INT_TO_FLOAT,
+ e.span,
+ &format!("transmute from a `{}` to a `{}`", from_ty, to_ty),
+ |db| {
+ let arg = sugg::Sugg::hir(cx, &args[0], "..");
+ let arg = if let ty::Int(int_ty) = from_ty.sty {
+ arg.as_ty(format!(
+ "u{}",
+ int_ty.bit_width().map_or_else(|| "size".to_string(), |v| v.to_string())
+ ))
+ } else {
+ arg
+ };
+ db.span_suggestion_with_applicability(
+ e.span,
+ "consider using",
+ format!("{}::from_bits({})", to_ty, arg.to_string()),
+ Applicability::Unspecified,
+ );
+ },
+ ),
_ => return,
};
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use std::cmp;
use crate::rustc::hir;
Self { limit }
}
- fn check_trait_method(
- &mut self,
- cx: &LateContext<'_, 'tcx>,
- item: &TraitItemRef
- ) {
+ fn check_trait_method(&mut self, cx: &LateContext<'_, 'tcx>, item: &TraitItemRef) {
let method_def_id = cx.tcx.hir.local_def_id(item.id.node_id);
let method_sig = cx.tcx.fn_sig(method_def_id);
let method_sig = cx.tcx.erase_late_bound_regions(&method_sig);
self.check_poly_fn(cx, &decl, &method_sig, None);
}
- fn check_poly_fn(
- &mut self,
- cx: &LateContext<'_, 'tcx>,
- decl: &FnDecl,
- sig: &FnSig<'tcx>,
- span: Option<Span>,
- ) {
+ fn check_poly_fn(&mut self, cx: &LateContext<'_, 'tcx>, decl: &FnDecl, sig: &FnSig<'tcx>, span: Option<Span>) {
// Use lifetimes to determine if we're returning a reference to the
// argument. In that case we can't switch to pass-by-value as the
// argument will not live long enough.
}
}
- fn check_trait_items(
- &mut self,
- cx: &LateContext<'_, '_>,
- trait_items: &[TraitItemRef]
- ) {
+ fn check_trait_items(&mut self, cx: &LateContext<'_, '_>, trait_items: &[TraitItemRef]) {
for item in trait_items {
- if let AssociatedItemKind::Method{..} = item.kind {
+ if let AssociatedItemKind::Method { .. } = item.kind {
self.check_trait_method(cx, item);
}
}
declare_clippy_lint! {
pub LINKEDLIST,
pedantic,
- "usage of LinkedList, usually a vector is faster, or a more specialized data \
- structure like a VecDeque"
+ "usage of LinkedList, usually a vector is faster, or a more specialized data structure like a VecDeque"
}
/// **What it does:** Checks for use of `&Box<T>` anywhere in the code.
OPTION_OPTION,
ast_ty.span,
"consider using `Option<T>` instead of `Option<Option<T>>` or a custom \
- enum if you need to distinguish all 3 cases",
+ enum if you need to distinguish all 3 cases",
);
return; // don't recurse into the type
}
check_ty(cx, ty, is_local);
}
},
- QPath::Resolved(None, ref p) => for ty in p.segments.iter().flat_map(|seg| {
- seg.args
- .as_ref()
- .map_or_else(|| [].iter(), |params| params.args.iter())
- .filter_map(|arg| match arg {
- GenericArg::Type(ty) => Some(ty),
- GenericArg::Lifetime(_) => None,
- })
- }) {
- check_ty(cx, ty, is_local);
+ QPath::Resolved(None, ref p) => {
+ for ty in p.segments.iter().flat_map(|seg| {
+ seg.args
+ .as_ref()
+ .map_or_else(|| [].iter(), |params| params.args.iter())
+ .filter_map(|arg| match arg {
+ GenericArg::Type(ty) => Some(ty),
+ GenericArg::Lifetime(_) => None,
+ })
+ }) {
+ check_ty(cx, ty, is_local);
+ }
},
QPath::TypeRelative(ref ty, ref seg) => {
check_ty(cx, ty, is_local);
},
TyKind::Rptr(ref lt, ref mut_ty) => check_ty_rptr(cx, ast_ty, is_local, lt, mut_ty),
// recurse
- TyKind::Slice(ref ty) | TyKind::Array(ref ty, _) | TyKind::Ptr(MutTy { ref ty, .. }) => check_ty(cx, ty, is_local),
- TyKind::Tup(ref tys) => for ty in tys {
- check_ty(cx, ty, is_local);
+ TyKind::Slice(ref ty) | TyKind::Array(ref ty, _) | TyKind::Ptr(MutTy { ref ty, .. }) => {
+ check_ty(cx, ty, is_local)
+ },
+ TyKind::Tup(ref tys) => {
+ for ty in tys {
+ check_ty(cx, ty, is_local);
+ }
},
_ => {},
}
ast_ty.span,
"you seem to be trying to use `&Box<T>`. Consider using just `&T`",
"try",
- format!("&{}{}{}", ltopt, mutopt, &snippet_with_applicability(cx, inner.span, "..", &mut applicability)),
+ format!(
+ "&{}{}{}",
+ ltopt,
+ mutopt,
+ &snippet_with_applicability(cx, inner.span, "..", &mut applicability)
+ ),
Applicability::Unspecified,
);
return; // don't recurse into the type
///
/// **Example:**
/// ```rust
-/// let x = { 1; };
+/// let x = {
+/// 1;
+/// };
/// ```
declare_clippy_lint! {
pub LET_UNIT_VALUE,
///
/// **Example:**
/// ```rust
-/// if { foo(); } == { bar(); } { baz(); }
+/// if {
+/// foo();
+/// } == {
+/// bar();
+/// } {
+/// baz();
+/// }
/// ```
/// is equal to
/// ```rust
-/// { foo(); bar(); baz(); }
+/// {
+/// foo();
+/// bar();
+/// baz();
+/// }
/// ```
declare_clippy_lint! {
pub UNIT_CMP,
}
}
-/// **What it does:** Checks for passing a unit value as an argument to a function without using a unit literal (`()`).
+/// **What it does:** Checks for passing a unit value as an argument to a function without using a
+/// unit literal (`()`).
///
/// **Why is this bad?** This is likely the result of an accidental semicolon.
///
/// **Example:**
/// ```rust
/// foo({
-/// let a = bar();
-/// baz(a);
+/// let a = bar();
+/// baz(a);
/// })
/// ```
declare_clippy_lint! {
// only the calls to `Try::from_error` is marked as desugared,
// so we need to check both the current Expr and its parent.
if !is_questionmark_desugar_marked_call(expr) {
- if_chain!{
+ if_chain! {
let opt_parent_node = map.find(map.get_parent_node(expr.id));
if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node;
if is_questionmark_desugar_marked_call(parent_expr);
///
/// **Example:**
/// ```rust
-/// let x = u64::MAX; x as f64
+/// let x = u64::MAX;
+/// x as f64
/// ```
declare_clippy_lint! {
pub CAST_PRECISION_LOSS,
/// **Example:**
/// ```rust
/// let y: i8 = -1;
-/// y as u128 // will return 18446744073709551615
+/// y as u128 // will return 18446744073709551615
/// ```
declare_clippy_lint! {
pub CAST_SIGN_LOSS,
///
/// **Example:**
/// ```rust
-/// fn as_u8(x: u64) -> u8 { x as u8 }
+/// fn as_u8(x: u64) -> u8 {
+/// x as u8
+/// }
/// ```
declare_clippy_lint! {
pub CAST_POSSIBLE_TRUNCATION,
pedantic,
- "casts that may cause truncation of the value, e.g. `x as u8` where `x: u32`, \
- or `x as i32` where `x: f32`"
+ "casts that may cause truncation of the value, e.g. `x as u8` where `x: u32`, or `x as i32` where `x: f32`"
}
/// **What it does:** Checks for casts from an unsigned type to a signed type of
///
/// **Example:**
/// ```rust
-/// u32::MAX as i32 // will yield a value of `-1`
+/// u32::MAX as i32 // will yield a value of `-1`
/// ```
declare_clippy_lint! {
pub CAST_POSSIBLE_WRAP,
pedantic,
- "casts that may cause wrapping around the value, e.g. `x as i32` where `x: u32` \
- and `x > i32::MAX`"
+ "casts that may cause wrapping around the value, e.g. `x as i32` where `x: u32` and `x > i32::MAX`"
}
/// **What it does:** Checks for on casts between numerical types that may
///
/// **Example:**
/// ```rust
-/// fn as_u64(x: u8) -> u64 { x as u64 }
+/// fn as_u64(x: u8) -> u64 {
+/// x as u64
+/// }
/// ```
///
/// Using `::from` would look like this:
///
/// ```rust
-/// fn as_u64(x: u8) -> u64 { u64::from(x) }
+/// fn as_u64(x: u8) -> u64 {
+/// u64::from(x)
+/// }
/// ```
declare_clippy_lint! {
pub CAST_LOSSLESS,
///
/// ```rust
/// // Bad
-/// fn fn1() -> i16 { 1 };
+/// fn fn1() -> i16 {
+/// 1
+/// };
/// let _ = fn1 as i32;
///
/// // Better: Cast to usize first, then comment with the reason for the truncation
-/// fn fn2() -> i16 { 1 };
+/// fn fn2() -> i16 {
+/// 1
+/// };
/// let fn_ptr = fn2 as usize;
/// let fn_ptr_truncated = fn_ptr as i32;
/// ```
is only {4} bits wide)",
cast_from,
if cast_to_f64 { "f64" } else { "f32" },
- if arch_dependent {
- arch_dependent_str
- } else {
- ""
- },
+ if arch_dependent { arch_dependent_str } else { "" },
from_nbits_str,
mantissa_nbits
),
fn span_lossless_lint(cx: &LateContext<'_, '_>, expr: &Expr, op: &Expr, cast_from: Ty<'_>, cast_to: Ty<'_>) {
// Do not suggest using From in consts/statics until it is valid to do so (see #2267).
- if in_constant(cx, expr.id) { return }
+ if in_constant(cx, expr.id) {
+ return;
+ }
// The suggestion is to use a function call, so if the original expression
// has parens on the outside, they are no longer needed.
let mut applicability = Applicability::MachineApplicable;
cx,
CAST_LOSSLESS,
expr.span,
- &format!("casting {} to {} may become silently lossy if types change", cast_from, cast_to),
+ &format!(
+ "casting {} to {} may become silently lossy if types change",
+ cast_from, cast_to
+ ),
"try",
format!("{}::from({})", cast_to, sugg),
applicability,
use crate::syntax::ast::{LitIntType, LitKind};
match lit.node {
LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::FloatUnsuffixed(_) => {},
- _ => if cast_from.sty == cast_to.sty && !in_external_macro(cx.sess(), expr.span) {
- span_lint(
- cx,
- UNNECESSARY_CAST,
- expr.span,
- &format!("casting to the same type is unnecessary (`{}` -> `{}`)", cast_from, cast_to),
- );
+ _ => {
+ if cast_from.sty == cast_to.sty && !in_external_macro(cx.sess(), expr.span) {
+ span_lint(
+ cx,
+ UNNECESSARY_CAST,
+ expr.span,
+ &format!(
+ "casting to the same type is unnecessary (`{}` -> `{}`)",
+ cast_from, cast_to
+ ),
+ );
+ }
},
}
}
check_lossless(cx, expr, ex, cast_from, cast_to);
},
(false, false) => {
- if let (&ty::Float(FloatTy::F64), &ty::Float(FloatTy::F32)) = (&cast_from.sty, &cast_to.sty)
- {
+ if let (&ty::Float(FloatTy::F64), &ty::Float(FloatTy::F32)) = (&cast_from.sty, &cast_to.sty) {
span_lint(
cx,
CAST_POSSIBLE_TRUNCATION,
"casting f64 to f32 may truncate the value",
);
}
- if let (&ty::Float(FloatTy::F32), &ty::Float(FloatTy::F64)) = (&cast_from.sty, &cast_to.sty)
- {
+ if let (&ty::Float(FloatTy::F32), &ty::Float(FloatTy::F64)) = (&cast_from.sty, &cast_to.sty) {
span_lossless_lint(cx, expr, ex, cast_from, cast_to);
}
},
}
}
- if_chain!{
+ if_chain! {
if let ty::RawPtr(from_ptr_ty) = &cast_from.sty;
if let ty::RawPtr(to_ptr_ty) = &cast_to.sty;
if let Some(from_align) = cx.layout_of(from_ptr_ty.ty).ok().map(|a| a.align.abi);
}
}
-fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Expr, cast_from: Ty<'_>, cast_to: Ty<'_>) {
+fn lint_fn_to_numeric_cast(
+ cx: &LateContext<'_, '_>,
+ expr: &Expr,
+ cast_expr: &Expr,
+ cast_from: Ty<'_>,
+ cast_to: Ty<'_>,
+) {
// We only want to check casts to `ty::Uint` or `ty::Int`
match cast_to.sty {
ty::Uint(_) | ty::Int(..) => { /* continue on */ },
- _ => return
+ _ => return,
}
match cast_from.sty {
ty::FnDef(..) | ty::FnPtr(_) => {
cx,
FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
expr.span,
- &format!("casting function pointer `{}` to `{}`, which truncates the value", from_snippet, cast_to),
+ &format!(
+ "casting function pointer `{}` to `{}`, which truncates the value",
+ from_snippet, cast_to
+ ),
"try",
format!("{} as usize", from_snippet),
applicability,
);
-
} else if cast_to.sty != ty::Uint(UintTy::Usize) {
span_lint_and_sugg(
cx,
);
}
},
- _ => {}
+ _ => {},
}
}
///
/// **Example:**
/// ```rust
-/// struct Foo { inner: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>> }
+/// struct Foo {
+/// inner: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>>,
+/// }
/// ```
declare_clippy_lint! {
pub TYPE_COMPLEXITY,
impl TypeComplexityPass {
pub fn new(threshold: u64) -> Self {
- Self {
- threshold,
- }
+ Self { threshold }
}
}
TyKind::BareFn(ref bare) if bare.abi == Abi::Rust => (50 * self.nest, 1),
TyKind::TraitObject(ref param_bounds, _) => {
- let has_lifetime_parameters = param_bounds
- .iter()
- .any(|bound| bound.bound_generic_params.iter().any(|gen| match gen.kind {
+ let has_lifetime_parameters = param_bounds.iter().any(|bound| {
+ bound.bound_generic_params.iter().any(|gen| match gen.kind {
GenericParamKind::Lifetime { .. } => true,
_ => false,
- }));
+ })
+ });
if has_lifetime_parameters {
// complex trait bounds like A<'a, 'b>
(50 * self.nest, 1)
let msg = "casting character literal to u8. `char`s \
are 4 bytes wide in rust, so casting to u8 \
truncates them";
- let help = format!("Consider using a byte literal instead:\nb{}", snippet(cx, e.span, "'x'"));
+ let help = format!(
+ "Consider using a byte literal instead:\nb{}",
+ snippet(cx, e.span, "'x'")
+ );
span_help_and_lint(cx, CHAR_LIT_AS_U8, expr.span, msg, &help);
}
}
InequalityImpossible,
}
-
-fn is_cast_between_fixed_and_target<'a, 'tcx>(
- cx: &LateContext<'a, 'tcx>,
- expr: &'tcx Expr
-) -> bool {
-
+fn is_cast_between_fixed_and_target<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool {
if let ExprKind::Cast(ref cast_exp, _) = expr.node {
let precast_ty = cx.tables.expr_ty(cast_exp);
let cast_ty = cx.tables.expr_ty(expr);
- return is_isize_or_usize(precast_ty) != is_isize_or_usize(cast_ty)
+ return is_isize_or_usize(precast_ty) != is_isize_or_usize(cast_ty);
}
false
lhs: &'tcx Expr,
rhs: &'tcx Expr,
) -> Option<(ExtremeExpr<'tcx>, AbsurdComparisonResult)> {
- use crate::types::ExtremeType::*;
use crate::types::AbsurdComparisonResult::*;
+ use crate::types::ExtremeType::*;
use crate::utils::comparisons::*;
// absurd comparison only makes sense on primitive types
let cv = constant(cx, cx.tables, expr)?.0;
let which = match (&ty.sty, cv) {
- (&ty::Bool, Constant::Bool(false)) |
- (&ty::Uint(_), Constant::Int(0)) => Minimum,
- (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::min_value() >> (128 - int_bits(cx.tcx, ity)), ity) => Minimum,
+ (&ty::Bool, Constant::Bool(false)) | (&ty::Uint(_), Constant::Int(0)) => Minimum,
+ (&ty::Int(ity), Constant::Int(i))
+ if i == unsext(cx.tcx, i128::min_value() >> (128 - int_bits(cx.tcx, ity)), ity) =>
+ {
+ Minimum
+ },
(&ty::Bool, Constant::Bool(true)) => Maximum,
- (&ty::Int(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::max_value() >> (128 - int_bits(cx.tcx, ity)), ity) => Maximum,
+ (&ty::Int(ity), Constant::Int(i))
+ if i == unsext(cx.tcx, i128::max_value() >> (128 - int_bits(cx.tcx, ity)), ity) =>
+ {
+ Maximum
+ },
(&ty::Uint(uty), Constant::Int(i)) if clip(cx.tcx, u128::max_value(), uty) == i => Maximum,
_ => return None,
};
- Some(ExtremeExpr {
- which,
- expr,
- })
+ Some(ExtremeExpr { which, expr })
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AbsurdExtremeComparisons {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
- use crate::types::ExtremeType::*;
use crate::types::AbsurdComparisonResult::*;
+ use crate::types::ExtremeType::*;
if let ExprKind::Binary(ref cmp, ref lhs, ref rhs) = expr.node {
if let Some((culprit, result)) = detect_absurd_comparison(cx, cmp.node, lhs, rhs) {
impl PartialEq for FullInt {
fn eq(&self, other: &Self) -> bool {
- self.partial_cmp(other)
- .expect("partial_cmp only returns Some(_)") == Ordering::Equal
+ self.partial_cmp(other).expect("partial_cmp only returns Some(_)") == Ordering::Equal
}
}
}
}
-
fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<(FullInt, FullInt)> {
use crate::syntax::ast::{IntTy, UintTy};
use std::*;
}
match pre_cast_ty.sty {
ty::Int(int_ty) => Some(match int_ty {
- IntTy::I8 => (FullInt::S(i128::from(i8::min_value())), FullInt::S(i128::from(i8::max_value()))),
+ IntTy::I8 => (
+ FullInt::S(i128::from(i8::min_value())),
+ FullInt::S(i128::from(i8::max_value())),
+ ),
IntTy::I16 => (
FullInt::S(i128::from(i16::min_value())),
FullInt::S(i128::from(i16::max_value())),
FullInt::S(i128::from(i64::max_value())),
),
IntTy::I128 => (FullInt::S(i128::min_value()), FullInt::S(i128::max_value())),
- IntTy::Isize => (FullInt::S(isize::min_value() as i128), FullInt::S(isize::max_value() as i128)),
+ IntTy::Isize => (
+ FullInt::S(isize::min_value() as i128),
+ FullInt::S(isize::max_value() as i128),
+ ),
}),
ty::Uint(uint_ty) => Some(match uint_ty {
- UintTy::U8 => (FullInt::U(u128::from(u8::min_value())), FullInt::U(u128::from(u8::max_value()))),
+ UintTy::U8 => (
+ FullInt::U(u128::from(u8::min_value())),
+ FullInt::U(u128::from(u8::max_value())),
+ ),
UintTy::U16 => (
FullInt::U(u128::from(u16::min_value())),
FullInt::U(u128::from(u16::max_value())),
FullInt::U(u128::from(u64::max_value())),
),
UintTy::U128 => (FullInt::U(u128::min_value()), FullInt::U(u128::max_value())),
- UintTy::Usize => (FullInt::U(usize::min_value() as u128), FullInt::U(usize::max_value() as u128)),
+ UintTy::Usize => (
+ FullInt::U(usize::min_value() as u128),
+ FullInt::U(usize::max_value() as u128),
+ ),
}),
_ => None,
}
err_upcast_comparison(cx, span, lhs, rel == Rel::Ne);
}
} else if match rel {
- Rel::Lt => if invert {
- norm_rhs_val < lb
- } else {
- ub < norm_rhs_val
+ Rel::Lt => {
+ if invert {
+ norm_rhs_val < lb
+ } else {
+ ub < norm_rhs_val
+ }
},
- Rel::Le => if invert {
- norm_rhs_val <= lb
- } else {
- ub <= norm_rhs_val
+ Rel::Le => {
+ if invert {
+ norm_rhs_val <= lb
+ } else {
+ ub <= norm_rhs_val
+ }
},
Rel::Eq | Rel::Ne => unreachable!(),
} {
err_upcast_comparison(cx, span, lhs, true)
} else if match rel {
- Rel::Lt => if invert {
- norm_rhs_val >= ub
- } else {
- lb >= norm_rhs_val
+ Rel::Lt => {
+ if invert {
+ norm_rhs_val >= ub
+ } else {
+ lb >= norm_rhs_val
+ }
},
- Rel::Le => if invert {
- norm_rhs_val > ub
- } else {
- lb > norm_rhs_val
+ Rel::Le => {
+ if invert {
+ norm_rhs_val > ub
+ } else {
+ lb > norm_rhs_val
+ }
},
Rel::Eq | Rel::Ne => unreachable!(),
} {
cx,
IMPLICIT_HASHER,
target.span(),
- &format!("impl for `{}` should be generalized over different hashers", target.type_name()),
+ &format!(
+ "impl for `{}` should be generalized over different hashers",
+ target.type_name()
+ ),
move |db| {
suggestion(cx, db, generics.span, generics_suggestion_span, target, ctr_vis);
},
/// Checks that `ty` is a target type without a BuildHasher.
fn new<'a>(cx: &LateContext<'a, 'tcx>, hir_ty: &hir::Ty) -> Option<Self> {
if let TyKind::Path(QPath::Resolved(None, ref path)) = hir_ty.node {
- let params: Vec<_> = path.segments.last().as_ref()?.args.as_ref()?
- .args.iter().filter_map(|arg| match arg {
+ let params: Vec<_> = path
+ .segments
+ .last()
+ .as_ref()?
+ .args
+ .as_ref()?
+ .args
+ .iter()
+ .filter_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None,
- }).collect();
+ })
+ .collect();
let params_len = params.len();
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
snippet(cx, params[1].span, "V"),
))
} else if match_path(path, &paths::HASHSET) && params_len == 1 {
- Some(ImplicitHasherType::HashSet(hir_ty.span, ty, snippet(cx, params[0].span, "T")))
+ Some(ImplicitHasherType::HashSet(
+ hir_ty.span,
+ ty,
+ snippet(cx, params[0].span, "T"),
+ ))
} else {
None
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use crate::rustc::hir::*;
use crate::syntax::ast::{LitKind, NodeId};
use crate::syntax::source_map::Span;
-use unicode_normalization::UnicodeNormalization;
use crate::utils::{is_allowed, snippet, span_help_and_lint};
+use unicode_normalization::UnicodeNormalization;
/// **What it does:** Checks for the Unicode zero-width space in the code.
///
declare_clippy_lint! {
pub NON_ASCII_LITERAL,
pedantic,
- "using any literal non-ASCII chars in a string literal instead of \
- using the `\\u` escape"
+ "using any literal non-ASCII chars in a string literal instead of using the `\\u` escape"
}
/// **What it does:** Checks for string literals that contain Unicode in a form
declare_clippy_lint! {
pub UNICODE_NOT_NFC,
pedantic,
- "using a unicode literal not in NFC normal form (see \
- [unicode tr15](http://www.unicode.org/reports/tr15/) for further information)"
+ "using a unicode literal not in NFC normal form (see [unicode tr15](http://www.unicode.org/reports/tr15/) for further information)"
}
-
#[derive(Copy, Clone)]
pub struct Unicode;
UNICODE_NOT_NFC,
span,
"non-nfc unicode sequence detected",
- &format!("Consider replacing the string with:\n\"{}\"", string.nfc().collect::<String>()),
+ &format!(
+ "Consider replacing the string with:\n\"{}\"",
+ string.nfc().collect::<String>()
+ ),
);
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast::*;
.expect("use paths cannot be empty")
.ident;
unsafe_to_safe_check(old_name, new_name, cx, span);
- }
- UseTreeKind::Simple(None, ..) |
- UseTreeKind::Glob => {},
+ },
+ UseTreeKind::Simple(None, ..) | UseTreeKind::Glob => {},
UseTreeKind::Nested(ref nested_use_tree) => {
for &(ref use_tree, _) in nested_use_tree {
check_use_tree(use_tree, cx, span);
}
- }
+ },
}
}
cx,
UNSAFE_REMOVED_FROM_NAME,
span,
- &format!("removed \"unsafe\" from the name of `{}` in use as `{}`", old_str, new_str),
+ &format!(
+ "removed \"unsafe\" from the name of `{}` in use as `{}`",
+ old_str, new_str
+ ),
);
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+use crate::rustc::hir;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use crate::rustc::hir;
use crate::utils::{is_try, match_qpath, match_trait_method, paths, span_lint};
/// **What it does:** Checks for unused written/read amount.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc::hir;
use crate::rustc::hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor};
+use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_data_structures::fx::FxHashMap;
use crate::syntax::ast;
use crate::syntax::source_map::Span;
impl<'a, 'tcx: 'a> Visitor<'tcx> for UnusedLabelVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
match expr.node {
- hir::ExprKind::Break(destination, _) | hir::ExprKind::Continue(destination) => if let Some(label) = destination.label {
- self.labels.remove(&label.ident.as_str());
+ hir::ExprKind::Break(destination, _) | hir::ExprKind::Continue(destination) => {
+ if let Some(label) = destination.label {
+ self.labels.remove(&label.ident.as_str());
+ }
},
hir::ExprKind::Loop(_, Some(label), _) | hir::ExprKind::While(_, _, Some(label)) => {
self.labels.insert(label.ident.as_str(), expr.span);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use if_chain::if_chain;
-use crate::utils::{in_macro, match_type, paths, span_lint_and_then, usage::is_potentially_mutated};
use crate::rustc::hir::intravisit::*;
use crate::rustc::hir::*;
use crate::syntax::ast::NodeId;
use crate::syntax::source_map::Span;
+use crate::utils::{in_macro, match_type, paths, span_lint_and_then, usage::is_potentially_mutated};
/// **What it does:** Checks for calls of `unwrap[_err]()` that cannot fail.
///
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::hir::intravisit::{walk_path, walk_ty, NestedVisitorMap, Visitor};
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
let impl_ty = self.impl_type_walker.next();
if let TyKind::Path(QPath::Resolved(_, path)) = &t.node {
-
// The implementation and trait types don't match which means that
// the concrete type was specified by the implementation
if impl_ty != trait_ty {
-
if let Some(impl_ty) = impl_ty {
if self.item_type == impl_ty {
let is_self_ty = if let def::Def::SelfTy(..) = path.def {
}
}
}
-
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! A group of attributes that can be attached to Rust code in order
//! to generate a clippy lint detecting said code automatically.
-use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc::hir;
-use crate::rustc::hir::{Expr, ExprKind, QPath, TyKind, Pat, PatKind, BindingAnnotation, StmtKind, DeclKind, Stmt};
use crate::rustc::hir::intravisit::{NestedVisitorMap, Visitor};
+use crate::rustc::hir::{BindingAnnotation, DeclKind, Expr, ExprKind, Pat, PatKind, QPath, Stmt, StmtKind, TyKind};
+use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_data_structures::fx::FxHashMap;
use crate::syntax::ast::{Attribute, LitKind, DUMMY_NODE_ID};
use crate::utils::get_attr;
///
/// ```rust
/// // ./tests/ui/new_lint.stdout
-/// if_chain!{
+/// if_chain! {
/// if let ExprKind::If(ref cond, ref then, None) = item.node,
/// if let ExprKind::Binary(BinOp::Eq, ref left, ref right) = cond.node,
/// if let ExprKind::Path(ref path) = left.node,
let op_pat = self.next("op");
let left_pat = self.next("left");
let right_pat = self.next("right");
- println!("Binary(ref {}, ref {}, ref {}) = {};", op_pat, left_pat, right_pat, current);
+ println!(
+ "Binary(ref {}, ref {}, ref {}) = {};",
+ op_pat, left_pat, right_pat, current
+ );
println!(" if BinOpKind::{:?} == {}.node;", op.node, op_pat);
self.current = left_pat;
self.visit_expr(left);
let then_pat = self.next("then");
if let Some(ref else_) = *opt_else {
let else_pat = self.next("else_");
- println!("If(ref {}, ref {}, Some(ref {})) = {};", cond_pat, then_pat, else_pat, current);
+ println!(
+ "If(ref {}, ref {}, Some(ref {})) = {};",
+ cond_pat, then_pat, else_pat, current
+ );
self.current = else_pat;
self.visit_expr(else_);
} else {
let cond_pat = self.next("cond");
let body_pat = self.next("body");
let label_pat = self.next("label");
- println!("While(ref {}, ref {}, ref {}) = {};", cond_pat, body_pat, label_pat, current);
+ println!(
+ "While(ref {}, ref {}, ref {}) = {};",
+ cond_pat, body_pat, label_pat, current
+ );
self.current = cond_pat;
self.visit_expr(cond);
self.current = body_pat;
println!(" if let Guard::If(ref {}) = {};", if_expr_pat, guard_pat);
self.current = if_expr_pat;
self.visit_expr(if_expr);
- }
+ },
}
}
println!(" if {}[{}].pats.len() == {};", arms_pat, i, arm.pats.len());
let op_pat = self.next("op");
let target_pat = self.next("target");
let value_pat = self.next("value");
- println!("AssignOp(ref {}, ref {}, ref {}) = {};", op_pat, target_pat, value_pat, current);
+ println!(
+ "AssignOp(ref {}, ref {}, ref {}) = {};",
+ op_pat, target_pat, value_pat, current
+ );
println!(" if BinOpKind::{:?} == {}.node;", op.node, op_pat);
self.current = target_pat;
self.visit_expr(target);
println!("Again(ref {}) = {};", destination_pat, current);
// FIXME: implement label printing
},
- ExprKind::Ret(ref opt_value) => if let Some(ref value) = *opt_value {
- let value_pat = self.next("value");
- println!("Ret(Some(ref {})) = {};", value_pat, current);
- self.current = value_pat;
- self.visit_expr(value);
- } else {
- println!("Ret(None) = {};", current);
+ ExprKind::Ret(ref opt_value) => {
+ if let Some(ref value) = *opt_value {
+ let value_pat = self.next("value");
+ println!("Ret(Some(ref {})) = {};", value_pat, current);
+ self.current = value_pat;
+ self.visit_expr(value);
+ } else {
+ println!("Ret(None) = {};", current);
+ }
},
ExprKind::InlineAsm(_, ref _input, ref _output) => {
println!("InlineAsm(_, ref input, ref output) = {};", current);
let base_pat = self.next("base");
println!(
"Struct(ref {}, ref {}, Some(ref {})) = {};",
- path_pat,
- fields_pat,
- base_pat,
- current
+ path_pat, fields_pat, base_pat, current
);
self.current = base_pat;
self.visit_expr(base);
let name_pat = self.next("name");
if let Some(ref sub) = *sub {
let sub_pat = self.next("sub");
- println!("Binding({}, _, {}, Some(ref {})) = {};", anno_pat, name_pat, sub_pat, current);
+ println!(
+ "Binding({}, _, {}, Some(ref {})) = {};",
+ anno_pat, name_pat, sub_pat, current
+ );
self.current = sub_pat;
self.visit_pat(sub);
} else {
println!("Binding({}, _, {}, None) = {};", anno_pat, name_pat, current);
}
println!(" if {}.node.as_str() == \"{}\";", name_pat, ident.as_str());
- }
+ },
PatKind::Struct(ref path, ref fields, ignore) => {
let path_pat = self.next("path");
let fields_pat = self.next("fields");
- println!("Struct(ref {}, ref {}, {}) = {};", path_pat, fields_pat, ignore, current);
+ println!(
+ "Struct(ref {}, ref {}, {}) = {};",
+ path_pat, fields_pat, ignore, current
+ );
self.current = path_pat;
self.print_qpath(path);
println!(" if {}.len() == {};", fields_pat, fields.len());
println!(" // unimplemented: field checks");
- }
+ },
PatKind::TupleStruct(ref path, ref fields, skip_pos) => {
let path_pat = self.next("path");
let fields_pat = self.next("fields");
- println!("TupleStruct(ref {}, ref {}, {:?}) = {};", path_pat, fields_pat, skip_pos, current);
+ println!(
+ "TupleStruct(ref {}, ref {}, {:?}) = {};",
+ path_pat, fields_pat, skip_pos, current
+ );
self.current = path_pat;
self.print_qpath(path);
println!(" if {}.len() == {};", fields_pat, fields.len());
println!("Path(ref {}) = {};", path_pat, current);
self.current = path_pat;
self.print_qpath(path);
- }
+ },
PatKind::Tuple(ref fields, skip_pos) => {
let fields_pat = self.next("fields");
println!("Tuple(ref {}, {:?}) = {};", fields_pat, skip_pos, current);
println!(" if {}.len() == {};", fields_pat, fields.len());
println!(" // unimplemented: field checks");
- }
+ },
PatKind::Box(ref pat) => {
let pat_pat = self.next("pat");
println!("Box(ref {}) = {};", pat_pat, current);
println!("Lit(ref {}) = {}", lit_expr_pat, current);
self.current = lit_expr_pat;
self.visit_expr(lit_expr);
- }
+ },
PatKind::Range(ref start, ref end, end_kind) => {
let start_pat = self.next("start");
let end_pat = self.next("end");
- println!("Range(ref {}, ref {}, RangeEnd::{:?}) = {};", start_pat, end_pat, end_kind, current);
+ println!(
+ "Range(ref {}, ref {}, RangeEnd::{:?}) = {};",
+ start_pat, end_pat, end_kind, current
+ );
self.current = start_pat;
self.visit_expr(start);
self.current = end_pat;
self.visit_expr(end);
- }
+ },
PatKind::Slice(ref start, ref middle, ref end) => {
let start_pat = self.next("start");
let end_pat = self.next("end");
if let Some(ref middle) = middle {
let middle_pat = self.next("middle");
- println!("Slice(ref {}, Some(ref {}), ref {}) = {};", start_pat, middle_pat, end_pat, current);
+ println!(
+ "Slice(ref {}, Some(ref {}), ref {}) = {};",
+ start_pat, middle_pat, end_pat, current
+ );
self.current = middle_pat;
self.visit_pat(middle);
} else {
self.current = format!("{}[{}]", end_pat, i);
self.visit_pat(pat);
}
- }
+ },
}
}
println!("Item(item_id) = {};", current);
},
}
- }
+ },
// Expr without trailing semi-colon (must have unit type):
StmtKind::Expr(ref e, _) => {
hir::MatchSource::TryDesugar => "MatchSource::TryDesugar".to_string(),
hir::MatchSource::WhileLetDesugar => "MatchSource::WhileLetDesugar".to_string(),
hir::MatchSource::Normal => "MatchSource::Normal".to_string(),
- hir::MatchSource::IfLetDesugar { contains_else_clause } => format!("MatchSource::IfLetDesugar {{ contains_else_clause: {} }}", contains_else_clause),
+ hir::MatchSource::IfLetDesugar { contains_else_clause } => format!(
+ "MatchSource::IfLetDesugar {{ contains_else_clause: {} }}",
+ contains_else_clause
+ ),
}
}
fn print_path(path: &QPath, first: &mut bool) {
match *path {
- QPath::Resolved(_, ref path) => for segment in &path.segments {
- if *first {
- *first = false;
- } else {
- print!(", ");
+ QPath::Resolved(_, ref path) => {
+ for segment in &path.segments {
+ if *first {
+ *first = false;
+ } else {
+ print!(", ");
+ }
+ print!("{:?}", segment.ident.as_str());
}
- print!("{:?}", segment.ident.as_str());
},
QPath::TypeRelative(ref ty, ref segment) => match ty.node {
hir::TyKind::Path(ref inner_path) => {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
/// Return the index of the character after the first camel-case component of
/// `s`.
pub fn until(s: &str) -> usize {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! Utility functions about comparison operators.
#![deny(clippy::missing_docs_in_private_items)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! Read configurations files.
#![deny(clippy::missing_docs_in_private_items)]
+use crate::syntax::{ast, source_map};
use lazy_static::lazy_static;
use std::default::Default;
-use std::{env, fmt, fs, io, path};
use std::io::Read;
-use crate::syntax::{ast, source_map};
-use toml;
use std::sync::Mutex;
+use std::{env, fmt, fs, io, path};
+use toml;
/// Get the configuration file from arguments.
pub fn file_from_args(
ast::MetaItemKind::Word | ast::MetaItemKind::List(_) => {
Err(("`conf_file` must be a named value", arg.span))
},
- ast::MetaItemKind::NameValue(ref value) => if let ast::LitKind::Str(ref file, _) = value.node {
- Ok(Some(file.to_string().into()))
- } else {
- Err(("`conf_file` value must be a string", value.span))
+ ast::MetaItemKind::NameValue(ref value) => {
+ if let ast::LitKind::Str(ref file, _) = value.node {
+ Ok(Some(file.to_string().into()))
+ } else {
+ Err(("`conf_file` value must be a string", value.span))
+ }
},
};
}
Ok(ref md) if md.is_file() => return Ok(Some(config_file)),
// Return the error if it's something other than `NotFound`; otherwise we didn't
// find the project file yet, and continue searching.
- Err(e) => if e.kind() != io::ErrorKind::NotFound {
- return Err(e);
+ Err(e) => {
+ if e.kind() != io::ErrorKind::NotFound {
+ return Err(e);
+ }
},
_ => (),
}
Err(err) => return default(vec![err.into()]),
};
- assert!(
- ERRORS
- .lock()
- .expect("no threading -> mutex always safe")
- .is_empty()
- );
+ assert!(ERRORS.lock().expect("no threading -> mutex always safe").is_empty());
match toml::from_str(&file) {
Ok(toml) => (
toml,
- ERRORS
- .lock()
- .expect("no threading -> mutex always safe")
- .split_off(0),
+ ERRORS.lock().expect("no threading -> mutex always safe").split_off(0),
),
Err(e) => {
- let mut errors = ERRORS
- .lock()
- .expect("no threading -> mutex always safe")
- .split_off(0);
+ let mut errors = ERRORS.lock().expect("no threading -> mutex always safe").split_off(0);
errors.push(Error::Toml(e.to_string()));
default(errors)
},
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! This module contains some useful constants.
#![deny(clippy::missing_docs_in_private_items)]
///
/// [reference-types]: https://doc.rust-lang.org/reference/types.html
pub const BUILTIN_TYPES: &[&str] = &[
- "i8",
- "u8",
- "i16",
- "u16",
- "i32",
- "u32",
- "i64",
- "u64",
- "i128",
- "u128",
- "isize",
- "usize",
- "f32",
- "f64",
- "bool",
- "str",
- "char",
+ "i8", "u8", "i16", "u16", "i32", "u32", "i64", "u64", "i128", "u128", "isize", "usize", "f32", "f64", "bool",
+ "str", "char",
];
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! This module contains functions for retrieve the original AST from lowered
//! `hir`.
#![deny(clippy::missing_docs_in_private_items)]
-use if_chain::if_chain;
-use crate::rustc::{hir, ty};
use crate::rustc::lint::LateContext;
+use crate::rustc::{hir, ty};
use crate::syntax::ast;
use crate::utils::{is_expn_of, match_def_path, match_qpath, opt_def_id, paths, resolve_node};
+use if_chain::if_chain;
/// Convert a hir binary operator to the corresponding `ast` type.
pub fn binop(op: hir::BinOpKind) -> ast::BinOpKind {
Some(expr)
}
-
let def_path = match cx.tables.expr_ty(expr).sty {
ty::Adt(def, _) => cx.tcx.def_path(def.did),
_ => return None,
None
}
},
- hir::ExprKind::Call(ref path, ref args) => if let hir::ExprKind::Path(ref path) = path.node {
- if match_qpath(path, &paths::RANGE_INCLUSIVE_STD_NEW) || match_qpath(path, &paths::RANGE_INCLUSIVE_NEW) {
+ hir::ExprKind::Call(ref path, ref args) => {
+ if let hir::ExprKind::Path(ref path) = path.node {
+ if match_qpath(path, &paths::RANGE_INCLUSIVE_STD_NEW) || match_qpath(path, &paths::RANGE_INCLUSIVE_NEW)
+ {
+ Some(Range {
+ start: Some(&args[0]),
+ end: Some(&args[1]),
+ limits: ast::RangeLimits::Closed,
+ })
+ } else {
+ None
+ }
+ } else {
+ None
+ }
+ },
+ hir::ExprKind::Struct(ref path, ref fields, None) => {
+ if match_qpath(path, &paths::RANGE_FROM_STD) || match_qpath(path, &paths::RANGE_FROM) {
+ Some(Range {
+ start: Some(get_field("start", fields)?),
+ end: None,
+ limits: ast::RangeLimits::HalfOpen,
+ })
+ } else if match_qpath(path, &paths::RANGE_STD) || match_qpath(path, &paths::RANGE) {
+ Some(Range {
+ start: Some(get_field("start", fields)?),
+ end: Some(get_field("end", fields)?),
+ limits: ast::RangeLimits::HalfOpen,
+ })
+ } else if match_qpath(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_qpath(path, &paths::RANGE_TO_INCLUSIVE)
+ {
Some(Range {
- start: Some(&args[0]),
- end: Some(&args[1]),
+ start: None,
+ end: Some(get_field("end", fields)?),
limits: ast::RangeLimits::Closed,
})
+ } else if match_qpath(path, &paths::RANGE_TO_STD) || match_qpath(path, &paths::RANGE_TO) {
+ Some(Range {
+ start: None,
+ end: Some(get_field("end", fields)?),
+ limits: ast::RangeLimits::HalfOpen,
+ })
} else {
None
}
- } else {
- None
- },
- hir::ExprKind::Struct(ref path, ref fields, None) => if match_qpath(path, &paths::RANGE_FROM_STD)
- || match_qpath(path, &paths::RANGE_FROM)
- {
- Some(Range {
- start: Some(get_field("start", fields)?),
- end: None,
- limits: ast::RangeLimits::HalfOpen,
- })
- } else if match_qpath(path, &paths::RANGE_STD) || match_qpath(path, &paths::RANGE) {
- Some(Range {
- start: Some(get_field("start", fields)?),
- end: Some(get_field("end", fields)?),
- limits: ast::RangeLimits::HalfOpen,
- })
- } else if match_qpath(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_qpath(path, &paths::RANGE_TO_INCLUSIVE) {
- Some(Range {
- start: None,
- end: Some(get_field("end", fields)?),
- limits: ast::RangeLimits::Closed,
- })
- } else if match_qpath(path, &paths::RANGE_TO_STD) || match_qpath(path, &paths::RANGE_TO) {
- Some(Range {
- start: None,
- end: Some(get_field("end", fields)?),
- limits: ast::RangeLimits::HalfOpen,
- })
- } else {
- None
},
_ => None,
}
//
// ```
// for x in some_vec {
- // // do stuff
+ // // do stuff
// }
// ```
if_chain! {
//
// ```
// for _ in vec![()] {
- // // anything
+ // // anything
// }
// ```
if_chain! {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use crate::consts::{constant_simple, constant_context};
-use crate::rustc::lint::LateContext;
+use crate::consts::{constant_context, constant_simple};
use crate::rustc::hir::*;
-use crate::rustc::ty::{TypeckTables};
-use std::hash::{Hash, Hasher};
-use std::collections::hash_map::DefaultHasher;
+use crate::rustc::lint::LateContext;
+use crate::rustc::ty::TypeckTables;
use crate::syntax::ast::Name;
use crate::syntax::ptr::P;
use crate::utils::differing_macro_contexts;
+use std::collections::hash_map::DefaultHasher;
+use std::hash::{Hash, Hasher};
/// Type used to check whether two ast are the same. This is different from the
/// operator
false
}
},
- (&StmtKind::Expr(ref l, _), &StmtKind::Expr(ref r, _)) | (&StmtKind::Semi(ref l, _), &StmtKind::Semi(ref r, _)) => {
- self.eq_expr(l, r)
- },
+ (&StmtKind::Expr(ref l, _), &StmtKind::Expr(ref r, _))
+ | (&StmtKind::Semi(ref l, _), &StmtKind::Semi(ref r, _)) => self.eq_expr(l, r),
_ => false,
}
}
return false;
}
- if let (Some(l), Some(r)) = (constant_simple(self.cx, self.tables, left), constant_simple(self.cx, self.tables, right)) {
+ if let (Some(l), Some(r)) = (
+ constant_simple(self.cx, self.tables, left),
+ constant_simple(self.cx, self.tables, right),
+ ) {
if l == r {
return true;
}
}
match (&left.node, &right.node) {
- (&ExprKind::AddrOf(l_mut, ref le), &ExprKind::AddrOf(r_mut, ref re)) => l_mut == r_mut && self.eq_expr(le, re),
+ (&ExprKind::AddrOf(l_mut, ref le), &ExprKind::AddrOf(r_mut, ref re)) => {
+ l_mut == r_mut && self.eq_expr(le, re)
+ },
(&ExprKind::Continue(li), &ExprKind::Continue(ri)) => {
both(&li.label, &ri.label, |l, r| l.ident.as_str() == r.ident.as_str())
},
- (&ExprKind::Assign(ref ll, ref lr), &ExprKind::Assign(ref rl, ref rr)) => self.eq_expr(ll, rl) && self.eq_expr(lr, rr),
+ (&ExprKind::Assign(ref ll, ref lr), &ExprKind::Assign(ref rl, ref rr)) => {
+ self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
+ },
(&ExprKind::AssignOp(ref lo, ref ll, ref lr), &ExprKind::AssignOp(ref ro, ref rl, ref rr)) => {
lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
},
(&ExprKind::Call(ref l_fun, ref l_args), &ExprKind::Call(ref r_fun, ref r_args)) => {
!self.ignore_fn && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args)
},
- (&ExprKind::Cast(ref lx, ref lt), &ExprKind::Cast(ref rx, ref rt)) |
- (&ExprKind::Type(ref lx, ref lt), &ExprKind::Type(ref rx, ref rt)) => self.eq_expr(lx, rx) && self.eq_ty(lt, rt),
+ (&ExprKind::Cast(ref lx, ref lt), &ExprKind::Cast(ref rx, ref rt))
+ | (&ExprKind::Type(ref lx, ref lt), &ExprKind::Type(ref rx, ref rt)) => {
+ self.eq_expr(lx, rx) && self.eq_ty(lt, rt)
+ },
(&ExprKind::Field(ref l_f_exp, ref l_f_ident), &ExprKind::Field(ref r_f_exp, ref r_f_ident)) => {
l_f_ident.name == r_f_ident.name && self.eq_expr(l_f_exp, r_f_exp)
},
- (&ExprKind::Index(ref la, ref li), &ExprKind::Index(ref ra, ref ri)) => self.eq_expr(la, ra) && self.eq_expr(li, ri),
+ (&ExprKind::Index(ref la, ref li), &ExprKind::Index(ref ra, ref ri)) => {
+ self.eq_expr(la, ra) && self.eq_expr(li, ri)
+ },
(&ExprKind::If(ref lc, ref lt, ref le), &ExprKind::If(ref rc, ref rt, ref re)) => {
self.eq_expr(lc, rc) && self.eq_expr(&**lt, &**rt) && both(le, re, |l, r| self.eq_expr(l, r))
},
lls == rls && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.ident.as_str() == r.ident.as_str())
},
(&ExprKind::Match(ref le, ref la, ref ls), &ExprKind::Match(ref re, ref ra, ref rs)) => {
- ls == rs && self.eq_expr(le, re) && over(la, ra, |l, r| {
- self.eq_expr(&l.body, &r.body) && both(&l.guard, &r.guard, |l, r| self.eq_guard(l, r))
- && over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r))
- })
+ ls == rs
+ && self.eq_expr(le, re)
+ && over(la, ra, |l, r| {
+ self.eq_expr(&l.body, &r.body)
+ && both(&l.guard, &r.guard, |l, r| self.eq_guard(l, r))
+ && over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r))
+ })
},
(&ExprKind::MethodCall(ref l_path, _, ref l_args), &ExprKind::MethodCall(ref r_path, _, ref r_args)) => {
!self.ignore_fn && self.eq_path_segment(l_path, r_path) && self.eq_exprs(l_args, r_args)
(&ExprKind::Ret(ref l), &ExprKind::Ret(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)),
(&ExprKind::Path(ref l), &ExprKind::Path(ref r)) => self.eq_qpath(l, r),
(&ExprKind::Struct(ref l_path, ref lf, ref lo), &ExprKind::Struct(ref r_path, ref rf, ref ro)) => {
- self.eq_qpath(l_path, r_path) && both(lo, ro, |l, r| self.eq_expr(l, r))
+ self.eq_qpath(l_path, r_path)
+ && both(lo, ro, |l, r| self.eq_expr(l, r))
&& over(lf, rf, |l, r| self.eq_field(l, r))
},
(&ExprKind::Tup(ref l_tup), &ExprKind::Tup(ref r_tup)) => self.eq_exprs(l_tup, r_tup),
(&ExprKind::Unary(l_op, ref le), &ExprKind::Unary(r_op, ref re)) => l_op == r_op && self.eq_expr(le, re),
(&ExprKind::Array(ref l), &ExprKind::Array(ref r)) => self.eq_exprs(l, r),
(&ExprKind::While(ref lc, ref lb, ref ll), &ExprKind::While(ref rc, ref rb, ref rl)) => {
- self.eq_expr(lc, rc) && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.ident.as_str() == r.ident.as_str())
+ self.eq_expr(lc, rc)
+ && self.eq_block(lb, rb)
+ && both(ll, rl, |l, r| l.ident.as_str() == r.ident.as_str())
},
_ => false,
}
},
(&PatKind::Ref(ref le, ref lm), &PatKind::Ref(ref re, ref rm)) => lm == rm && self.eq_pat(le, re),
(&PatKind::Slice(ref ls, ref li, ref le), &PatKind::Slice(ref rs, ref ri, ref re)) => {
- over(ls, rs, |l, r| self.eq_pat(l, r)) && over(le, re, |l, r| self.eq_pat(l, r))
+ over(ls, rs, |l, r| self.eq_pat(l, r))
+ && over(le, re, |l, r| self.eq_pat(l, r))
&& both(li, ri, |l, r| self.eq_pat(l, r))
},
(&PatKind::Wild, &PatKind::Wild) => true,
&& over(&left.bindings, &right.bindings, |l, r| self.eq_type_binding(l, r))
} else if left.parenthesized && right.parenthesized {
over(left.inputs(), right.inputs(), |l, r| self.eq_ty(l, r))
- && both(
- &Some(&left.bindings[0].ty),
- &Some(&right.bindings[0].ty),
- |l, r| self.eq_ty(l, r),
- )
+ && both(&Some(&left.bindings[0].ty), &Some(&right.bindings[0].ty), |l, r| {
+ self.eq_ty(l, r)
+ })
} else {
false
}
self.tables = full_table;
eq_ty && ll == rl
},
- (&TyKind::Ptr(ref l_mut), &TyKind::Ptr(ref r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty),
+ (&TyKind::Ptr(ref l_mut), &TyKind::Ptr(ref r_mut)) => {
+ l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty)
+ },
(&TyKind::Rptr(_, ref l_rmut), &TyKind::Rptr(_, ref r_rmut)) => {
l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(&*l_rmut.ty, &*r_rmut.ty)
},
fn swap_binop<'a>(binop: BinOpKind, lhs: &'a Expr, rhs: &'a Expr) -> Option<(BinOpKind, &'a Expr, &'a Expr)> {
match binop {
- BinOpKind::Add |
- BinOpKind::Mul |
- BinOpKind::Eq |
- BinOpKind::Ne |
- BinOpKind::BitAnd |
- BinOpKind::BitXor |
- BinOpKind::BitOr => Some((binop, rhs, lhs)),
+ BinOpKind::Add
+ | BinOpKind::Mul
+ | BinOpKind::Eq
+ | BinOpKind::Ne
+ | BinOpKind::BitAnd
+ | BinOpKind::BitXor
+ | BinOpKind::BitOr => Some((binop, rhs, lhs)),
BinOpKind::Lt => Some((BinOpKind::Gt, rhs, lhs)),
BinOpKind::Le => Some((BinOpKind::Ge, rhs, lhs)),
BinOpKind::Ge => Some((BinOpKind::Le, rhs, lhs)),
BinOpKind::Gt => Some((BinOpKind::Lt, rhs, lhs)),
- BinOpKind::Shl |
- BinOpKind::Shr |
- BinOpKind::Rem |
- BinOpKind::Sub |
- BinOpKind::Div |
- BinOpKind::And |
- BinOpKind::Or => None,
+ BinOpKind::Shl
+ | BinOpKind::Shr
+ | BinOpKind::Rem
+ | BinOpKind::Sub
+ | BinOpKind::Div
+ | BinOpKind::And
+ | BinOpKind::Or => None,
}
}
left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y))
}
-
/// Type used to hash an ast element. This is different from the `Hash` trait
/// on ast types as this
/// trait would consider IDs and spans.
BlockCheckMode::UnsafeBlock(_) => 1,
BlockCheckMode::PushUnsafeBlock(_) => 2,
BlockCheckMode::PopUnsafeBlock(_) => 3,
- }.hash(&mut self.s);
+ }
+ .hash(&mut self.s);
}
#[allow(clippy::many_single_char_names)]
match cap {
CaptureClause::CaptureByValue => 0,
CaptureClause::CaptureByRef => 1,
- }.hash(&mut self.s);
+ }
+ .hash(&mut self.s);
self.hash_expr(&self.cx.tcx.hir.body(eid).value);
},
ExprKind::Field(ref e, ref f) => {
let c: fn(_) -> _ = Guard::If;
c.hash(&mut self.s);
self.hash_expr(expr);
- }
+ },
}
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! checks for attributes
-use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc::hir;
use crate::rustc::hir::print;
+use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
+use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast::Attribute;
use crate::utils::get_attr;
},
hir::ItemKind::TraitAlias(..) => {
println!("trait alias");
- }
+ },
hir::ItemKind::Impl(_, _, _, _, Some(ref _trait_ref), _, _) => {
println!("trait impl");
},
hir::Guard::If(expr) => {
println!("{}If", ind);
print_expr(cx, expr, indent + 1);
- }
+ },
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use crate::utils::{
- match_def_path, match_type, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty,
-};
-use if_chain::if_chain;
use crate::rustc::hir;
+use crate::rustc::hir::def::Def;
use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use crate::rustc::hir::*;
-use crate::rustc::hir::def::Def;
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use crate::rustc_errors::Applicability;
use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use crate::rustc_errors::Applicability;
use crate::syntax::ast::{Crate as AstCrate, Ident, ItemKind, Name};
use crate::syntax::source_map::Span;
use crate::syntax::symbol::LocalInternedString;
+use crate::utils::{
+ match_def_path, match_type, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty,
+};
+use if_chain::if_chain;
/// **What it does:** Checks for various things we like to keep tidy in clippy.
///
impl EarlyLintPass for Clippy {
fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &AstCrate) {
- if let Some(utils) = krate
- .module
- .items
- .iter()
- .find(|item| item.ident.name == "utils")
- {
+ if let Some(utils) = krate.module.items.iter().find(|item| item.ident.name == "utils") {
if let ItemKind::Mod(ref utils_mod) = utils.node {
- if let Some(paths) = utils_mod
- .items
- .iter()
- .find(|item| item.ident.name == "paths")
- {
+ if let Some(paths) = utils_mod.items.iter().find(|item| item.ident.name == "paths") {
if let ItemKind::Mod(ref paths_mod) = paths.node {
let mut last_name: Option<LocalInternedString> = None;
for item in &paths_mod.items {
ty: ref inner,
mutbl: MutImmutable,
},
- ) = ty.node {
+ ) = ty.node
+ {
if let TyKind::Path(ref path) = inner.node {
if let Def::Struct(def_id) = cx.tables.qpath_def(path, inner.hir_id) {
return match_def_path(cx.tcx, def_id, &paths::LINT);
fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
let ident_string = ident.to_string();
if let Some(replace) = self.map.get(&ident_string) {
- let msg = format!("Prefer {} over {}, it has better performance \
- and we don't need any collision prevention in clippy",
- replace, ident_string);
+ let msg = format!(
+ "Prefer {} over {}, it has better performance \
+ and we don't need any collision prevention in clippy",
+ replace, ident_string
+ );
span_lint_and_sugg(
cx,
DEFAULT_HASH_TYPES,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! This module contains paths to types and functions Clippy needs to know
//! about.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use std::borrow::Cow;
-use crate::rustc::hir::*;
use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
+use crate::rustc::hir::*;
use crate::rustc::lint::LateContext;
use crate::syntax::ast::Name;
use crate::syntax::source_map::Span;
use crate::utils::{get_pat_name, match_var, snippet};
+use std::borrow::Cow;
pub fn get_spans(
cx: &LateContext<'_, '_>,
replacements: &'static [(&'static str, &'static str)],
) -> Option<Vec<(Span, Cow<'static, str>)>> {
if let Some(body) = opt_body_id.map(|id| cx.tcx.hir.body(id)) {
- get_binding_name(&body.arguments[idx])
- .map_or_else(|| Some(vec![]), |name| extract_clone_suggestions(cx, name, replacements, body))
+ get_binding_name(&body.arguments[idx]).map_or_else(
+ || Some(vec![]),
+ |name| extract_clone_suggestions(cx, name, replacements, body),
+ )
} else {
Some(vec![])
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
//! Contains utility functions to generate suggestions.
#![deny(clippy::missing_docs_in_private_items)]
-use matches::matches;
use crate::rustc::hir;
use crate::rustc::lint::{EarlyContext, LateContext, LintContext};
use crate::rustc_errors;
-use std::borrow::Cow;
-use std::convert::TryInto;
-use std::fmt::Display;
-use std;
-use crate::syntax::source_map::{CharPos, Span};
+use crate::rustc_errors::Applicability;
+use crate::syntax::ast;
use crate::syntax::parse::token;
use crate::syntax::print::pprust::token_to_string;
+use crate::syntax::source_map::{CharPos, Span};
use crate::syntax::util::parser::AssocOp;
-use crate::syntax::ast;
-use crate::utils::{higher, in_macro, snippet, snippet_opt};
use crate::syntax_pos::{BytePos, Pos};
-use crate::rustc_errors::Applicability;
+use crate::utils::{higher, in_macro, snippet, snippet_opt};
+use matches::matches;
+use std;
+use std::borrow::Cow;
+use std::convert::TryInto;
+use std::fmt::Display;
/// A helper type to build suggestion correctly handling parenthesis.
pub enum Sugg<'a> {
snippet_opt(cx, expr.span).map(|snippet| {
let snippet = Cow::Owned(snippet);
match expr.node {
- hir::ExprKind::AddrOf(..) |
- hir::ExprKind::Box(..) |
- hir::ExprKind::Closure(.., _) |
- hir::ExprKind::If(..) |
- hir::ExprKind::Unary(..) |
- hir::ExprKind::Match(..) => Sugg::MaybeParen(snippet),
- hir::ExprKind::Continue(..) |
- hir::ExprKind::Yield(..) |
- hir::ExprKind::Array(..) |
- hir::ExprKind::Block(..) |
- hir::ExprKind::Break(..) |
- hir::ExprKind::Call(..) |
- hir::ExprKind::Field(..) |
- hir::ExprKind::Index(..) |
- hir::ExprKind::InlineAsm(..) |
- hir::ExprKind::Lit(..) |
- hir::ExprKind::Loop(..) |
- hir::ExprKind::MethodCall(..) |
- hir::ExprKind::Path(..) |
- hir::ExprKind::Repeat(..) |
- hir::ExprKind::Ret(..) |
- hir::ExprKind::Struct(..) |
- hir::ExprKind::Tup(..) |
- hir::ExprKind::While(..) => Sugg::NonParen(snippet),
+ hir::ExprKind::AddrOf(..)
+ | hir::ExprKind::Box(..)
+ | hir::ExprKind::Closure(.., _)
+ | hir::ExprKind::If(..)
+ | hir::ExprKind::Unary(..)
+ | hir::ExprKind::Match(..) => Sugg::MaybeParen(snippet),
+ hir::ExprKind::Continue(..)
+ | hir::ExprKind::Yield(..)
+ | hir::ExprKind::Array(..)
+ | hir::ExprKind::Block(..)
+ | hir::ExprKind::Break(..)
+ | hir::ExprKind::Call(..)
+ | hir::ExprKind::Field(..)
+ | hir::ExprKind::Index(..)
+ | hir::ExprKind::InlineAsm(..)
+ | hir::ExprKind::Lit(..)
+ | hir::ExprKind::Loop(..)
+ | hir::ExprKind::MethodCall(..)
+ | hir::ExprKind::Path(..)
+ | hir::ExprKind::Repeat(..)
+ | hir::ExprKind::Ret(..)
+ | hir::ExprKind::Struct(..)
+ | hir::ExprKind::Tup(..)
+ | hir::ExprKind::While(..) => Sugg::NonParen(snippet),
hir::ExprKind::Assign(..) => Sugg::BinOp(AssocOp::Assign, snippet),
hir::ExprKind::AssignOp(op, ..) => Sugg::BinOp(hirbinop2assignop(op), snippet),
hir::ExprKind::Binary(op, ..) => Sugg::BinOp(AssocOp::from_ast_binop(higher::binop(op.node)), snippet),
///
/// - Applicability level `Unspecified` will never be changed.
/// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`.
- /// - If the default value is used and the applicability level is `MachineApplicable`, change it to
+ /// - If the default value is used and the applicability level is `MachineApplicable`, change it
+ /// to
/// `HasPlaceholders`
pub fn hir_with_applicability(
cx: &LateContext<'_, '_>,
let snippet = snippet(cx, expr.span, default);
match expr.node {
- ast::ExprKind::AddrOf(..) |
- ast::ExprKind::Box(..) |
- ast::ExprKind::Closure(..) |
- ast::ExprKind::If(..) |
- ast::ExprKind::IfLet(..) |
- ast::ExprKind::ObsoleteInPlace(..) |
- ast::ExprKind::Unary(..) |
- ast::ExprKind::Match(..) => Sugg::MaybeParen(snippet),
- ast::ExprKind::Async(..) |
- ast::ExprKind::Block(..) |
- ast::ExprKind::Break(..) |
- ast::ExprKind::Call(..) |
- ast::ExprKind::Continue(..) |
- ast::ExprKind::Yield(..) |
- ast::ExprKind::Field(..) |
- ast::ExprKind::ForLoop(..) |
- ast::ExprKind::Index(..) |
- ast::ExprKind::InlineAsm(..) |
- ast::ExprKind::Lit(..) |
- ast::ExprKind::Loop(..) |
- ast::ExprKind::Mac(..) |
- ast::ExprKind::MethodCall(..) |
- ast::ExprKind::Paren(..) |
- ast::ExprKind::Path(..) |
- ast::ExprKind::Repeat(..) |
- ast::ExprKind::Ret(..) |
- ast::ExprKind::Struct(..) |
- ast::ExprKind::Try(..) |
- ast::ExprKind::TryBlock(..) |
- ast::ExprKind::Tup(..) |
- ast::ExprKind::Array(..) |
- ast::ExprKind::While(..) |
- ast::ExprKind::WhileLet(..) => Sugg::NonParen(snippet),
+ ast::ExprKind::AddrOf(..)
+ | ast::ExprKind::Box(..)
+ | ast::ExprKind::Closure(..)
+ | ast::ExprKind::If(..)
+ | ast::ExprKind::IfLet(..)
+ | ast::ExprKind::ObsoleteInPlace(..)
+ | ast::ExprKind::Unary(..)
+ | ast::ExprKind::Match(..) => Sugg::MaybeParen(snippet),
+ ast::ExprKind::Async(..)
+ | ast::ExprKind::Block(..)
+ | ast::ExprKind::Break(..)
+ | ast::ExprKind::Call(..)
+ | ast::ExprKind::Continue(..)
+ | ast::ExprKind::Yield(..)
+ | ast::ExprKind::Field(..)
+ | ast::ExprKind::ForLoop(..)
+ | ast::ExprKind::Index(..)
+ | ast::ExprKind::InlineAsm(..)
+ | ast::ExprKind::Lit(..)
+ | ast::ExprKind::Loop(..)
+ | ast::ExprKind::Mac(..)
+ | ast::ExprKind::MethodCall(..)
+ | ast::ExprKind::Paren(..)
+ | ast::ExprKind::Path(..)
+ | ast::ExprKind::Repeat(..)
+ | ast::ExprKind::Ret(..)
+ | ast::ExprKind::Struct(..)
+ | ast::ExprKind::Try(..)
+ | ast::ExprKind::TryBlock(..)
+ | ast::ExprKind::Tup(..)
+ | ast::ExprKind::Array(..)
+ | ast::ExprKind::While(..)
+ | ast::ExprKind::WhileLet(..) => Sugg::NonParen(snippet),
ast::ExprKind::Range(.., RangeLimits::HalfOpen) => Sugg::BinOp(AssocOp::DotDot, snippet),
ast::ExprKind::Range(.., RangeLimits::Closed) => Sugg::BinOp(AssocOp::DotDotEq, snippet),
ast::ExprKind::Assign(..) => Sugg::BinOp(AssocOp::Assign, snippet),
match self {
Sugg::NonParen(..) => self,
// (x) and (x).y() both don't need additional parens
- Sugg::MaybeParen(sugg) => if sugg.starts_with('(') && sugg.ends_with(')') {
- Sugg::MaybeParen(sugg)
- } else {
- Sugg::NonParen(format!("({})", sugg).into())
+ Sugg::MaybeParen(sugg) => {
+ if sugg.starts_with('(') && sugg.ends_with(')') {
+ Sugg::MaybeParen(sugg)
+ } else {
+ Sugg::NonParen(format!("({})", sugg).into())
+ }
},
Sugg::BinOp(_, sugg) => Sugg::NonParen(format!("({})", sugg).into()),
}
impl<T> ParenHelper<T> {
/// Build a `ParenHelper`.
fn new(paren: bool, wrapped: T) -> Self {
- Self {
- paren,
- wrapped,
- }
+ Self { paren, wrapped }
}
}
|| (other.precedence() == op.precedence()
&& ((op != other && associativity(op) != dir)
|| (op == other && associativity(op) != Associativity::Both)))
- || is_shift(op) && is_arith(other) || is_shift(other) && is_arith(op)
+ || is_shift(op) && is_arith(other)
+ || is_shift(other) && is_arith(op)
}
let lhs_paren = if let Sugg::BinOp(ref lop, _) = *lhs {
let lhs = ParenHelper::new(lhs_paren, lhs);
let rhs = ParenHelper::new(rhs_paren, rhs);
let sugg = match op {
- AssocOp::Add |
- AssocOp::BitAnd |
- AssocOp::BitOr |
- AssocOp::BitXor |
- AssocOp::Divide |
- AssocOp::Equal |
- AssocOp::Greater |
- AssocOp::GreaterEqual |
- AssocOp::LAnd |
- AssocOp::LOr |
- AssocOp::Less |
- AssocOp::LessEqual |
- AssocOp::Modulus |
- AssocOp::Multiply |
- AssocOp::NotEqual |
- AssocOp::ShiftLeft |
- AssocOp::ShiftRight |
- AssocOp::Subtract => format!("{} {} {}", lhs, op.to_ast_binop().expect("Those are AST ops").to_string(), rhs),
+ AssocOp::Add
+ | AssocOp::BitAnd
+ | AssocOp::BitOr
+ | AssocOp::BitXor
+ | AssocOp::Divide
+ | AssocOp::Equal
+ | AssocOp::Greater
+ | AssocOp::GreaterEqual
+ | AssocOp::LAnd
+ | AssocOp::LOr
+ | AssocOp::Less
+ | AssocOp::LessEqual
+ | AssocOp::Modulus
+ | AssocOp::Multiply
+ | AssocOp::NotEqual
+ | AssocOp::ShiftLeft
+ | AssocOp::ShiftRight
+ | AssocOp::Subtract => format!(
+ "{} {} {}",
+ lhs,
+ op.to_ast_binop().expect("Those are AST ops").to_string(),
+ rhs
+ ),
AssocOp::Assign => format!("{} = {}", lhs, rhs),
AssocOp::ObsoleteInPlace => format!("in ({}) {}", lhs, rhs),
AssocOp::AssignOp(op) => format!("{} {}= {}", lhs, token_to_string(&token::BinOp(op)), rhs),
match *op {
ObsoleteInPlace | Assign | AssignOp(_) => Associativity::Right,
Add | BitAnd | BitOr | BitXor | LAnd | LOr | Multiply | As | Colon => Associativity::Both,
- Divide |
- Equal |
- Greater |
- GreaterEqual |
- Less |
- LessEqual |
- Modulus |
- NotEqual |
- ShiftLeft |
- ShiftRight |
- Subtract => Associativity::Left,
+ Divide | Equal | Greater | GreaterEqual | Less | LessEqual | Modulus | NotEqual | ShiftLeft | ShiftRight
+ | Subtract => Associativity::Left,
DotDot | DotDotEq => Associativity::None,
}
}
hir::BinOpKind::Shr => Shr,
hir::BinOpKind::Sub => Minus,
- | hir::BinOpKind::And
+ hir::BinOpKind::And
| hir::BinOpKind::Eq
| hir::BinOpKind::Ge
| hir::BinOpKind::Gt
| hir::BinOpKind::Le
| hir::BinOpKind::Lt
| hir::BinOpKind::Ne
- | hir::BinOpKind::Or
- => panic!("This operator does not exist"),
+ | hir::BinOpKind::Or => panic!("This operator does not exist"),
})
}
/// before it on its line.
fn indentation<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option<String> {
let lo = cx.sess().source_map().lookup_char_pos(span.lo());
- if let Some(line) = lo.file
- .get_line(lo.line - 1 /* line numbers in `Loc` are 1-based */)
- {
+ if let Some(line) = lo.file.get_line(lo.line - 1 /* line numbers in `Loc` are 1-based */) {
if let Some((pos, _)) = line.char_indices().find(|&(_, c)| c != ' ' && c != '\t') {
// we can mix char and byte positions here because we only consider `[ \t]`
if lo.col == CharPos(pos) {
/// ```rust,ignore
/// db.suggest_item_with_attr(cx, item, "#[derive(Default)]");
/// ```
- fn suggest_item_with_attr<D: Display + ?Sized>(&mut self, cx: &T, item: Span, msg: &str, attr: &D, applicability: Applicability);
+ fn suggest_item_with_attr<D: Display + ?Sized>(
+ &mut self,
+ cx: &T,
+ item: Span,
+ msg: &str,
+ attr: &D,
+ applicability: Applicability,
+ );
/// Suggest to add an item before another.
///
}
impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_errors::DiagnosticBuilder<'b> {
- fn suggest_item_with_attr<D: Display + ?Sized>(&mut self, cx: &T, item: Span, msg: &str, attr: &D, applicability: Applicability) {
+ fn suggest_item_with_attr<D: Display + ?Sized>(
+ &mut self,
+ cx: &T,
+ item: Span,
+ msg: &str,
+ attr: &D,
+ applicability: Applicability,
+ ) {
if let Some(indent) = indentation(cx, item) {
let span = item.with_hi(item.lo());
- self.span_suggestion_with_applicability(
- span,
- msg,
- format!("{}\n{}", attr, indent),
- applicability,
- );
+ self.span_suggestion_with_applicability(span, msg, format!("{}\n{}", attr, indent), applicability);
}
}
})
.collect::<String>();
- self.span_suggestion_with_applicability(
- span,
- msg,
- format!("{}\n{}", new_item, indent),
- applicability,
- );
+ self.span_suggestion_with_applicability(span, msg, format!("{}\n{}", new_item, indent), applicability);
}
}
let non_whitespace_offset = src[fmpos.pos.to_usize()..].find(|c| c != ' ' && c != '\t' && c != '\n');
if let Some(non_whitespace_offset) = non_whitespace_offset {
- remove_span = remove_span.with_hi(remove_span.hi() + BytePos(non_whitespace_offset.try_into().expect("offset too large")))
+ remove_span = remove_span
+ .with_hi(remove_span.hi() + BytePos(non_whitespace_offset.try_into().expect("offset too large")))
}
}
- self.span_suggestion_with_applicability(
- remove_span,
- msg,
- String::new(),
- applicability,
- );
+ self.span_suggestion_with_applicability(remove_span, msg, String::new(), applicability);
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::lint::LateContext;
use crate::rustc::hir::def::Def;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::consts::constant;
use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
return;
}
},
- higher::VecArgs::Vec(args) => if let Some(last) = args.iter().last() {
- let span = args[0].span.to(last.span);
+ higher::VecArgs::Vec(args) => {
+ if let Some(last) = args.iter().last() {
+ let span = args[0].span.to(last.span);
- format!("&[{}]", snippet_with_applicability(cx, span, "..", &mut applicability))
- } else {
- "&[]".into()
+ format!("&[{}]", snippet_with_applicability(cx, span, "..", &mut applicability))
+ } else {
+ "&[]".into()
+ }
},
};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
let mut seen = false;
for arg in &args {
match arg.position {
- ArgumentImplicitlyIs(n) | ArgumentIs(n) => if n == idx {
- all_simple &= arg.format == SIMPLE;
- seen = true;
+ ArgumentImplicitlyIs(n) | ArgumentIs(n) => {
+ if n == idx {
+ all_simple &= arg.format == SIMPLE;
+ seen = true;
+ }
},
ArgumentNamed(_) => {},
}
for arg in &args {
match arg.position {
ArgumentImplicitlyIs(_) | ArgumentIs(_) => {},
- ArgumentNamed(name) => if *p == name {
- seen = true;
- all_simple &= arg.format == SIMPLE;
+ ArgumentNamed(name) => {
+ if *p == name {
+ seen = true;
+ all_simple &= arg.format == SIMPLE;
+ }
},
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use crate::consts::{constant_simple, Constant};
+use crate::rustc::hir::*;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
-use if_chain::if_chain;
-use crate::rustc::hir::*;
use crate::utils::span_help_and_lint;
+use if_chain::if_chain;
/// **What it does:** Checks for `0.0 / 0.0`.
///
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use std::env;
#[macro_export]
comment_width = 100
match_block_trailing_comma = true
wrap_comments = true
+
+error_on_line_overflow = true
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
// error-pattern:yummy
#![feature(box_syntax)]
#![feature(rustc_private)]
-
#![feature(try_from)]
#![allow(clippy::missing_docs_in_private_items)]
pub fn main() {
rustc_driver::init_rustc_env_logger();
- exit(rustc_driver::run(move || {
- use std::env;
-
- if std::env::args().any(|a| a == "--version" || a == "-V") {
- show_version();
- exit(0);
- }
-
- let sys_root = option_env!("SYSROOT")
- .map(String::from)
- .or_else(|| std::env::var("SYSROOT").ok())
- .or_else(|| {
- let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
- let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
- home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain)))
- })
- .or_else(|| {
- Command::new("rustc")
- .arg("--print")
- .arg("sysroot")
- .output()
- .ok()
- .and_then(|out| String::from_utf8(out.stdout).ok())
- .map(|s| s.trim().to_owned())
- })
- .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust");
-
- // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
- // We're invoking the compiler programmatically, so we ignore this/
- let mut orig_args: Vec<String> = env::args().collect();
- if orig_args.len() <= 1 {
- std::process::exit(1);
- }
- if Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref()) {
- // we still want to be able to invoke it normally though
- orig_args.remove(1);
- }
- // this conditional check for the --sysroot flag is there so users can call
- // `clippy_driver` directly
- // without having to pass --sysroot or anything
- let mut args: Vec<String> = if orig_args.iter().any(|s| s == "--sysroot") {
- orig_args.clone()
- } else {
- orig_args
- .clone()
- .into_iter()
- .chain(Some("--sysroot".to_owned()))
- .chain(Some(sys_root))
- .collect()
- };
-
- // this check ensures that dependencies are built but not linted and the final
- // crate is
- // linted but not built
- let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true")
- || orig_args.iter().any(|s| s == "--emit=dep-info,metadata");
-
- if clippy_enabled {
- args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]);
- if let Ok(extra_args) = env::var("CLIPPY_ARGS") {
- args.extend(
- extra_args
- .split("__CLIPPY_HACKERY__")
- .filter_map(|s| if s.is_empty() {
+ exit(
+ rustc_driver::run(move || {
+ use std::env;
+
+ if std::env::args().any(|a| a == "--version" || a == "-V") {
+ show_version();
+ exit(0);
+ }
+
+ let sys_root = option_env!("SYSROOT")
+ .map(String::from)
+ .or_else(|| std::env::var("SYSROOT").ok())
+ .or_else(|| {
+ let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
+ let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
+ home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain)))
+ })
+ .or_else(|| {
+ Command::new("rustc")
+ .arg("--print")
+ .arg("sysroot")
+ .output()
+ .ok()
+ .and_then(|out| String::from_utf8(out.stdout).ok())
+ .map(|s| s.trim().to_owned())
+ })
+ .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust");
+
+ // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
+ // We're invoking the compiler programmatically, so we ignore this/
+ let mut orig_args: Vec<String> = env::args().collect();
+ if orig_args.len() <= 1 {
+ std::process::exit(1);
+ }
+ if Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref()) {
+ // we still want to be able to invoke it normally though
+ orig_args.remove(1);
+ }
+ // this conditional check for the --sysroot flag is there so users can call
+ // `clippy_driver` directly
+ // without having to pass --sysroot or anything
+ let mut args: Vec<String> = if orig_args.iter().any(|s| s == "--sysroot") {
+ orig_args.clone()
+ } else {
+ orig_args
+ .clone()
+ .into_iter()
+ .chain(Some("--sysroot".to_owned()))
+ .chain(Some(sys_root))
+ .collect()
+ };
+
+ // this check ensures that dependencies are built but not linted and the final
+ // crate is
+ // linted but not built
+ let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true")
+ || orig_args.iter().any(|s| s == "--emit=dep-info,metadata");
+
+ if clippy_enabled {
+ args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]);
+ if let Ok(extra_args) = env::var("CLIPPY_ARGS") {
+ args.extend(extra_args.split("__CLIPPY_HACKERY__").filter_map(|s| {
+ if s.is_empty() {
None
} else {
Some(s.to_string())
- })
- );
- }
- }
-
- let mut controller = CompileController::basic();
- if clippy_enabled {
- controller.after_parse.callback = Box::new(move |state| {
- let mut registry = rustc_plugin::registry::Registry::new(
- state.session,
- state
- .krate
- .as_ref()
- .expect(
- "at this compilation stage \
- the crate must be parsed",
- )
- .span,
- );
- registry.args_hidden = Some(Vec::new());
-
- let conf = clippy_lints::read_conf(®istry);
- clippy_lints::register_plugins(&mut registry, &conf);
-
- let rustc_plugin::registry::Registry {
- early_lint_passes,
- late_lint_passes,
- lint_groups,
- llvm_passes,
- attributes,
- ..
- } = registry;
- let sess = &state.session;
- let mut ls = sess.lint_store.borrow_mut();
- for pass in early_lint_passes {
- ls.register_early_pass(Some(sess), true, pass);
- }
- for pass in late_lint_passes {
- ls.register_late_pass(Some(sess), true, pass);
- }
-
- for (name, (to, deprecated_name)) in lint_groups {
- ls.register_group(Some(sess), true, name, deprecated_name, to);
+ }
+ }));
}
- clippy_lints::register_pre_expansion_lints(sess, &mut ls, &conf);
-
- sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
- sess.plugin_attributes.borrow_mut().extend(attributes);
- });
- }
- controller.compilation_done.stop = Compilation::Stop;
+ }
- let args = args;
- rustc_driver::run_compiler(&args, Box::new(controller), None, None)
- }).try_into().expect("exit code too large"))
+ let mut controller = CompileController::basic();
+ if clippy_enabled {
+ controller.after_parse.callback = Box::new(move |state| {
+ let mut registry = rustc_plugin::registry::Registry::new(
+ state.session,
+ state
+ .krate
+ .as_ref()
+ .expect(
+ "at this compilation stage \
+ the crate must be parsed",
+ )
+ .span,
+ );
+ registry.args_hidden = Some(Vec::new());
+
+ let conf = clippy_lints::read_conf(®istry);
+ clippy_lints::register_plugins(&mut registry, &conf);
+
+ let rustc_plugin::registry::Registry {
+ early_lint_passes,
+ late_lint_passes,
+ lint_groups,
+ llvm_passes,
+ attributes,
+ ..
+ } = registry;
+ let sess = &state.session;
+ let mut ls = sess.lint_store.borrow_mut();
+ for pass in early_lint_passes {
+ ls.register_early_pass(Some(sess), true, pass);
+ }
+ for pass in late_lint_passes {
+ ls.register_late_pass(Some(sess), true, pass);
+ }
+
+ for (name, (to, deprecated_name)) in lint_groups {
+ ls.register_group(Some(sess), true, name, deprecated_name, to);
+ }
+ clippy_lints::register_pre_expansion_lints(sess, &mut ls, &conf);
+
+ sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
+ sess.plugin_attributes.borrow_mut().extend(attributes);
+ });
+ }
+ controller.compilation_done.stop = Compilation::Stop;
+
+ let args = args;
+ rustc_driver::run_compiler(&args, Box::new(controller), None, None)
+ })
+ .try_into()
+ .expect("exit code too large"),
+ )
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
// error-pattern:cargo-clippy
#![feature(plugin_registrar)]
#![feature(rustc_private)]
-
#![allow(clippy::missing_docs_in_private_items)]
#![warn(rust_2018_idioms)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
// error-pattern:yummy
#![feature(box_syntax)]
#![feature(rustc_private)]
-
#![allow(clippy::missing_docs_in_private_items)]
use rustc_tools_util::*;
.into_os_string()
},
)
- }).map(|p| ("CARGO_TARGET_DIR", p));
+ })
+ .map(|p| ("CARGO_TARGET_DIR", p));
let exit_status = std::process::Command::new("cargo")
.args(&args)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
#![feature(test)]
extern crate compiletest_rs as compiletest;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
#[test]
fn dogfood() {
if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
#![feature(rustc_private)]
extern crate clippy_lints;
#[test]
fn test_overlapping() {
- use clippy_lints::matches::overlapping;
use crate::syntax::source_map::DUMMY_SP;
+ use clippy_lints::matches::overlapping;
let sp = |s, e| clippy_lints::matches::SpannedRange {
span: DUMMY_SP,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-
-
// Tests for the various helper functions used by the needless_continue
// lint that don't belong in utils.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
extern crate cargo_metadata;
extern crate semver;
use semver::VersionReq;