mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-10 15:14:29 +00:00
Merge commit 'b7f3f7f6082679da2da9a0b3faf1b5adef3afd3b' into clippyup
This commit is contained in:
parent
87bb18e7c2
commit
5cf4984872
147 changed files with 4288 additions and 2969 deletions
|
@ -2695,6 +2695,7 @@ Released 2018-09-13
|
||||||
[`enum_glob_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_glob_use
|
[`enum_glob_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_glob_use
|
||||||
[`enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names
|
[`enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names
|
||||||
[`eq_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#eq_op
|
[`eq_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#eq_op
|
||||||
|
[`equatable_if_let`]: https://rust-lang.github.io/rust-clippy/master/index.html#equatable_if_let
|
||||||
[`erasing_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#erasing_op
|
[`erasing_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#erasing_op
|
||||||
[`eval_order_dependence`]: https://rust-lang.github.io/rust-clippy/master/index.html#eval_order_dependence
|
[`eval_order_dependence`]: https://rust-lang.github.io/rust-clippy/master/index.html#eval_order_dependence
|
||||||
[`excessive_precision`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_precision
|
[`excessive_precision`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_precision
|
||||||
|
@ -2898,6 +2899,7 @@ Released 2018-09-13
|
||||||
[`no_effect`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect
|
[`no_effect`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect
|
||||||
[`non_ascii_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_ascii_literal
|
[`non_ascii_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_ascii_literal
|
||||||
[`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions
|
[`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions
|
||||||
|
[`non_send_fields_in_send_ty`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty
|
||||||
[`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool
|
[`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool
|
||||||
[`nonsensical_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonsensical_open_options
|
[`nonsensical_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonsensical_open_options
|
||||||
[`nonstandard_macro_braces`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces
|
[`nonstandard_macro_braces`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces
|
||||||
|
|
|
@ -3,14 +3,7 @@
|
||||||
// warn on lints, that are included in `rust-lang/rust`s bootstrap
|
// warn on lints, that are included in `rust-lang/rust`s bootstrap
|
||||||
#![warn(rust_2018_idioms, unused_lifetimes)]
|
#![warn(rust_2018_idioms, unused_lifetimes)]
|
||||||
|
|
||||||
use itertools::Itertools;
|
use std::path::PathBuf;
|
||||||
use regex::Regex;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::ffi::OsStr;
|
|
||||||
use std::fs;
|
|
||||||
use std::lazy::SyncLazy;
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
use walkdir::WalkDir;
|
|
||||||
|
|
||||||
pub mod bless;
|
pub mod bless;
|
||||||
pub mod fmt;
|
pub mod fmt;
|
||||||
|
@ -19,323 +12,6 @@ pub mod serve;
|
||||||
pub mod setup;
|
pub mod setup;
|
||||||
pub mod update_lints;
|
pub mod update_lints;
|
||||||
|
|
||||||
static DEC_CLIPPY_LINT_RE: SyncLazy<Regex> = SyncLazy::new(|| {
|
|
||||||
Regex::new(
|
|
||||||
r#"(?x)
|
|
||||||
declare_clippy_lint!\s*[\{(]
|
|
||||||
(?:\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 DEC_DEPRECATED_LINT_RE: SyncLazy<Regex> = SyncLazy::new(|| {
|
|
||||||
Regex::new(
|
|
||||||
r#"(?x)
|
|
||||||
declare_deprecated_lint!\s*[{(]\s*
|
|
||||||
(?:\s+///.*)*
|
|
||||||
\s+pub\s+(?P<name>[A-Z_][A-Z_0-9]*)\s*,\s*
|
|
||||||
"(?P<desc>(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})]
|
|
||||||
"#,
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
});
|
|
||||||
static NL_ESCAPE_RE: SyncLazy<Regex> = SyncLazy::new(|| Regex::new(r#"\\\n\s*"#).unwrap());
|
|
||||||
|
|
||||||
pub static DOCS_LINK: &str = "https://rust-lang.github.io/rust-clippy/master/index.html";
|
|
||||||
|
|
||||||
/// Lint data parsed from the Clippy source code.
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
|
||||||
pub struct Lint {
|
|
||||||
pub name: String,
|
|
||||||
pub group: String,
|
|
||||||
pub desc: String,
|
|
||||||
pub deprecation: Option<String>,
|
|
||||||
pub module: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Lint {
|
|
||||||
#[must_use]
|
|
||||||
pub fn new(name: &str, group: &str, desc: &str, deprecation: Option<&str>, module: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.to_lowercase(),
|
|
||||||
group: group.to_string(),
|
|
||||||
desc: NL_ESCAPE_RE.replace(&desc.replace("\\\"", "\""), "").to_string(),
|
|
||||||
deprecation: deprecation.map(ToString::to_string),
|
|
||||||
module: module.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns all non-deprecated lints and non-internal lints
|
|
||||||
#[must_use]
|
|
||||||
pub fn usable_lints(lints: &[Self]) -> Vec<Self> {
|
|
||||||
lints
|
|
||||||
.iter()
|
|
||||||
.filter(|l| l.deprecation.is_none() && !l.group.starts_with("internal"))
|
|
||||||
.cloned()
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns all internal lints (not `internal_warn` lints)
|
|
||||||
#[must_use]
|
|
||||||
pub fn internal_lints(lints: &[Self]) -> Vec<Self> {
|
|
||||||
lints.iter().filter(|l| l.group == "internal").cloned().collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns all deprecated lints
|
|
||||||
#[must_use]
|
|
||||||
pub fn deprecated_lints(lints: &[Self]) -> Vec<Self> {
|
|
||||||
lints.iter().filter(|l| l.deprecation.is_some()).cloned().collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the lints in a `HashMap`, grouped by the different lint groups
|
|
||||||
#[must_use]
|
|
||||||
pub fn by_lint_group(lints: impl Iterator<Item = Self>) -> HashMap<String, Vec<Self>> {
|
|
||||||
lints.map(|lint| (lint.group.to_string(), lint)).into_group_map()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generates the Vec items for `register_lint_group` calls in `clippy_lints/src/lib.rs`.
|
|
||||||
#[must_use]
|
|
||||||
pub fn gen_lint_group_list<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> {
|
|
||||||
lints
|
|
||||||
.map(|l| format!(" LintId::of({}::{}),", l.module, l.name.to_uppercase()))
|
|
||||||
.sorted()
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generates the `pub mod module_name` list in `clippy_lints/src/lib.rs`.
|
|
||||||
#[must_use]
|
|
||||||
pub fn gen_modules_list<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> {
|
|
||||||
lints
|
|
||||||
.map(|l| &l.module)
|
|
||||||
.unique()
|
|
||||||
.map(|module| format!("mod {};", module))
|
|
||||||
.sorted()
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generates the list of lint links at the bottom of the README
|
|
||||||
#[must_use]
|
|
||||||
pub fn gen_changelog_lint_list<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> {
|
|
||||||
lints
|
|
||||||
.sorted_by_key(|l| &l.name)
|
|
||||||
.map(|l| format!("[`{}`]: {}#{}", l.name, DOCS_LINK, l.name))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generates the `register_removed` code in `./clippy_lints/src/lib.rs`.
|
|
||||||
#[must_use]
|
|
||||||
pub fn gen_deprecated<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> {
|
|
||||||
lints
|
|
||||||
.flat_map(|l| {
|
|
||||||
l.deprecation
|
|
||||||
.clone()
|
|
||||||
.map(|depr_text| {
|
|
||||||
vec![
|
|
||||||
" store.register_removed(".to_string(),
|
|
||||||
format!(" \"clippy::{}\",", l.name),
|
|
||||||
format!(" \"{}\",", depr_text),
|
|
||||||
" );".to_string(),
|
|
||||||
]
|
|
||||||
})
|
|
||||||
.expect("only deprecated lints should be passed")
|
|
||||||
})
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn gen_register_lint_list<'a>(
|
|
||||||
internal_lints: impl Iterator<Item = &'a Lint>,
|
|
||||||
usable_lints: impl Iterator<Item = &'a Lint>,
|
|
||||||
) -> Vec<String> {
|
|
||||||
let header = " store.register_lints(&[".to_string();
|
|
||||||
let footer = " ]);".to_string();
|
|
||||||
let internal_lints = internal_lints
|
|
||||||
.sorted_by_key(|l| format!(" {}::{},", l.module, l.name.to_uppercase()))
|
|
||||||
.map(|l| {
|
|
||||||
format!(
|
|
||||||
" #[cfg(feature = \"internal-lints\")]\n {}::{},",
|
|
||||||
l.module,
|
|
||||||
l.name.to_uppercase()
|
|
||||||
)
|
|
||||||
});
|
|
||||||
let other_lints = usable_lints
|
|
||||||
.sorted_by_key(|l| format!(" {}::{},", l.module, l.name.to_uppercase()))
|
|
||||||
.map(|l| format!(" {}::{},", l.module, l.name.to_uppercase()))
|
|
||||||
.sorted();
|
|
||||||
let mut lint_list = vec![header];
|
|
||||||
lint_list.extend(internal_lints);
|
|
||||||
lint_list.extend(other_lints);
|
|
||||||
lint_list.push(footer);
|
|
||||||
lint_list
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gathers all files in `src/clippy_lints` and gathers all lints inside
|
|
||||||
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> {
|
|
||||||
let content = fs::read_to_string(dir_entry.path()).unwrap();
|
|
||||||
let path = dir_entry.path();
|
|
||||||
let filename = path.file_stem().unwrap();
|
|
||||||
let path_buf = path.with_file_name(filename);
|
|
||||||
let mut rel_path = path_buf
|
|
||||||
.strip_prefix(clippy_project_root().join("clippy_lints/src"))
|
|
||||||
.expect("only files in `clippy_lints/src` should be looked at");
|
|
||||||
// If the lints are stored in mod.rs, we get the module name from
|
|
||||||
// the containing directory:
|
|
||||||
if filename == "mod" {
|
|
||||||
rel_path = rel_path.parent().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
let module = rel_path
|
|
||||||
.components()
|
|
||||||
.map(|c| c.as_os_str().to_str().unwrap())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join("::");
|
|
||||||
|
|
||||||
parse_contents(&content, &module)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_contents(content: &str, module: &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, module));
|
|
||||||
let deprecated = DEC_DEPRECATED_LINT_RE
|
|
||||||
.captures_iter(content)
|
|
||||||
.map(|m| Lint::new(&m["name"], "Deprecated", &m["desc"], Some(&m["desc"]), module));
|
|
||||||
// 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> {
|
|
||||||
// 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/`.
|
|
||||||
let path = clippy_project_root().join("clippy_lints/src");
|
|
||||||
WalkDir::new(path)
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(Result::ok)
|
|
||||||
.filter(|f| f.path().extension() == Some(OsStr::new("rs")))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether a file has had its text changed or not
|
|
||||||
#[derive(PartialEq, Debug)]
|
|
||||||
pub struct FileChange {
|
|
||||||
pub changed: bool,
|
|
||||||
pub new_lines: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Replaces a region in a file delimited by two lines matching regexes.
|
|
||||||
///
|
|
||||||
/// `path` is the relative path to the file on which you want to perform the replacement.
|
|
||||||
///
|
|
||||||
/// See `replace_region_in_text` for documentation of the other options.
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// Panics if the path could not read or then written
|
|
||||||
pub fn replace_region_in_file<F>(
|
|
||||||
path: &Path,
|
|
||||||
start: &str,
|
|
||||||
end: &str,
|
|
||||||
replace_start: bool,
|
|
||||||
write_back: bool,
|
|
||||||
replacements: F,
|
|
||||||
) -> FileChange
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Vec<String>,
|
|
||||||
{
|
|
||||||
let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from {}: {}", path.display(), e));
|
|
||||||
let file_change = replace_region_in_text(&contents, start, end, replace_start, replacements);
|
|
||||||
|
|
||||||
if write_back {
|
|
||||||
if let Err(e) = fs::write(path, file_change.new_lines.as_bytes()) {
|
|
||||||
panic!("Cannot write to {}: {}", path.display(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_change
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Replaces a region in a text delimited by two lines matching regexes.
|
|
||||||
///
|
|
||||||
/// * `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.
|
|
||||||
/// * `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,
|
|
||||||
/// use `replace_region_in_file`.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// let the_text = "replace_start\nsome text\nthat will be replaced\nreplace_end";
|
|
||||||
/// let result =
|
|
||||||
/// clippy_dev::replace_region_in_text(the_text, "replace_start", "replace_end", false, || {
|
|
||||||
/// vec!["a different".to_string(), "text".to_string()]
|
|
||||||
/// })
|
|
||||||
/// .new_lines;
|
|
||||||
/// assert_eq!("replace_start\na different\ntext\nreplace_end", result);
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// Panics if start or end is not valid regex
|
|
||||||
pub fn replace_region_in_text<F>(text: &str, start: &str, end: &str, replace_start: bool, replacements: F) -> FileChange
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Vec<String>,
|
|
||||||
{
|
|
||||||
let replace_it = replacements();
|
|
||||||
let mut in_old_region = false;
|
|
||||||
let mut found = false;
|
|
||||||
let mut new_lines = vec![];
|
|
||||||
let start = Regex::new(start).unwrap();
|
|
||||||
let end = Regex::new(end).unwrap();
|
|
||||||
|
|
||||||
for line in text.lines() {
|
|
||||||
if in_old_region {
|
|
||||||
if end.is_match(line) {
|
|
||||||
in_old_region = false;
|
|
||||||
new_lines.extend(replace_it.clone());
|
|
||||||
new_lines.push(line.to_string());
|
|
||||||
}
|
|
||||||
} else if start.is_match(line) {
|
|
||||||
if !replace_start {
|
|
||||||
new_lines.push(line.to_string());
|
|
||||||
}
|
|
||||||
in_old_region = true;
|
|
||||||
found = true;
|
|
||||||
} else {
|
|
||||||
new_lines.push(line.to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
// This happens if the provided regex in `clippy_dev/src/main.rs` does not match in the
|
|
||||||
// given text or file. Most likely this is an error on the programmer's side and the Regex
|
|
||||||
// is incorrect.
|
|
||||||
eprintln!("error: regex \n{:?}\ndoesn't match. You may have to update it.", start);
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut new_lines = new_lines.join("\n");
|
|
||||||
if text.ends_with('\n') {
|
|
||||||
new_lines.push('\n');
|
|
||||||
}
|
|
||||||
let changed = new_lines != text;
|
|
||||||
FileChange { changed, new_lines }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the path to the Clippy project directory
|
/// Returns the path to the Clippy project directory
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
|
@ -360,200 +36,3 @@ pub fn clippy_project_root() -> PathBuf {
|
||||||
}
|
}
|
||||||
panic!("error: Can't determine root of project. Please run inside a Clippy working dir.");
|
panic!("error: Can't determine root of project. Please run inside a Clippy working dir.");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_parse_contents() {
|
|
||||||
let result: Vec<Lint> = parse_contents(
|
|
||||||
r#"
|
|
||||||
declare_clippy_lint! {
|
|
||||||
pub PTR_ARG,
|
|
||||||
style,
|
|
||||||
"really long \
|
|
||||||
text"
|
|
||||||
}
|
|
||||||
|
|
||||||
declare_clippy_lint!{
|
|
||||||
pub DOC_MARKDOWN,
|
|
||||||
pedantic,
|
|
||||||
"single line"
|
|
||||||
}
|
|
||||||
|
|
||||||
/// some doc comment
|
|
||||||
declare_deprecated_lint! {
|
|
||||||
pub SHOULD_ASSERT_EQ,
|
|
||||||
"`assert!()` will be more flexible with RFC 2011"
|
|
||||||
}
|
|
||||||
"#,
|
|
||||||
"module_name",
|
|
||||||
)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let expected = vec![
|
|
||||||
Lint::new("ptr_arg", "style", "really long text", None, "module_name"),
|
|
||||||
Lint::new("doc_markdown", "pedantic", "single line", None, "module_name"),
|
|
||||||
Lint::new(
|
|
||||||
"should_assert_eq",
|
|
||||||
"Deprecated",
|
|
||||||
"`assert!()` will be more flexible with RFC 2011",
|
|
||||||
Some("`assert!()` will be more flexible with RFC 2011"),
|
|
||||||
"module_name",
|
|
||||||
),
|
|
||||||
];
|
|
||||||
assert_eq!(expected, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_replace_region() {
|
|
||||||
let text = "\nabc\n123\n789\ndef\nghi";
|
|
||||||
let expected = FileChange {
|
|
||||||
changed: true,
|
|
||||||
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()]
|
|
||||||
});
|
|
||||||
assert_eq!(expected, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_replace_region_with_start() {
|
|
||||||
let text = "\nabc\n123\n789\ndef\nghi";
|
|
||||||
let expected = FileChange {
|
|
||||||
changed: true,
|
|
||||||
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()]
|
|
||||||
});
|
|
||||||
assert_eq!(expected, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_replace_region_no_changes() {
|
|
||||||
let text = "123\n456\n789";
|
|
||||||
let expected = FileChange {
|
|
||||||
changed: false,
|
|
||||||
new_lines: "123\n456\n789".to_string(),
|
|
||||||
};
|
|
||||||
let result = replace_region_in_text(text, r#"^\s*123$"#, r#"^\s*456"#, false, Vec::new);
|
|
||||||
assert_eq!(expected, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_usable_lints() {
|
|
||||||
let lints = vec![
|
|
||||||
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",
|
|
||||||
)];
|
|
||||||
assert_eq!(expected, Lint::usable_lints(&lints));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_by_lint_group() {
|
|
||||||
let lints = vec![
|
|
||||||
Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
|
|
||||||
Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"),
|
|
||||||
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")],
|
|
||||||
);
|
|
||||||
assert_eq!(expected, Lint::by_lint_group(lints.into_iter()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_gen_changelog_lint_list() {
|
|
||||||
let lints = vec![
|
|
||||||
Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
|
|
||||||
Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"),
|
|
||||||
];
|
|
||||||
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()),
|
|
||||||
];
|
|
||||||
assert_eq!(expected, gen_changelog_lint_list(lints.iter()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_gen_deprecated() {
|
|
||||||
let lints = vec![
|
|
||||||
Lint::new(
|
|
||||||
"should_assert_eq",
|
|
||||||
"group1",
|
|
||||||
"abc",
|
|
||||||
Some("has been superseded by should_assert_eq2"),
|
|
||||||
"module_name",
|
|
||||||
),
|
|
||||||
Lint::new(
|
|
||||||
"another_deprecated",
|
|
||||||
"group2",
|
|
||||||
"abc",
|
|
||||||
Some("will be removed"),
|
|
||||||
"module_name",
|
|
||||||
),
|
|
||||||
];
|
|
||||||
let expected: Vec<String> = vec![
|
|
||||||
" store.register_removed(",
|
|
||||||
" \"clippy::should_assert_eq\",",
|
|
||||||
" \"has been superseded by should_assert_eq2\",",
|
|
||||||
" );",
|
|
||||||
" store.register_removed(",
|
|
||||||
" \"clippy::another_deprecated\",",
|
|
||||||
" \"will be removed\",",
|
|
||||||
" );",
|
|
||||||
]
|
|
||||||
.into_iter()
|
|
||||||
.map(String::from)
|
|
||||||
.collect();
|
|
||||||
assert_eq!(expected, gen_deprecated(lints.iter()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic]
|
|
||||||
fn test_gen_deprecated_fail() {
|
|
||||||
let lints = vec![Lint::new("should_assert_eq2", "group2", "abc", None, "module_name")];
|
|
||||||
let _deprecated_lints = gen_deprecated(lints.iter());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_gen_modules_list() {
|
|
||||||
let lints = vec![
|
|
||||||
Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
|
|
||||||
Lint::new("incorrect_stuff", "group3", "abc", None, "another_module"),
|
|
||||||
];
|
|
||||||
let expected = vec!["mod another_module;".to_string(), "mod module_name;".to_string()];
|
|
||||||
assert_eq!(expected, gen_modules_list(lints.iter()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_gen_lint_group_list() {
|
|
||||||
let lints = vec![
|
|
||||||
Lint::new("abc", "group1", "abc", None, "module_name"),
|
|
||||||
Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
|
|
||||||
Lint::new("internal", "internal_style", "abc", None, "module_name"),
|
|
||||||
];
|
|
||||||
let expected = vec![
|
|
||||||
" LintId::of(module_name::ABC),".to_string(),
|
|
||||||
" LintId::of(module_name::INTERNAL),".to_string(),
|
|
||||||
" LintId::of(module_name::SHOULD_ASSERT_EQ),".to_string(),
|
|
||||||
];
|
|
||||||
assert_eq!(expected, gen_lint_group_list(lints.iter()));
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,8 +1,45 @@
|
||||||
use crate::{
|
use itertools::Itertools;
|
||||||
gather_all, gen_changelog_lint_list, gen_deprecated, gen_lint_group_list, gen_modules_list, gen_register_lint_list,
|
use regex::Regex;
|
||||||
replace_region_in_file, Lint, DOCS_LINK,
|
use std::collections::HashMap;
|
||||||
};
|
use std::ffi::OsStr;
|
||||||
|
use std::fs;
|
||||||
|
use std::lazy::SyncLazy;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
|
use crate::clippy_project_root;
|
||||||
|
|
||||||
|
const GENERATED_FILE_COMMENT: &str = "// This file was generated by `cargo dev update_lints`.\n\
|
||||||
|
// Use that command to update this file and do not edit by hand.\n\
|
||||||
|
// Manual edits will be overwritten.\n\n";
|
||||||
|
|
||||||
|
static DEC_CLIPPY_LINT_RE: SyncLazy<Regex> = SyncLazy::new(|| {
|
||||||
|
Regex::new(
|
||||||
|
r#"(?x)
|
||||||
|
declare_clippy_lint!\s*[\{(]
|
||||||
|
(?:\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 DEC_DEPRECATED_LINT_RE: SyncLazy<Regex> = SyncLazy::new(|| {
|
||||||
|
Regex::new(
|
||||||
|
r#"(?x)
|
||||||
|
declare_deprecated_lint!\s*[{(]\s*
|
||||||
|
(?:\s+///.*)*
|
||||||
|
\s+pub\s+(?P<name>[A-Z_][A-Z_0-9]*)\s*,\s*
|
||||||
|
"(?P<desc>(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})]
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
static NL_ESCAPE_RE: SyncLazy<Regex> = SyncLazy::new(|| Regex::new(r#"\\\n\s*"#).unwrap());
|
||||||
|
|
||||||
|
static DOCS_LINK: &str = "https://rust-lang.github.io/rust-clippy/master/index.html";
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
pub enum UpdateMode {
|
pub enum UpdateMode {
|
||||||
|
@ -10,6 +47,15 @@ pub enum UpdateMode {
|
||||||
Change,
|
Change,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Runs the `update_lints` command.
|
||||||
|
///
|
||||||
|
/// This updates various generated values from the lint source code.
|
||||||
|
///
|
||||||
|
/// `update_mode` indicates if the files should be updated or if updates should be checked for.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if a file path could not read from or then written to
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
pub fn run(update_mode: UpdateMode) {
|
pub fn run(update_mode: UpdateMode) {
|
||||||
let lint_list: Vec<Lint> = gather_all().collect();
|
let lint_list: Vec<Lint> = gather_all().collect();
|
||||||
|
@ -52,26 +98,7 @@ pub fn run(update_mode: UpdateMode) {
|
||||||
)
|
)
|
||||||
.changed;
|
.changed;
|
||||||
|
|
||||||
file_change |= replace_region_in_file(
|
// This has to be in lib.rs, otherwise rustfmt doesn't work
|
||||||
Path::new("clippy_lints/src/lib.rs"),
|
|
||||||
"begin deprecated lints",
|
|
||||||
"end deprecated lints",
|
|
||||||
false,
|
|
||||||
update_mode == UpdateMode::Change,
|
|
||||||
|| gen_deprecated(deprecated_lints.iter()),
|
|
||||||
)
|
|
||||||
.changed;
|
|
||||||
|
|
||||||
file_change |= replace_region_in_file(
|
|
||||||
Path::new("clippy_lints/src/lib.rs"),
|
|
||||||
"begin register lints",
|
|
||||||
"end register lints",
|
|
||||||
false,
|
|
||||||
update_mode == UpdateMode::Change,
|
|
||||||
|| gen_register_lint_list(internal_lints.iter(), usable_lints.iter()),
|
|
||||||
)
|
|
||||||
.changed;
|
|
||||||
|
|
||||||
file_change |= replace_region_in_file(
|
file_change |= replace_region_in_file(
|
||||||
Path::new("clippy_lints/src/lib.rs"),
|
Path::new("clippy_lints/src/lib.rs"),
|
||||||
"begin lints modules",
|
"begin lints modules",
|
||||||
|
@ -82,46 +109,37 @@ pub fn run(update_mode: UpdateMode) {
|
||||||
)
|
)
|
||||||
.changed;
|
.changed;
|
||||||
|
|
||||||
// Generate lists of lints in the clippy::all lint group
|
if file_change && update_mode == UpdateMode::Check {
|
||||||
file_change |= replace_region_in_file(
|
exit_with_failure();
|
||||||
Path::new("clippy_lints/src/lib.rs"),
|
|
||||||
r#"store.register_group\(true, "clippy::all""#,
|
|
||||||
r#"\]\);"#,
|
|
||||||
false,
|
|
||||||
update_mode == UpdateMode::Change,
|
|
||||||
|| {
|
|
||||||
// clippy::all should only include the following lint groups:
|
|
||||||
let all_group_lints = usable_lints.iter().filter(|l| {
|
|
||||||
matches!(
|
|
||||||
&*l.group,
|
|
||||||
"correctness" | "suspicious" | "style" | "complexity" | "perf"
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
gen_lint_group_list(all_group_lints)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.changed;
|
|
||||||
|
|
||||||
// Generate the list of lints for all other lint groups
|
|
||||||
for (lint_group, lints) in Lint::by_lint_group(usable_lints.into_iter().chain(internal_lints)) {
|
|
||||||
file_change |= replace_region_in_file(
|
|
||||||
Path::new("clippy_lints/src/lib.rs"),
|
|
||||||
&format!("store.register_group\\(true, \"clippy::{}\"", lint_group),
|
|
||||||
r#"\]\);"#,
|
|
||||||
false,
|
|
||||||
update_mode == UpdateMode::Change,
|
|
||||||
|| gen_lint_group_list(lints.iter()),
|
|
||||||
)
|
|
||||||
.changed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if update_mode == UpdateMode::Check && file_change {
|
process_file(
|
||||||
println!(
|
"clippy_lints/src/lib.register_lints.rs",
|
||||||
"Not all lints defined properly. \
|
update_mode,
|
||||||
Please run `cargo dev update_lints` to make sure all lints are defined properly."
|
&gen_register_lint_list(internal_lints.iter(), usable_lints.iter()),
|
||||||
|
);
|
||||||
|
process_file(
|
||||||
|
"clippy_lints/src/lib.deprecated.rs",
|
||||||
|
update_mode,
|
||||||
|
&gen_deprecated(deprecated_lints.iter()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let all_group_lints = usable_lints.iter().filter(|l| {
|
||||||
|
matches!(
|
||||||
|
&*l.group,
|
||||||
|
"correctness" | "suspicious" | "style" | "complexity" | "perf"
|
||||||
|
)
|
||||||
|
});
|
||||||
|
let content = gen_lint_group_list("all", all_group_lints);
|
||||||
|
process_file("clippy_lints/src/lib.register_all.rs", update_mode, &content);
|
||||||
|
|
||||||
|
for (lint_group, lints) in Lint::by_lint_group(usable_lints.into_iter().chain(internal_lints)) {
|
||||||
|
let content = gen_lint_group_list(&lint_group, lints.iter());
|
||||||
|
process_file(
|
||||||
|
&format!("clippy_lints/src/lib.register_{}.rs", lint_group),
|
||||||
|
update_mode,
|
||||||
|
&content,
|
||||||
);
|
);
|
||||||
std::process::exit(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,3 +168,538 @@ pub fn print_lints() {
|
||||||
fn round_to_fifty(count: usize) -> usize {
|
fn round_to_fifty(count: usize) -> usize {
|
||||||
count / 50 * 50
|
count / 50 * 50
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn process_file(path: impl AsRef<Path>, update_mode: UpdateMode, content: &str) {
|
||||||
|
if update_mode == UpdateMode::Check {
|
||||||
|
let old_content =
|
||||||
|
fs::read_to_string(&path).unwrap_or_else(|e| panic!("Cannot read from {}: {}", path.as_ref().display(), e));
|
||||||
|
if content != old_content {
|
||||||
|
exit_with_failure();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fs::write(&path, content.as_bytes())
|
||||||
|
.unwrap_or_else(|e| panic!("Cannot write to {}: {}", path.as_ref().display(), e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exit_with_failure() {
|
||||||
|
println!(
|
||||||
|
"Not all lints defined properly. \
|
||||||
|
Please run `cargo dev update_lints` to make sure all lints are defined properly."
|
||||||
|
);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Lint data parsed from the Clippy source code.
|
||||||
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
|
struct Lint {
|
||||||
|
name: String,
|
||||||
|
group: String,
|
||||||
|
desc: String,
|
||||||
|
deprecation: Option<String>,
|
||||||
|
module: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Lint {
|
||||||
|
#[must_use]
|
||||||
|
fn new(name: &str, group: &str, desc: &str, deprecation: Option<&str>, module: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_lowercase(),
|
||||||
|
group: group.to_string(),
|
||||||
|
desc: NL_ESCAPE_RE.replace(&desc.replace("\\\"", "\""), "").to_string(),
|
||||||
|
deprecation: deprecation.map(ToString::to_string),
|
||||||
|
module: module.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns all non-deprecated lints and non-internal lints
|
||||||
|
#[must_use]
|
||||||
|
fn usable_lints(lints: &[Self]) -> Vec<Self> {
|
||||||
|
lints
|
||||||
|
.iter()
|
||||||
|
.filter(|l| l.deprecation.is_none() && !l.group.starts_with("internal"))
|
||||||
|
.cloned()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns all internal lints (not `internal_warn` lints)
|
||||||
|
#[must_use]
|
||||||
|
fn internal_lints(lints: &[Self]) -> Vec<Self> {
|
||||||
|
lints.iter().filter(|l| l.group == "internal").cloned().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns all deprecated lints
|
||||||
|
#[must_use]
|
||||||
|
fn deprecated_lints(lints: &[Self]) -> Vec<Self> {
|
||||||
|
lints.iter().filter(|l| l.deprecation.is_some()).cloned().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the lints in a `HashMap`, grouped by the different lint groups
|
||||||
|
#[must_use]
|
||||||
|
fn by_lint_group(lints: impl Iterator<Item = Self>) -> HashMap<String, Vec<Self>> {
|
||||||
|
lints.map(|lint| (lint.group.to_string(), lint)).into_group_map()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates the code for registering a group
|
||||||
|
fn gen_lint_group_list<'a>(group_name: &str, lints: impl Iterator<Item = &'a Lint>) -> String {
|
||||||
|
let mut details: Vec<_> = lints.map(|l| (&l.module, l.name.to_uppercase())).collect();
|
||||||
|
details.sort_unstable();
|
||||||
|
|
||||||
|
let mut output = GENERATED_FILE_COMMENT.to_string();
|
||||||
|
|
||||||
|
output.push_str(&format!(
|
||||||
|
"store.register_group(true, \"clippy::{0}\", Some(\"clippy_{0}\"), vec![\n",
|
||||||
|
group_name
|
||||||
|
));
|
||||||
|
for (module, name) in details {
|
||||||
|
output.push_str(&format!(" LintId::of({}::{}),\n", module, name));
|
||||||
|
}
|
||||||
|
output.push_str("])\n");
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates the module declarations for `lints`
|
||||||
|
#[must_use]
|
||||||
|
fn gen_modules_list<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> {
|
||||||
|
lints
|
||||||
|
.map(|l| &l.module)
|
||||||
|
.unique()
|
||||||
|
.map(|module| format!("mod {};", module))
|
||||||
|
.sorted()
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates the list of lint links at the bottom of the CHANGELOG
|
||||||
|
#[must_use]
|
||||||
|
fn gen_changelog_lint_list<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> {
|
||||||
|
lints
|
||||||
|
.sorted_by_key(|l| &l.name)
|
||||||
|
.map(|l| format!("[`{}`]: {}#{}", l.name, DOCS_LINK, l.name))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates the `register_removed` code
|
||||||
|
#[must_use]
|
||||||
|
fn gen_deprecated<'a>(lints: impl Iterator<Item = &'a Lint>) -> String {
|
||||||
|
let mut output = GENERATED_FILE_COMMENT.to_string();
|
||||||
|
output.push_str("{\n");
|
||||||
|
for Lint { name, deprecation, .. } in lints {
|
||||||
|
output.push_str(&format!(
|
||||||
|
concat!(
|
||||||
|
" store.register_removed(\n",
|
||||||
|
" \"clippy::{}\",\n",
|
||||||
|
" \"{}\",\n",
|
||||||
|
" );\n"
|
||||||
|
),
|
||||||
|
name,
|
||||||
|
deprecation.as_ref().expect("`lints` are deprecated")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
output.push_str("}\n");
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates the code for registering lints
|
||||||
|
#[must_use]
|
||||||
|
fn gen_register_lint_list<'a>(
|
||||||
|
internal_lints: impl Iterator<Item = &'a Lint>,
|
||||||
|
usable_lints: impl Iterator<Item = &'a Lint>,
|
||||||
|
) -> String {
|
||||||
|
let mut details: Vec<_> = internal_lints
|
||||||
|
.map(|l| (false, &l.module, l.name.to_uppercase()))
|
||||||
|
.chain(usable_lints.map(|l| (true, &l.module, l.name.to_uppercase())))
|
||||||
|
.collect();
|
||||||
|
details.sort_unstable();
|
||||||
|
|
||||||
|
let mut output = GENERATED_FILE_COMMENT.to_string();
|
||||||
|
output.push_str("store.register_lints(&[\n");
|
||||||
|
|
||||||
|
for (is_public, module_name, lint_name) in details {
|
||||||
|
if !is_public {
|
||||||
|
output.push_str(" #[cfg(feature = \"internal-lints\")]\n");
|
||||||
|
}
|
||||||
|
output.push_str(&format!(" {}::{},\n", module_name, lint_name));
|
||||||
|
}
|
||||||
|
output.push_str("])\n");
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gathers all files in `src/clippy_lints` and gathers all lints inside
|
||||||
|
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> {
|
||||||
|
let content = fs::read_to_string(dir_entry.path()).unwrap();
|
||||||
|
let path = dir_entry.path();
|
||||||
|
let filename = path.file_stem().unwrap();
|
||||||
|
let path_buf = path.with_file_name(filename);
|
||||||
|
let mut rel_path = path_buf
|
||||||
|
.strip_prefix(clippy_project_root().join("clippy_lints/src"))
|
||||||
|
.expect("only files in `clippy_lints/src` should be looked at");
|
||||||
|
// If the lints are stored in mod.rs, we get the module name from
|
||||||
|
// the containing directory:
|
||||||
|
if filename == "mod" {
|
||||||
|
rel_path = rel_path.parent().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let module = rel_path
|
||||||
|
.components()
|
||||||
|
.map(|c| c.as_os_str().to_str().unwrap())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("::");
|
||||||
|
|
||||||
|
parse_contents(&content, &module)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_contents(content: &str, module: &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, module));
|
||||||
|
let deprecated = DEC_DEPRECATED_LINT_RE
|
||||||
|
.captures_iter(content)
|
||||||
|
.map(|m| Lint::new(&m["name"], "Deprecated", &m["desc"], Some(&m["desc"]), module));
|
||||||
|
// 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> {
|
||||||
|
// 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/`.
|
||||||
|
let path = clippy_project_root().join("clippy_lints/src");
|
||||||
|
WalkDir::new(path)
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(Result::ok)
|
||||||
|
.filter(|f| f.path().extension() == Some(OsStr::new("rs")))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether a file has had its text changed or not
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
|
struct FileChange {
|
||||||
|
changed: bool,
|
||||||
|
new_lines: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Replaces a region in a file delimited by two lines matching regexes.
|
||||||
|
///
|
||||||
|
/// `path` is the relative path to the file on which you want to perform the replacement.
|
||||||
|
///
|
||||||
|
/// See `replace_region_in_text` for documentation of the other options.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the path could not read or then written
|
||||||
|
fn replace_region_in_file<F>(
|
||||||
|
path: &Path,
|
||||||
|
start: &str,
|
||||||
|
end: &str,
|
||||||
|
replace_start: bool,
|
||||||
|
write_back: bool,
|
||||||
|
replacements: F,
|
||||||
|
) -> FileChange
|
||||||
|
where
|
||||||
|
F: FnOnce() -> Vec<String>,
|
||||||
|
{
|
||||||
|
let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from {}: {}", path.display(), e));
|
||||||
|
let file_change = replace_region_in_text(&contents, start, end, replace_start, replacements);
|
||||||
|
|
||||||
|
if write_back {
|
||||||
|
if let Err(e) = fs::write(path, file_change.new_lines.as_bytes()) {
|
||||||
|
panic!("Cannot write to {}: {}", path.display(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_change
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Replaces a region in a text delimited by two lines matching regexes.
|
||||||
|
///
|
||||||
|
/// * `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.
|
||||||
|
/// * `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,
|
||||||
|
/// use `replace_region_in_file`.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// let the_text = "replace_start\nsome text\nthat will be replaced\nreplace_end";
|
||||||
|
/// let result =
|
||||||
|
/// replace_region_in_text(the_text, "replace_start", "replace_end", false, || {
|
||||||
|
/// vec!["a different".to_string(), "text".to_string()]
|
||||||
|
/// })
|
||||||
|
/// .new_lines;
|
||||||
|
/// assert_eq!("replace_start\na different\ntext\nreplace_end", result);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if start or end is not valid regex
|
||||||
|
fn replace_region_in_text<F>(text: &str, start: &str, end: &str, replace_start: bool, replacements: F) -> FileChange
|
||||||
|
where
|
||||||
|
F: FnOnce() -> Vec<String>,
|
||||||
|
{
|
||||||
|
let replace_it = replacements();
|
||||||
|
let mut in_old_region = false;
|
||||||
|
let mut found = false;
|
||||||
|
let mut new_lines = vec![];
|
||||||
|
let start = Regex::new(start).unwrap();
|
||||||
|
let end = Regex::new(end).unwrap();
|
||||||
|
|
||||||
|
for line in text.lines() {
|
||||||
|
if in_old_region {
|
||||||
|
if end.is_match(line) {
|
||||||
|
in_old_region = false;
|
||||||
|
new_lines.extend(replace_it.clone());
|
||||||
|
new_lines.push(line.to_string());
|
||||||
|
}
|
||||||
|
} else if start.is_match(line) {
|
||||||
|
if !replace_start {
|
||||||
|
new_lines.push(line.to_string());
|
||||||
|
}
|
||||||
|
in_old_region = true;
|
||||||
|
found = true;
|
||||||
|
} else {
|
||||||
|
new_lines.push(line.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
// This happens if the provided regex in `clippy_dev/src/main.rs` does not match in the
|
||||||
|
// given text or file. Most likely this is an error on the programmer's side and the Regex
|
||||||
|
// is incorrect.
|
||||||
|
eprintln!("error: regex \n{:?}\ndoesn't match. You may have to update it.", start);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut new_lines = new_lines.join("\n");
|
||||||
|
if text.ends_with('\n') {
|
||||||
|
new_lines.push('\n');
|
||||||
|
}
|
||||||
|
let changed = new_lines != text;
|
||||||
|
FileChange { changed, new_lines }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_contents() {
|
||||||
|
let result: Vec<Lint> = parse_contents(
|
||||||
|
r#"
|
||||||
|
declare_clippy_lint! {
|
||||||
|
pub PTR_ARG,
|
||||||
|
style,
|
||||||
|
"really long \
|
||||||
|
text"
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_clippy_lint!{
|
||||||
|
pub DOC_MARKDOWN,
|
||||||
|
pedantic,
|
||||||
|
"single line"
|
||||||
|
}
|
||||||
|
|
||||||
|
/// some doc comment
|
||||||
|
declare_deprecated_lint! {
|
||||||
|
pub SHOULD_ASSERT_EQ,
|
||||||
|
"`assert!()` will be more flexible with RFC 2011"
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
"module_name",
|
||||||
|
)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let expected = vec![
|
||||||
|
Lint::new("ptr_arg", "style", "really long text", None, "module_name"),
|
||||||
|
Lint::new("doc_markdown", "pedantic", "single line", None, "module_name"),
|
||||||
|
Lint::new(
|
||||||
|
"should_assert_eq",
|
||||||
|
"Deprecated",
|
||||||
|
"`assert!()` will be more flexible with RFC 2011",
|
||||||
|
Some("`assert!()` will be more flexible with RFC 2011"),
|
||||||
|
"module_name",
|
||||||
|
),
|
||||||
|
];
|
||||||
|
assert_eq!(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_replace_region() {
|
||||||
|
let text = "\nabc\n123\n789\ndef\nghi";
|
||||||
|
let expected = FileChange {
|
||||||
|
changed: true,
|
||||||
|
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()]
|
||||||
|
});
|
||||||
|
assert_eq!(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_replace_region_with_start() {
|
||||||
|
let text = "\nabc\n123\n789\ndef\nghi";
|
||||||
|
let expected = FileChange {
|
||||||
|
changed: true,
|
||||||
|
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()]
|
||||||
|
});
|
||||||
|
assert_eq!(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_replace_region_no_changes() {
|
||||||
|
let text = "123\n456\n789";
|
||||||
|
let expected = FileChange {
|
||||||
|
changed: false,
|
||||||
|
new_lines: "123\n456\n789".to_string(),
|
||||||
|
};
|
||||||
|
let result = replace_region_in_text(text, r#"^\s*123$"#, r#"^\s*456"#, false, Vec::new);
|
||||||
|
assert_eq!(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_usable_lints() {
|
||||||
|
let lints = vec![
|
||||||
|
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",
|
||||||
|
)];
|
||||||
|
assert_eq!(expected, Lint::usable_lints(&lints));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_by_lint_group() {
|
||||||
|
let lints = vec![
|
||||||
|
Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
|
||||||
|
Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"),
|
||||||
|
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")],
|
||||||
|
);
|
||||||
|
assert_eq!(expected, Lint::by_lint_group(lints.into_iter()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_gen_changelog_lint_list() {
|
||||||
|
let lints = vec![
|
||||||
|
Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
|
||||||
|
Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"),
|
||||||
|
];
|
||||||
|
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()),
|
||||||
|
];
|
||||||
|
assert_eq!(expected, gen_changelog_lint_list(lints.iter()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_gen_deprecated() {
|
||||||
|
let lints = vec![
|
||||||
|
Lint::new(
|
||||||
|
"should_assert_eq",
|
||||||
|
"group1",
|
||||||
|
"abc",
|
||||||
|
Some("has been superseded by should_assert_eq2"),
|
||||||
|
"module_name",
|
||||||
|
),
|
||||||
|
Lint::new(
|
||||||
|
"another_deprecated",
|
||||||
|
"group2",
|
||||||
|
"abc",
|
||||||
|
Some("will be removed"),
|
||||||
|
"module_name",
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
let expected = GENERATED_FILE_COMMENT.to_string()
|
||||||
|
+ &[
|
||||||
|
"{",
|
||||||
|
" store.register_removed(",
|
||||||
|
" \"clippy::should_assert_eq\",",
|
||||||
|
" \"has been superseded by should_assert_eq2\",",
|
||||||
|
" );",
|
||||||
|
" store.register_removed(",
|
||||||
|
" \"clippy::another_deprecated\",",
|
||||||
|
" \"will be removed\",",
|
||||||
|
" );",
|
||||||
|
"}",
|
||||||
|
]
|
||||||
|
.join("\n")
|
||||||
|
+ "\n";
|
||||||
|
|
||||||
|
assert_eq!(expected, gen_deprecated(lints.iter()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_gen_deprecated_fail() {
|
||||||
|
let lints = vec![Lint::new("should_assert_eq2", "group2", "abc", None, "module_name")];
|
||||||
|
let _deprecated_lints = gen_deprecated(lints.iter());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_gen_modules_list() {
|
||||||
|
let lints = vec![
|
||||||
|
Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
|
||||||
|
Lint::new("incorrect_stuff", "group3", "abc", None, "another_module"),
|
||||||
|
];
|
||||||
|
let expected = vec!["mod another_module;".to_string(), "mod module_name;".to_string()];
|
||||||
|
assert_eq!(expected, gen_modules_list(lints.iter()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_gen_lint_group_list() {
|
||||||
|
let lints = vec![
|
||||||
|
Lint::new("abc", "group1", "abc", None, "module_name"),
|
||||||
|
Lint::new("should_assert_eq", "group1", "abc", None, "module_name"),
|
||||||
|
Lint::new("internal", "internal_style", "abc", None, "module_name"),
|
||||||
|
];
|
||||||
|
let expected = GENERATED_FILE_COMMENT.to_string()
|
||||||
|
+ &[
|
||||||
|
"store.register_group(true, \"clippy::group1\", Some(\"clippy_group1\"), vec![",
|
||||||
|
" LintId::of(module_name::ABC),",
|
||||||
|
" LintId::of(module_name::INTERNAL),",
|
||||||
|
" LintId::of(module_name::SHOULD_ASSERT_EQ),",
|
||||||
|
"])",
|
||||||
|
]
|
||||||
|
.join("\n")
|
||||||
|
+ "\n";
|
||||||
|
|
||||||
|
let result = gen_lint_group_list("group1", lints.iter());
|
||||||
|
|
||||||
|
assert_eq!(expected, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -563,7 +563,7 @@ fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||||
skip_item.path.segments.last().expect("empty path in attribute").ident.name == sym::skip;
|
skip_item.path.segments.last().expect("empty path in attribute").ident.name == sym::skip;
|
||||||
// Only lint outer attributes, because custom inner attributes are unstable
|
// Only lint outer attributes, because custom inner attributes are unstable
|
||||||
// Tracking issue: https://github.com/rust-lang/rust/issues/54726
|
// Tracking issue: https://github.com/rust-lang/rust/issues/54726
|
||||||
if let AttrStyle::Outer = attr.style;
|
if attr.style == AttrStyle::Outer;
|
||||||
then {
|
then {
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
|
|
|
@ -16,7 +16,7 @@ declare_clippy_lint! {
|
||||||
/// The Mutex types found in std::sync and parking_lot
|
/// The Mutex types found in std::sync and parking_lot
|
||||||
/// are not designed to operate in an async context across await points.
|
/// are not designed to operate in an async context across await points.
|
||||||
///
|
///
|
||||||
/// There are two potential solutions. One is to use an asynx-aware Mutex
|
/// There are two potential solutions. One is to use an async-aware Mutex
|
||||||
/// type. Many asynchronous foundation crates provide such a Mutex type. The
|
/// type. Many asynchronous foundation crates provide such a Mutex type. The
|
||||||
/// other solution is to ensure the mutex is unlocked before calling await,
|
/// other solution is to ensure the mutex is unlocked before calling await,
|
||||||
/// either by introducing a scope or an explicit call to Drop::drop.
|
/// either by introducing a scope or an explicit call to Drop::drop.
|
||||||
|
|
|
@ -12,7 +12,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, ca
|
||||||
}
|
}
|
||||||
|
|
||||||
let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx);
|
let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx);
|
||||||
let to_nbits = if let ty::Float(FloatTy::F32) = cast_to.kind() {
|
let to_nbits = if cast_to.kind() == &ty::Float(FloatTy::F32) {
|
||||||
32
|
32
|
||||||
} else {
|
} else {
|
||||||
64
|
64
|
||||||
|
|
|
@ -83,6 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
|
||||||
if !attrs.iter().any(|attr| attr.doc_str().is_some());
|
if !attrs.iter().any(|attr| attr.doc_str().is_some());
|
||||||
if let child_attrs = cx.tcx.hir().attrs(impl_item_hir);
|
if let child_attrs = cx.tcx.hir().attrs(impl_item_hir);
|
||||||
if !child_attrs.iter().any(|attr| attr.doc_str().is_some());
|
if !child_attrs.iter().any(|attr| attr.doc_str().is_some());
|
||||||
|
if adt_def.is_struct();
|
||||||
then {
|
then {
|
||||||
if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind {
|
if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind {
|
||||||
if let Some(PathSegment { args: Some(a), .. }) = p.segments.last() {
|
if let Some(PathSegment { args: Some(a), .. }) = p.segments.last() {
|
||||||
|
|
|
@ -393,7 +393,7 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
|
||||||
|
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let Some(header) = kind.header();
|
if let Some(header) = kind.header();
|
||||||
if let Unsafety::Unsafe = header.unsafety;
|
if header.unsafety == Unsafety::Unsafe;
|
||||||
then {
|
then {
|
||||||
self.has_unsafe = true;
|
self.has_unsafe = true;
|
||||||
}
|
}
|
||||||
|
@ -408,7 +408,7 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let ExprKind::Block(block, _) = expr.kind {
|
if let ExprKind::Block(block, _) = expr.kind {
|
||||||
if let BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) = block.rules {
|
if block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) {
|
||||||
self.has_unsafe = true;
|
self.has_unsafe = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,7 +236,17 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
|
||||||
hir::ItemKind::Impl(ref impl_) => {
|
hir::ItemKind::Impl(ref impl_) => {
|
||||||
self.in_trait_impl = impl_.of_trait.is_some();
|
self.in_trait_impl = impl_.of_trait.is_some();
|
||||||
},
|
},
|
||||||
_ => {},
|
hir::ItemKind::Trait(_, unsafety, ..) => {
|
||||||
|
if !headers.safety && unsafety == hir::Unsafety::Unsafe {
|
||||||
|
span_lint(
|
||||||
|
cx,
|
||||||
|
MISSING_SAFETY_DOC,
|
||||||
|
item.span,
|
||||||
|
"docs for unsafe trait missing `# Safety` section",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,6 +406,15 @@ struct DocHeaders {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &'a [Attribute]) -> DocHeaders {
|
fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &'a [Attribute]) -> DocHeaders {
|
||||||
|
use pulldown_cmark::{BrokenLink, CowStr, Options};
|
||||||
|
/// We don't want the parser to choke on intra doc links. Since we don't
|
||||||
|
/// actually care about rendering them, just pretend that all broken links are
|
||||||
|
/// point to a fake address.
|
||||||
|
#[allow(clippy::unnecessary_wraps)] // we're following a type signature
|
||||||
|
fn fake_broken_link_callback<'a>(_: BrokenLink<'_>) -> Option<(CowStr<'a>, CowStr<'a>)> {
|
||||||
|
Some(("fake".into(), "fake".into()))
|
||||||
|
}
|
||||||
|
|
||||||
let mut doc = String::new();
|
let mut doc = String::new();
|
||||||
let mut spans = vec![];
|
let mut spans = vec![];
|
||||||
|
|
||||||
|
@ -430,7 +449,10 @@ fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let parser = pulldown_cmark::Parser::new(&doc).into_offset_iter();
|
let mut cb = fake_broken_link_callback;
|
||||||
|
|
||||||
|
let parser =
|
||||||
|
pulldown_cmark::Parser::new_with_broken_link_callback(&doc, Options::empty(), Some(&mut cb)).into_offset_iter();
|
||||||
// Iterate over all `Events` and combine consecutive events into one
|
// Iterate over all `Events` and combine consecutive events into one
|
||||||
let events = parser.coalesce(|previous, current| {
|
let events = parser.coalesce(|previous, current| {
|
||||||
use pulldown_cmark::Event::Text;
|
use pulldown_cmark::Event::Text;
|
||||||
|
|
100
clippy_lints/src/equatable_if_let.rs
Normal file
100
clippy_lints/src/equatable_if_let.rs
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
|
use clippy_utils::source::snippet_with_applicability;
|
||||||
|
use clippy_utils::ty::implements_trait;
|
||||||
|
use if_chain::if_chain;
|
||||||
|
use rustc_errors::Applicability;
|
||||||
|
use rustc_hir::{Expr, ExprKind, Pat, PatKind};
|
||||||
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
|
use rustc_middle::ty::Ty;
|
||||||
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
|
|
||||||
|
declare_clippy_lint! {
|
||||||
|
/// ### What it does
|
||||||
|
/// Checks for pattern matchings that can be expressed using equality.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
///
|
||||||
|
/// * It reads better and has less cognitive load because equality won't cause binding.
|
||||||
|
/// * It is a [Yoda condition](https://en.wikipedia.org/wiki/Yoda_conditions). Yoda conditions are widely
|
||||||
|
/// criticized for increasing the cognitive load of reading the code.
|
||||||
|
/// * Equality is a simple bool expression and can be merged with `&&` and `||` and
|
||||||
|
/// reuse if blocks
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// if let Some(2) = x {
|
||||||
|
/// do_thing();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
/// Should be written
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// if x == Some(2) {
|
||||||
|
/// do_thing();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub EQUATABLE_IF_LET,
|
||||||
|
nursery,
|
||||||
|
"using pattern matching instead of equality"
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_lint_pass!(PatternEquality => [EQUATABLE_IF_LET]);
|
||||||
|
|
||||||
|
/// detects if pattern matches just one thing
|
||||||
|
fn unary_pattern(pat: &Pat<'_>) -> bool {
|
||||||
|
fn array_rec(pats: &[Pat<'_>]) -> bool {
|
||||||
|
pats.iter().all(unary_pattern)
|
||||||
|
}
|
||||||
|
match &pat.kind {
|
||||||
|
PatKind::Slice(_, _, _) | PatKind::Range(_, _, _) | PatKind::Binding(..) | PatKind::Wild | PatKind::Or(_) => {
|
||||||
|
false
|
||||||
|
},
|
||||||
|
PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)),
|
||||||
|
PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => !etc.is_some() && array_rec(a),
|
||||||
|
PatKind::Ref(x, _) | PatKind::Box(x) => unary_pattern(x),
|
||||||
|
PatKind::Path(_) | PatKind::Lit(_) => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_structural_partial_eq(cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: Ty<'tcx>) -> bool {
|
||||||
|
if let Some(def_id) = cx.tcx.lang_items().eq_trait() {
|
||||||
|
implements_trait(cx, ty, def_id, &[other.into()])
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> LateLintPass<'tcx> for PatternEquality {
|
||||||
|
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||||
|
if_chain! {
|
||||||
|
if let ExprKind::Let(pat, exp, _) = expr.kind;
|
||||||
|
if unary_pattern(pat);
|
||||||
|
let exp_ty = cx.typeck_results().expr_ty(exp);
|
||||||
|
let pat_ty = cx.typeck_results().pat_ty(pat);
|
||||||
|
if is_structural_partial_eq(cx, exp_ty, pat_ty);
|
||||||
|
then {
|
||||||
|
|
||||||
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
|
let pat_str = match pat.kind {
|
||||||
|
PatKind::Struct(..) => format!(
|
||||||
|
"({})",
|
||||||
|
snippet_with_applicability(cx, pat.span, "..", &mut applicability),
|
||||||
|
),
|
||||||
|
_ => snippet_with_applicability(cx, pat.span, "..", &mut applicability).to_string(),
|
||||||
|
};
|
||||||
|
span_lint_and_sugg(
|
||||||
|
cx,
|
||||||
|
EQUATABLE_IF_LET,
|
||||||
|
expr.span,
|
||||||
|
"this pattern matching can be expressed using equality",
|
||||||
|
"try",
|
||||||
|
format!(
|
||||||
|
"{} == {}",
|
||||||
|
snippet_with_applicability(cx, exp.span, "..", &mut applicability),
|
||||||
|
pat_str,
|
||||||
|
),
|
||||||
|
applicability,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for ErasingOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(cx: &LateContext<'_>, e: &Expr<'_>, span: Span) {
|
fn check(cx: &LateContext<'_>, e: &Expr<'_>, span: Span) {
|
||||||
if let Some(Constant::Int(0)) = constant_simple(cx, cx.typeck_results(), e) {
|
if constant_simple(cx, cx.typeck_results(), e) == Some(Constant::Int(0)) {
|
||||||
span_lint(
|
span_lint(
|
||||||
cx,
|
cx,
|
||||||
ERASING_OP,
|
ERASING_OP,
|
||||||
|
|
|
@ -90,7 +90,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
|
||||||
for trait_item in items {
|
for trait_item in items {
|
||||||
if trait_item.id.hir_id() == hir_id {
|
if trait_item.id.hir_id() == hir_id {
|
||||||
// be sure we have `self` parameter in this function
|
// be sure we have `self` parameter in this function
|
||||||
if let AssocItemKind::Fn { has_self: true } = trait_item.kind {
|
if trait_item.kind == (AssocItemKind::Fn { has_self: true }) {
|
||||||
trait_self_ty = Some(
|
trait_self_ty = Some(
|
||||||
TraitRef::identity(cx.tcx, trait_item.id.def_id.to_def_id())
|
TraitRef::identity(cx.tcx, trait_item.id.def_id.to_def_id())
|
||||||
.self_ty()
|
.self_ty()
|
||||||
|
|
|
@ -116,7 +116,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
|
||||||
if let Some(mut snippet) = snippet_opt(cx, callee.span) {
|
if let Some(mut snippet) = snippet_opt(cx, callee.span) {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let ty::Closure(_, substs) = callee_ty.peel_refs().kind();
|
if let ty::Closure(_, substs) = callee_ty.peel_refs().kind();
|
||||||
if let ClosureKind::FnMut = substs.as_closure().kind();
|
if substs.as_closure().kind() == ClosureKind::FnMut;
|
||||||
if get_enclosing_loop_or_closure(cx.tcx, expr).is_some()
|
if get_enclosing_loop_or_closure(cx.tcx, expr).is_some()
|
||||||
|| UsedAfterExprVisitor::is_found(cx, callee);
|
|| UsedAfterExprVisitor::is_found(cx, callee);
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
|
||||||
match typ.kind() {
|
match typ.kind() {
|
||||||
ty::FnDef(..) | ty::FnPtr(_) => {
|
ty::FnDef(..) | ty::FnPtr(_) => {
|
||||||
let sig = typ.fn_sig(self.cx.tcx);
|
let sig = typ.fn_sig(self.cx.tcx);
|
||||||
if let ty::Never = self.cx.tcx.erase_late_bound_regions(sig).output().kind() {
|
if self.cx.tcx.erase_late_bound_regions(sig).output().kind() == &ty::Never {
|
||||||
self.report_diverging_sub_expr(e);
|
self.report_diverging_sub_expr(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -112,7 +112,7 @@ fn is_display_arg(expr: &Expr<'_>) -> bool {
|
||||||
if let ExprKind::Call(_, [_, fmt]) = expr.kind;
|
if let ExprKind::Call(_, [_, fmt]) = expr.kind;
|
||||||
if let ExprKind::Path(QPath::Resolved(_, path)) = fmt.kind;
|
if let ExprKind::Path(QPath::Resolved(_, path)) = fmt.kind;
|
||||||
if let [.., t, _] = path.segments;
|
if let [.., t, _] = path.segments;
|
||||||
if t.ident.name.as_str() == "Display";
|
if t.ident.name == sym::Display;
|
||||||
then { true } else { false }
|
then { true } else { false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use clippy_utils::source::snippet;
|
use clippy_utils::source::snippet;
|
||||||
use if_chain::if_chain;
|
|
||||||
use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind};
|
use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
|
@ -62,16 +61,9 @@ impl<'tcx> LateLintPass<'tcx> for IdentityOp {
|
||||||
|
|
||||||
fn is_allowed(cx: &LateContext<'_>, cmp: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> bool {
|
fn is_allowed(cx: &LateContext<'_>, cmp: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> bool {
|
||||||
// `1 << 0` is a common pattern in bit manipulation code
|
// `1 << 0` is a common pattern in bit manipulation code
|
||||||
if_chain! {
|
cmp.node == BinOpKind::Shl
|
||||||
if let BinOpKind::Shl = cmp.node;
|
&& constant_simple(cx, cx.typeck_results(), right) == Some(Constant::Int(0))
|
||||||
if let Some(Constant::Int(0)) = constant_simple(cx, cx.typeck_results(), right);
|
&& constant_simple(cx, cx.typeck_results(), left) == Some(Constant::Int(1))
|
||||||
if let Some(Constant::Int(1)) = constant_simple(cx, cx.typeck_results(), left);
|
|
||||||
then {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::cast_possible_wrap)]
|
#[allow(clippy::cast_possible_wrap)]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::higher::PanicExpn;
|
use clippy_utils::higher::PanicExpn;
|
||||||
use clippy_utils::is_expn_of;
|
|
||||||
use clippy_utils::source::snippet_with_applicability;
|
use clippy_utils::source::snippet_with_applicability;
|
||||||
|
use clippy_utils::{is_expn_of, sugg};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{Block, Expr, ExprKind, StmtKind, UnOp};
|
use rustc_hir::{Block, Expr, ExprKind, StmtKind, UnOp};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
|
@ -74,12 +74,14 @@ impl LateLintPass<'_> for IfThenPanic {
|
||||||
};
|
};
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
let sugg = snippet_with_applicability(cx, span, "..", &mut applicability);
|
let sugg = snippet_with_applicability(cx, span, "..", &mut applicability);
|
||||||
|
let cond_sugg = if let ExprKind::DropTemps(e, ..) = cond.kind {
|
||||||
let cond_sugg =
|
if let Expr{kind: ExprKind::Unary(UnOp::Not, not_expr), ..} = e {
|
||||||
if let ExprKind::DropTemps(Expr{kind: ExprKind::Unary(UnOp::Not, not_expr), ..}) = cond.kind {
|
sugg::Sugg::hir_with_applicability(cx, not_expr, "..", &mut applicability).maybe_par().to_string()
|
||||||
snippet_with_applicability(cx, not_expr.span, "..", &mut applicability).to_string()
|
} else {
|
||||||
|
format!("!{}", sugg::Sugg::hir_with_applicability(cx, e, "..", &mut applicability).maybe_par().to_string())
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
format!("!{}", snippet_with_applicability(cx, cond.span, "..", &mut applicability))
|
format!("!{}", sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par().to_string())
|
||||||
};
|
};
|
||||||
|
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
|
|
|
@ -167,12 +167,20 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let generics_suggestion_span = generics.span.substitute_dummy({
|
let generics_suggestion_span = generics.span.substitute_dummy({
|
||||||
let pos = snippet_opt(cx, item.span.until(body.params[0].pat.span))
|
let pos = snippet_opt(
|
||||||
.and_then(|snip| {
|
cx,
|
||||||
let i = snip.find("fn")?;
|
Span::new(
|
||||||
Some(item.span.lo() + BytePos((i + (&snip[i..]).find('(')?) as u32))
|
item.span.lo(),
|
||||||
})
|
body.params[0].pat.span.lo(),
|
||||||
.expect("failed to create span for type parameters");
|
item.span.ctxt(),
|
||||||
|
item.span.parent(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.and_then(|snip| {
|
||||||
|
let i = snip.find("fn")?;
|
||||||
|
Some(item.span.lo() + BytePos((i + (&snip[i..]).find('(')?) as u32))
|
||||||
|
})
|
||||||
|
.expect("failed to create span for type parameters");
|
||||||
Span::new(pos, pos, item.span.ctxt(), item.span.parent())
|
Span::new(pos, pos, item.span.ctxt(), item.span.parent())
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for IntegerDivision {
|
||||||
fn is_integer_division<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) -> bool {
|
fn is_integer_division<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) -> bool {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let hir::ExprKind::Binary(binop, left, right) = &expr.kind;
|
if let hir::ExprKind::Binary(binop, left, right) = &expr.kind;
|
||||||
if let hir::BinOpKind::Div = &binop.node;
|
if binop.node == hir::BinOpKind::Div;
|
||||||
then {
|
then {
|
||||||
let (left_ty, right_ty) = (cx.typeck_results().expr_ty(left), cx.typeck_results().expr_ty(right));
|
let (left_ty, right_ty) = (cx.typeck_results().expr_ty(left), cx.typeck_results().expr_ty(right));
|
||||||
return left_ty.is_integral() && right_ty.is_integral();
|
return left_ty.is_integral() && right_ty.is_integral();
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
//! lint when there is a large size difference between variants on an enum
|
//! lint when there is a large size difference between variants on an enum
|
||||||
|
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::snippet_with_applicability;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{Item, ItemKind, VariantData};
|
use rustc_hir::{Item, ItemKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_middle::lint::in_external_macro;
|
||||||
use rustc_middle::ty::layout::LayoutOf;
|
use rustc_middle::ty::layout::LayoutOf;
|
||||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||||
|
use rustc_span::source_map::Span;
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
|
@ -58,6 +59,17 @@ impl LargeEnumVariant {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct FieldInfo {
|
||||||
|
ind: usize,
|
||||||
|
size: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VariantInfo {
|
||||||
|
ind: usize,
|
||||||
|
size: u64,
|
||||||
|
fields_size: Vec<FieldInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
impl_lint_pass!(LargeEnumVariant => [LARGE_ENUM_VARIANT]);
|
impl_lint_pass!(LargeEnumVariant => [LARGE_ENUM_VARIANT]);
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
|
impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
|
||||||
|
@ -68,72 +80,95 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
|
||||||
if let ItemKind::Enum(ref def, _) = item.kind {
|
if let ItemKind::Enum(ref def, _) = item.kind {
|
||||||
let ty = cx.tcx.type_of(item.def_id);
|
let ty = cx.tcx.type_of(item.def_id);
|
||||||
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.len() <= 1 {
|
||||||
let mut largest_variant: Option<(_, _)> = None;
|
return;
|
||||||
let mut second_variant: Option<(_, _)> = None;
|
|
||||||
|
|
||||||
for (i, variant) in adt.variants.iter().enumerate() {
|
|
||||||
let size: u64 = variant
|
|
||||||
.fields
|
|
||||||
.iter()
|
|
||||||
.filter_map(|f| {
|
|
||||||
let ty = cx.tcx.type_of(f.did);
|
|
||||||
// don't count generics by filtering out everything
|
|
||||||
// that does not have a layout
|
|
||||||
cx.layout_of(ty).ok().map(|l| l.size.bytes())
|
|
||||||
})
|
|
||||||
.sum();
|
|
||||||
|
|
||||||
let grouped = (size, (i, variant));
|
|
||||||
|
|
||||||
if grouped.0 >= largest_variant.map_or(0, |x| x.0) {
|
|
||||||
second_variant = largest_variant;
|
|
||||||
largest_variant = Some(grouped);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
let mut variants_size: Vec<VariantInfo> = adt
|
||||||
|
.variants
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, variant)| {
|
||||||
|
let mut fields_size = Vec::new();
|
||||||
|
let size: u64 = variant
|
||||||
|
.fields
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(|(i, f)| {
|
||||||
|
let ty = cx.tcx.type_of(f.did);
|
||||||
|
// don't count generics by filtering out everything
|
||||||
|
// that does not have a layout
|
||||||
|
cx.layout_of(ty).ok().map(|l| {
|
||||||
|
let size = l.size.bytes();
|
||||||
|
fields_size.push(FieldInfo { ind: i, size });
|
||||||
|
size
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.sum();
|
||||||
|
VariantInfo {
|
||||||
|
ind: i,
|
||||||
|
size,
|
||||||
|
fields_size,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
if let (Some(largest), Some(second)) = (largest_variant, second_variant) {
|
variants_size.sort_by(|a, b| (b.size.cmp(&a.size)));
|
||||||
let difference = largest.0 - second.0;
|
|
||||||
|
|
||||||
if difference > self.maximum_size_difference_allowed {
|
let mut difference = variants_size[0].size - variants_size[1].size;
|
||||||
let (i, variant) = largest.1;
|
if difference > self.maximum_size_difference_allowed {
|
||||||
|
let help_text = "consider boxing the large fields to reduce the total size of the enum";
|
||||||
|
span_lint_and_then(
|
||||||
|
cx,
|
||||||
|
LARGE_ENUM_VARIANT,
|
||||||
|
def.variants[variants_size[0].ind].span,
|
||||||
|
"large size difference between variants",
|
||||||
|
|diag| {
|
||||||
|
diag.span_label(
|
||||||
|
def.variants[variants_size[0].ind].span,
|
||||||
|
&format!("this variant is {} bytes", variants_size[0].size),
|
||||||
|
);
|
||||||
|
diag.span_note(
|
||||||
|
def.variants[variants_size[1].ind].span,
|
||||||
|
&format!("and the second-largest variant is {} bytes:", variants_size[1].size),
|
||||||
|
);
|
||||||
|
|
||||||
let help_text = "consider boxing the large fields to reduce the total size of the enum";
|
let fields = def.variants[variants_size[0].ind].data.fields();
|
||||||
span_lint_and_then(
|
variants_size[0].fields_size.sort_by(|a, b| (a.size.cmp(&b.size)));
|
||||||
cx,
|
let mut applicability = Applicability::MaybeIncorrect;
|
||||||
LARGE_ENUM_VARIANT,
|
let sugg: Vec<(Span, String)> = variants_size[0]
|
||||||
def.variants[i].span,
|
.fields_size
|
||||||
"large size difference between variants",
|
.iter()
|
||||||
|diag| {
|
.rev()
|
||||||
diag.span_label(
|
.map_while(|val| {
|
||||||
def.variants[(largest.1).0].span,
|
if difference > self.maximum_size_difference_allowed {
|
||||||
&format!("this variant is {} bytes", largest.0),
|
difference = difference.saturating_sub(val.size);
|
||||||
);
|
Some((
|
||||||
diag.span_note(
|
fields[val.ind].ty.span,
|
||||||
def.variants[(second.1).0].span,
|
format!(
|
||||||
&format!("and the second-largest variant is {} bytes:", second.0),
|
"Box<{}>",
|
||||||
);
|
snippet_with_applicability(
|
||||||
if variant.fields.len() == 1 {
|
cx,
|
||||||
let span = match def.variants[i].data {
|
fields[val.ind].ty.span,
|
||||||
VariantData::Struct(fields, ..) | VariantData::Tuple(fields, ..) => {
|
"..",
|
||||||
fields[0].ty.span
|
&mut applicability
|
||||||
},
|
)
|
||||||
VariantData::Unit(..) => unreachable!(),
|
.into_owned()
|
||||||
};
|
),
|
||||||
if let Some(snip) = snippet_opt(cx, span) {
|
))
|
||||||
diag.span_suggestion(
|
} else {
|
||||||
span,
|
None
|
||||||
help_text,
|
|
||||||
format!("Box<{}>", snip),
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
diag.span_help(def.variants[i].span, help_text);
|
.collect();
|
||||||
},
|
|
||||||
);
|
if !sugg.is_empty() {
|
||||||
}
|
diag.multipart_suggestion(help_text, sugg, Applicability::MaybeIncorrect);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
diag.span_help(def.variants[variants_size[0].ind].span, help_text);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -455,14 +455,10 @@ fn is_empty_array(expr: &Expr<'_>) -> bool {
|
||||||
fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||||
/// Gets an `AssocItem` and return true if it matches `is_empty(self)`.
|
/// Gets an `AssocItem` and return true if it matches `is_empty(self)`.
|
||||||
fn is_is_empty(cx: &LateContext<'_>, item: &ty::AssocItem) -> bool {
|
fn is_is_empty(cx: &LateContext<'_>, item: &ty::AssocItem) -> bool {
|
||||||
if let ty::AssocKind::Fn = item.kind {
|
if item.kind == ty::AssocKind::Fn && item.ident.name.as_str() == "is_empty" {
|
||||||
if item.ident.name.as_str() == "is_empty" {
|
let sig = cx.tcx.fn_sig(item.def_id);
|
||||||
let sig = cx.tcx.fn_sig(item.def_id);
|
let ty = sig.skip_binder();
|
||||||
let ty = sig.skip_binder();
|
ty.inputs().len() == 1
|
||||||
ty.inputs().len() == 1
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
70
clippy_lints/src/lib.deprecated.rs
Normal file
70
clippy_lints/src/lib.deprecated.rs
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
// This file was generated by `cargo dev update_lints`.
|
||||||
|
// Use that command to update this file and do not edit by hand.
|
||||||
|
// Manual edits will be overwritten.
|
||||||
|
|
||||||
|
{
|
||||||
|
store.register_removed(
|
||||||
|
"clippy::should_assert_eq",
|
||||||
|
"`assert!()` will be more flexible with RFC 2011",
|
||||||
|
);
|
||||||
|
store.register_removed(
|
||||||
|
"clippy::extend_from_slice",
|
||||||
|
"`.extend_from_slice(_)` is a faster way to extend a Vec by a slice",
|
||||||
|
);
|
||||||
|
store.register_removed(
|
||||||
|
"clippy::range_step_by_zero",
|
||||||
|
"`iterator.step_by(0)` panics nowadays",
|
||||||
|
);
|
||||||
|
store.register_removed(
|
||||||
|
"clippy::unstable_as_slice",
|
||||||
|
"`Vec::as_slice` has been stabilized in 1.7",
|
||||||
|
);
|
||||||
|
store.register_removed(
|
||||||
|
"clippy::unstable_as_mut_slice",
|
||||||
|
"`Vec::as_mut_slice` has been stabilized in 1.7",
|
||||||
|
);
|
||||||
|
store.register_removed(
|
||||||
|
"clippy::misaligned_transmute",
|
||||||
|
"this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr",
|
||||||
|
);
|
||||||
|
store.register_removed(
|
||||||
|
"clippy::assign_ops",
|
||||||
|
"using compound assignment operators (e.g., `+=`) is harmless",
|
||||||
|
);
|
||||||
|
store.register_removed(
|
||||||
|
"clippy::if_let_redundant_pattern_matching",
|
||||||
|
"this lint has been changed to redundant_pattern_matching",
|
||||||
|
);
|
||||||
|
store.register_removed(
|
||||||
|
"clippy::unsafe_vector_initialization",
|
||||||
|
"the replacement suggested by this lint had substantially different behavior",
|
||||||
|
);
|
||||||
|
store.register_removed(
|
||||||
|
"clippy::unused_collect",
|
||||||
|
"`collect` has been marked as #[must_use] in rustc and that covers all cases of this lint",
|
||||||
|
);
|
||||||
|
store.register_removed(
|
||||||
|
"clippy::replace_consts",
|
||||||
|
"associated-constants `MIN`/`MAX` of integers are preferred to `{min,max}_value()` and module constants",
|
||||||
|
);
|
||||||
|
store.register_removed(
|
||||||
|
"clippy::regex_macro",
|
||||||
|
"the regex! macro has been removed from the regex crate in 2018",
|
||||||
|
);
|
||||||
|
store.register_removed(
|
||||||
|
"clippy::find_map",
|
||||||
|
"this lint has been replaced by `manual_find_map`, a more specific lint",
|
||||||
|
);
|
||||||
|
store.register_removed(
|
||||||
|
"clippy::filter_map",
|
||||||
|
"this lint has been replaced by `manual_filter_map`, a more specific lint",
|
||||||
|
);
|
||||||
|
store.register_removed(
|
||||||
|
"clippy::pub_enum_variant_names",
|
||||||
|
"set the `avoid-breaking-exported-api` config option to `false` to enable the `enum_variant_names` lint for public items",
|
||||||
|
);
|
||||||
|
store.register_removed(
|
||||||
|
"clippy::wrong_pub_self_convention",
|
||||||
|
"set the `avoid-breaking-exported-api` config option to `false` to enable the `wrong_self_convention` lint for public items",
|
||||||
|
);
|
||||||
|
}
|
304
clippy_lints/src/lib.register_all.rs
Normal file
304
clippy_lints/src/lib.register_all.rs
Normal file
|
@ -0,0 +1,304 @@
|
||||||
|
// This file was generated by `cargo dev update_lints`.
|
||||||
|
// Use that command to update this file and do not edit by hand.
|
||||||
|
// Manual edits will be overwritten.
|
||||||
|
|
||||||
|
store.register_group(true, "clippy::all", Some("clippy_all"), vec![
|
||||||
|
LintId::of(absurd_extreme_comparisons::ABSURD_EXTREME_COMPARISONS),
|
||||||
|
LintId::of(approx_const::APPROX_CONSTANT),
|
||||||
|
LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS),
|
||||||
|
LintId::of(assign_ops::ASSIGN_OP_PATTERN),
|
||||||
|
LintId::of(assign_ops::MISREFACTORED_ASSIGN_OP),
|
||||||
|
LintId::of(async_yields_async::ASYNC_YIELDS_ASYNC),
|
||||||
|
LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS),
|
||||||
|
LintId::of(attrs::DEPRECATED_CFG_ATTR),
|
||||||
|
LintId::of(attrs::DEPRECATED_SEMVER),
|
||||||
|
LintId::of(attrs::MISMATCHED_TARGET_OS),
|
||||||
|
LintId::of(attrs::USELESS_ATTRIBUTE),
|
||||||
|
LintId::of(bit_mask::BAD_BIT_MASK),
|
||||||
|
LintId::of(bit_mask::INEFFECTIVE_BIT_MASK),
|
||||||
|
LintId::of(blacklisted_name::BLACKLISTED_NAME),
|
||||||
|
LintId::of(blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS),
|
||||||
|
LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON),
|
||||||
|
LintId::of(booleans::LOGIC_BUG),
|
||||||
|
LintId::of(booleans::NONMINIMAL_BOOL),
|
||||||
|
LintId::of(casts::CAST_REF_TO_MUT),
|
||||||
|
LintId::of(casts::CHAR_LIT_AS_U8),
|
||||||
|
LintId::of(casts::FN_TO_NUMERIC_CAST),
|
||||||
|
LintId::of(casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION),
|
||||||
|
LintId::of(casts::UNNECESSARY_CAST),
|
||||||
|
LintId::of(collapsible_if::COLLAPSIBLE_ELSE_IF),
|
||||||
|
LintId::of(collapsible_if::COLLAPSIBLE_IF),
|
||||||
|
LintId::of(collapsible_match::COLLAPSIBLE_MATCH),
|
||||||
|
LintId::of(comparison_chain::COMPARISON_CHAIN),
|
||||||
|
LintId::of(copies::IFS_SAME_COND),
|
||||||
|
LintId::of(copies::IF_SAME_THEN_ELSE),
|
||||||
|
LintId::of(default::FIELD_REASSIGN_WITH_DEFAULT),
|
||||||
|
LintId::of(derivable_impls::DERIVABLE_IMPLS),
|
||||||
|
LintId::of(derive::DERIVE_HASH_XOR_EQ),
|
||||||
|
LintId::of(derive::DERIVE_ORD_XOR_PARTIAL_ORD),
|
||||||
|
LintId::of(doc::MISSING_SAFETY_DOC),
|
||||||
|
LintId::of(doc::NEEDLESS_DOCTEST_MAIN),
|
||||||
|
LintId::of(double_comparison::DOUBLE_COMPARISONS),
|
||||||
|
LintId::of(double_parens::DOUBLE_PARENS),
|
||||||
|
LintId::of(drop_forget_ref::DROP_COPY),
|
||||||
|
LintId::of(drop_forget_ref::DROP_REF),
|
||||||
|
LintId::of(drop_forget_ref::FORGET_COPY),
|
||||||
|
LintId::of(drop_forget_ref::FORGET_REF),
|
||||||
|
LintId::of(duration_subsec::DURATION_SUBSEC),
|
||||||
|
LintId::of(entry::MAP_ENTRY),
|
||||||
|
LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT),
|
||||||
|
LintId::of(enum_variants::ENUM_VARIANT_NAMES),
|
||||||
|
LintId::of(enum_variants::MODULE_INCEPTION),
|
||||||
|
LintId::of(eq_op::EQ_OP),
|
||||||
|
LintId::of(eq_op::OP_REF),
|
||||||
|
LintId::of(erasing_op::ERASING_OP),
|
||||||
|
LintId::of(escape::BOXED_LOCAL),
|
||||||
|
LintId::of(eta_reduction::REDUNDANT_CLOSURE),
|
||||||
|
LintId::of(eval_order_dependence::DIVERGING_SUB_EXPRESSION),
|
||||||
|
LintId::of(eval_order_dependence::EVAL_ORDER_DEPENDENCE),
|
||||||
|
LintId::of(explicit_write::EXPLICIT_WRITE),
|
||||||
|
LintId::of(float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS),
|
||||||
|
LintId::of(float_literal::EXCESSIVE_PRECISION),
|
||||||
|
LintId::of(format::USELESS_FORMAT),
|
||||||
|
LintId::of(formatting::POSSIBLE_MISSING_COMMA),
|
||||||
|
LintId::of(formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING),
|
||||||
|
LintId::of(formatting::SUSPICIOUS_ELSE_FORMATTING),
|
||||||
|
LintId::of(formatting::SUSPICIOUS_UNARY_OP_FORMATTING),
|
||||||
|
LintId::of(from_over_into::FROM_OVER_INTO),
|
||||||
|
LintId::of(from_str_radix_10::FROM_STR_RADIX_10),
|
||||||
|
LintId::of(functions::DOUBLE_MUST_USE),
|
||||||
|
LintId::of(functions::MUST_USE_UNIT),
|
||||||
|
LintId::of(functions::NOT_UNSAFE_PTR_ARG_DEREF),
|
||||||
|
LintId::of(functions::RESULT_UNIT_ERR),
|
||||||
|
LintId::of(functions::TOO_MANY_ARGUMENTS),
|
||||||
|
LintId::of(get_last_with_len::GET_LAST_WITH_LEN),
|
||||||
|
LintId::of(identity_op::IDENTITY_OP),
|
||||||
|
LintId::of(if_let_mutex::IF_LET_MUTEX),
|
||||||
|
LintId::of(if_then_panic::IF_THEN_PANIC),
|
||||||
|
LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING),
|
||||||
|
LintId::of(infinite_iter::INFINITE_ITER),
|
||||||
|
LintId::of(inherent_to_string::INHERENT_TO_STRING),
|
||||||
|
LintId::of(inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY),
|
||||||
|
LintId::of(inline_fn_without_body::INLINE_FN_WITHOUT_BODY),
|
||||||
|
LintId::of(int_plus_one::INT_PLUS_ONE),
|
||||||
|
LintId::of(large_const_arrays::LARGE_CONST_ARRAYS),
|
||||||
|
LintId::of(large_enum_variant::LARGE_ENUM_VARIANT),
|
||||||
|
LintId::of(len_zero::COMPARISON_TO_EMPTY),
|
||||||
|
LintId::of(len_zero::LEN_WITHOUT_IS_EMPTY),
|
||||||
|
LintId::of(len_zero::LEN_ZERO),
|
||||||
|
LintId::of(let_underscore::LET_UNDERSCORE_LOCK),
|
||||||
|
LintId::of(lifetimes::EXTRA_UNUSED_LIFETIMES),
|
||||||
|
LintId::of(lifetimes::NEEDLESS_LIFETIMES),
|
||||||
|
LintId::of(literal_representation::INCONSISTENT_DIGIT_GROUPING),
|
||||||
|
LintId::of(literal_representation::MISTYPED_LITERAL_SUFFIXES),
|
||||||
|
LintId::of(literal_representation::UNUSUAL_BYTE_GROUPINGS),
|
||||||
|
LintId::of(loops::EMPTY_LOOP),
|
||||||
|
LintId::of(loops::EXPLICIT_COUNTER_LOOP),
|
||||||
|
LintId::of(loops::FOR_KV_MAP),
|
||||||
|
LintId::of(loops::FOR_LOOPS_OVER_FALLIBLES),
|
||||||
|
LintId::of(loops::ITER_NEXT_LOOP),
|
||||||
|
LintId::of(loops::MANUAL_FLATTEN),
|
||||||
|
LintId::of(loops::MANUAL_MEMCPY),
|
||||||
|
LintId::of(loops::MUT_RANGE_BOUND),
|
||||||
|
LintId::of(loops::NEEDLESS_COLLECT),
|
||||||
|
LintId::of(loops::NEEDLESS_RANGE_LOOP),
|
||||||
|
LintId::of(loops::NEVER_LOOP),
|
||||||
|
LintId::of(loops::SAME_ITEM_PUSH),
|
||||||
|
LintId::of(loops::SINGLE_ELEMENT_LOOP),
|
||||||
|
LintId::of(loops::WHILE_IMMUTABLE_CONDITION),
|
||||||
|
LintId::of(loops::WHILE_LET_LOOP),
|
||||||
|
LintId::of(loops::WHILE_LET_ON_ITERATOR),
|
||||||
|
LintId::of(main_recursion::MAIN_RECURSION),
|
||||||
|
LintId::of(manual_async_fn::MANUAL_ASYNC_FN),
|
||||||
|
LintId::of(manual_map::MANUAL_MAP),
|
||||||
|
LintId::of(manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE),
|
||||||
|
LintId::of(manual_strip::MANUAL_STRIP),
|
||||||
|
LintId::of(manual_unwrap_or::MANUAL_UNWRAP_OR),
|
||||||
|
LintId::of(map_clone::MAP_CLONE),
|
||||||
|
LintId::of(map_unit_fn::OPTION_MAP_UNIT_FN),
|
||||||
|
LintId::of(map_unit_fn::RESULT_MAP_UNIT_FN),
|
||||||
|
LintId::of(match_result_ok::MATCH_RESULT_OK),
|
||||||
|
LintId::of(matches::INFALLIBLE_DESTRUCTURING_MATCH),
|
||||||
|
LintId::of(matches::MATCH_AS_REF),
|
||||||
|
LintId::of(matches::MATCH_LIKE_MATCHES_MACRO),
|
||||||
|
LintId::of(matches::MATCH_OVERLAPPING_ARM),
|
||||||
|
LintId::of(matches::MATCH_REF_PATS),
|
||||||
|
LintId::of(matches::MATCH_SINGLE_BINDING),
|
||||||
|
LintId::of(matches::REDUNDANT_PATTERN_MATCHING),
|
||||||
|
LintId::of(matches::SINGLE_MATCH),
|
||||||
|
LintId::of(matches::WILDCARD_IN_OR_PATTERNS),
|
||||||
|
LintId::of(mem_discriminant::MEM_DISCRIMINANT_NON_ENUM),
|
||||||
|
LintId::of(mem_replace::MEM_REPLACE_OPTION_WITH_NONE),
|
||||||
|
LintId::of(mem_replace::MEM_REPLACE_WITH_DEFAULT),
|
||||||
|
LintId::of(mem_replace::MEM_REPLACE_WITH_UNINIT),
|
||||||
|
LintId::of(methods::BIND_INSTEAD_OF_MAP),
|
||||||
|
LintId::of(methods::BYTES_NTH),
|
||||||
|
LintId::of(methods::CHARS_LAST_CMP),
|
||||||
|
LintId::of(methods::CHARS_NEXT_CMP),
|
||||||
|
LintId::of(methods::CLONE_DOUBLE_REF),
|
||||||
|
LintId::of(methods::CLONE_ON_COPY),
|
||||||
|
LintId::of(methods::EXPECT_FUN_CALL),
|
||||||
|
LintId::of(methods::EXTEND_WITH_DRAIN),
|
||||||
|
LintId::of(methods::FILTER_MAP_IDENTITY),
|
||||||
|
LintId::of(methods::FILTER_NEXT),
|
||||||
|
LintId::of(methods::FLAT_MAP_IDENTITY),
|
||||||
|
LintId::of(methods::INSPECT_FOR_EACH),
|
||||||
|
LintId::of(methods::INTO_ITER_ON_REF),
|
||||||
|
LintId::of(methods::ITERATOR_STEP_BY_ZERO),
|
||||||
|
LintId::of(methods::ITER_CLONED_COLLECT),
|
||||||
|
LintId::of(methods::ITER_COUNT),
|
||||||
|
LintId::of(methods::ITER_NEXT_SLICE),
|
||||||
|
LintId::of(methods::ITER_NTH),
|
||||||
|
LintId::of(methods::ITER_NTH_ZERO),
|
||||||
|
LintId::of(methods::ITER_SKIP_NEXT),
|
||||||
|
LintId::of(methods::MANUAL_FILTER_MAP),
|
||||||
|
LintId::of(methods::MANUAL_FIND_MAP),
|
||||||
|
LintId::of(methods::MANUAL_SATURATING_ARITHMETIC),
|
||||||
|
LintId::of(methods::MANUAL_SPLIT_ONCE),
|
||||||
|
LintId::of(methods::MANUAL_STR_REPEAT),
|
||||||
|
LintId::of(methods::MAP_COLLECT_RESULT_UNIT),
|
||||||
|
LintId::of(methods::MAP_IDENTITY),
|
||||||
|
LintId::of(methods::NEW_RET_NO_SELF),
|
||||||
|
LintId::of(methods::OK_EXPECT),
|
||||||
|
LintId::of(methods::OPTION_AS_REF_DEREF),
|
||||||
|
LintId::of(methods::OPTION_FILTER_MAP),
|
||||||
|
LintId::of(methods::OPTION_MAP_OR_NONE),
|
||||||
|
LintId::of(methods::OR_FUN_CALL),
|
||||||
|
LintId::of(methods::RESULT_MAP_OR_INTO_OPTION),
|
||||||
|
LintId::of(methods::SEARCH_IS_SOME),
|
||||||
|
LintId::of(methods::SHOULD_IMPLEMENT_TRAIT),
|
||||||
|
LintId::of(methods::SINGLE_CHAR_ADD_STR),
|
||||||
|
LintId::of(methods::SINGLE_CHAR_PATTERN),
|
||||||
|
LintId::of(methods::SKIP_WHILE_NEXT),
|
||||||
|
LintId::of(methods::STRING_EXTEND_CHARS),
|
||||||
|
LintId::of(methods::SUSPICIOUS_MAP),
|
||||||
|
LintId::of(methods::SUSPICIOUS_SPLITN),
|
||||||
|
LintId::of(methods::UNINIT_ASSUMED_INIT),
|
||||||
|
LintId::of(methods::UNNECESSARY_FILTER_MAP),
|
||||||
|
LintId::of(methods::UNNECESSARY_FOLD),
|
||||||
|
LintId::of(methods::UNNECESSARY_LAZY_EVALUATIONS),
|
||||||
|
LintId::of(methods::UNWRAP_OR_ELSE_DEFAULT),
|
||||||
|
LintId::of(methods::USELESS_ASREF),
|
||||||
|
LintId::of(methods::WRONG_SELF_CONVENTION),
|
||||||
|
LintId::of(methods::ZST_OFFSET),
|
||||||
|
LintId::of(minmax::MIN_MAX),
|
||||||
|
LintId::of(misc::CMP_NAN),
|
||||||
|
LintId::of(misc::CMP_OWNED),
|
||||||
|
LintId::of(misc::MODULO_ONE),
|
||||||
|
LintId::of(misc::SHORT_CIRCUIT_STATEMENT),
|
||||||
|
LintId::of(misc::TOPLEVEL_REF_ARG),
|
||||||
|
LintId::of(misc::ZERO_PTR),
|
||||||
|
LintId::of(misc_early::BUILTIN_TYPE_SHADOW),
|
||||||
|
LintId::of(misc_early::DOUBLE_NEG),
|
||||||
|
LintId::of(misc_early::DUPLICATE_UNDERSCORE_ARGUMENT),
|
||||||
|
LintId::of(misc_early::MIXED_CASE_HEX_LITERALS),
|
||||||
|
LintId::of(misc_early::REDUNDANT_PATTERN),
|
||||||
|
LintId::of(misc_early::UNNEEDED_WILDCARD_PATTERN),
|
||||||
|
LintId::of(misc_early::ZERO_PREFIXED_LITERAL),
|
||||||
|
LintId::of(mut_key::MUTABLE_KEY_TYPE),
|
||||||
|
LintId::of(mut_mutex_lock::MUT_MUTEX_LOCK),
|
||||||
|
LintId::of(mut_reference::UNNECESSARY_MUT_PASSED),
|
||||||
|
LintId::of(mutex_atomic::MUTEX_ATOMIC),
|
||||||
|
LintId::of(needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE),
|
||||||
|
LintId::of(needless_bool::BOOL_COMPARISON),
|
||||||
|
LintId::of(needless_bool::NEEDLESS_BOOL),
|
||||||
|
LintId::of(needless_borrow::NEEDLESS_BORROW),
|
||||||
|
LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE),
|
||||||
|
LintId::of(needless_option_as_deref::NEEDLESS_OPTION_AS_DEREF),
|
||||||
|
LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK),
|
||||||
|
LintId::of(needless_update::NEEDLESS_UPDATE),
|
||||||
|
LintId::of(neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD),
|
||||||
|
LintId::of(neg_multiply::NEG_MULTIPLY),
|
||||||
|
LintId::of(new_without_default::NEW_WITHOUT_DEFAULT),
|
||||||
|
LintId::of(no_effect::NO_EFFECT),
|
||||||
|
LintId::of(no_effect::UNNECESSARY_OPERATION),
|
||||||
|
LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST),
|
||||||
|
LintId::of(non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST),
|
||||||
|
LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
|
||||||
|
LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS),
|
||||||
|
LintId::of(open_options::NONSENSICAL_OPEN_OPTIONS),
|
||||||
|
LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP),
|
||||||
|
LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
|
||||||
|
LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL),
|
||||||
|
LintId::of(precedence::PRECEDENCE),
|
||||||
|
LintId::of(ptr::CMP_NULL),
|
||||||
|
LintId::of(ptr::INVALID_NULL_PTR_USAGE),
|
||||||
|
LintId::of(ptr::MUT_FROM_REF),
|
||||||
|
LintId::of(ptr::PTR_ARG),
|
||||||
|
LintId::of(ptr_eq::PTR_EQ),
|
||||||
|
LintId::of(ptr_offset_with_cast::PTR_OFFSET_WITH_CAST),
|
||||||
|
LintId::of(question_mark::QUESTION_MARK),
|
||||||
|
LintId::of(ranges::MANUAL_RANGE_CONTAINS),
|
||||||
|
LintId::of(ranges::RANGE_ZIP_WITH_LEN),
|
||||||
|
LintId::of(ranges::REVERSED_EMPTY_RANGES),
|
||||||
|
LintId::of(redundant_clone::REDUNDANT_CLONE),
|
||||||
|
LintId::of(redundant_closure_call::REDUNDANT_CLOSURE_CALL),
|
||||||
|
LintId::of(redundant_field_names::REDUNDANT_FIELD_NAMES),
|
||||||
|
LintId::of(redundant_slicing::REDUNDANT_SLICING),
|
||||||
|
LintId::of(redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
|
||||||
|
LintId::of(reference::DEREF_ADDROF),
|
||||||
|
LintId::of(reference::REF_IN_DEREF),
|
||||||
|
LintId::of(regex::INVALID_REGEX),
|
||||||
|
LintId::of(repeat_once::REPEAT_ONCE),
|
||||||
|
LintId::of(returns::LET_AND_RETURN),
|
||||||
|
LintId::of(returns::NEEDLESS_RETURN),
|
||||||
|
LintId::of(self_assignment::SELF_ASSIGNMENT),
|
||||||
|
LintId::of(self_named_constructors::SELF_NAMED_CONSTRUCTORS),
|
||||||
|
LintId::of(serde_api::SERDE_API_MISUSE),
|
||||||
|
LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
|
||||||
|
LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
|
||||||
|
LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
|
||||||
|
LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE),
|
||||||
|
LintId::of(strings::STRING_FROM_UTF8_AS_BYTES),
|
||||||
|
LintId::of(strlen_on_c_strings::STRLEN_ON_C_STRINGS),
|
||||||
|
LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
|
||||||
|
LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
|
||||||
|
LintId::of(swap::ALMOST_SWAPPED),
|
||||||
|
LintId::of(swap::MANUAL_SWAP),
|
||||||
|
LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
|
||||||
|
LintId::of(temporary_assignment::TEMPORARY_ASSIGNMENT),
|
||||||
|
LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME),
|
||||||
|
LintId::of(to_string_in_display::TO_STRING_IN_DISPLAY),
|
||||||
|
LintId::of(transmute::CROSSPOINTER_TRANSMUTE),
|
||||||
|
LintId::of(transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS),
|
||||||
|
LintId::of(transmute::TRANSMUTE_BYTES_TO_STR),
|
||||||
|
LintId::of(transmute::TRANSMUTE_FLOAT_TO_INT),
|
||||||
|
LintId::of(transmute::TRANSMUTE_INT_TO_BOOL),
|
||||||
|
LintId::of(transmute::TRANSMUTE_INT_TO_CHAR),
|
||||||
|
LintId::of(transmute::TRANSMUTE_INT_TO_FLOAT),
|
||||||
|
LintId::of(transmute::TRANSMUTE_PTR_TO_REF),
|
||||||
|
LintId::of(transmute::UNSOUND_COLLECTION_TRANSMUTE),
|
||||||
|
LintId::of(transmute::WRONG_TRANSMUTE),
|
||||||
|
LintId::of(transmuting_null::TRANSMUTING_NULL),
|
||||||
|
LintId::of(try_err::TRY_ERR),
|
||||||
|
LintId::of(types::BORROWED_BOX),
|
||||||
|
LintId::of(types::BOX_COLLECTION),
|
||||||
|
LintId::of(types::REDUNDANT_ALLOCATION),
|
||||||
|
LintId::of(types::TYPE_COMPLEXITY),
|
||||||
|
LintId::of(types::VEC_BOX),
|
||||||
|
LintId::of(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS),
|
||||||
|
LintId::of(unicode::INVISIBLE_CHARACTERS),
|
||||||
|
LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
|
||||||
|
LintId::of(unit_types::UNIT_ARG),
|
||||||
|
LintId::of(unit_types::UNIT_CMP),
|
||||||
|
LintId::of(unnamed_address::FN_ADDRESS_COMPARISONS),
|
||||||
|
LintId::of(unnamed_address::VTABLE_ADDRESS_COMPARISONS),
|
||||||
|
LintId::of(unnecessary_sort_by::UNNECESSARY_SORT_BY),
|
||||||
|
LintId::of(unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME),
|
||||||
|
LintId::of(unused_io_amount::UNUSED_IO_AMOUNT),
|
||||||
|
LintId::of(unused_unit::UNUSED_UNIT),
|
||||||
|
LintId::of(unwrap::PANICKING_UNWRAP),
|
||||||
|
LintId::of(unwrap::UNNECESSARY_UNWRAP),
|
||||||
|
LintId::of(upper_case_acronyms::UPPER_CASE_ACRONYMS),
|
||||||
|
LintId::of(useless_conversion::USELESS_CONVERSION),
|
||||||
|
LintId::of(vec::USELESS_VEC),
|
||||||
|
LintId::of(vec_init_then_push::VEC_INIT_THEN_PUSH),
|
||||||
|
LintId::of(vec_resize_to_zero::VEC_RESIZE_TO_ZERO),
|
||||||
|
LintId::of(write::PRINTLN_EMPTY_STRING),
|
||||||
|
LintId::of(write::PRINT_LITERAL),
|
||||||
|
LintId::of(write::PRINT_WITH_NEWLINE),
|
||||||
|
LintId::of(write::WRITELN_EMPTY_STRING),
|
||||||
|
LintId::of(write::WRITE_LITERAL),
|
||||||
|
LintId::of(write::WRITE_WITH_NEWLINE),
|
||||||
|
LintId::of(zero_div_zero::ZERO_DIVIDED_BY_ZERO),
|
||||||
|
])
|
11
clippy_lints/src/lib.register_cargo.rs
Normal file
11
clippy_lints/src/lib.register_cargo.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// This file was generated by `cargo dev update_lints`.
|
||||||
|
// Use that command to update this file and do not edit by hand.
|
||||||
|
// Manual edits will be overwritten.
|
||||||
|
|
||||||
|
store.register_group(true, "clippy::cargo", Some("clippy_cargo"), vec![
|
||||||
|
LintId::of(cargo_common_metadata::CARGO_COMMON_METADATA),
|
||||||
|
LintId::of(feature_name::NEGATIVE_FEATURE_NAMES),
|
||||||
|
LintId::of(feature_name::REDUNDANT_FEATURE_NAMES),
|
||||||
|
LintId::of(multiple_crate_versions::MULTIPLE_CRATE_VERSIONS),
|
||||||
|
LintId::of(wildcard_dependencies::WILDCARD_DEPENDENCIES),
|
||||||
|
])
|
94
clippy_lints/src/lib.register_complexity.rs
Normal file
94
clippy_lints/src/lib.register_complexity.rs
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
// This file was generated by `cargo dev update_lints`.
|
||||||
|
// Use that command to update this file and do not edit by hand.
|
||||||
|
// Manual edits will be overwritten.
|
||||||
|
|
||||||
|
store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec![
|
||||||
|
LintId::of(attrs::DEPRECATED_CFG_ATTR),
|
||||||
|
LintId::of(booleans::NONMINIMAL_BOOL),
|
||||||
|
LintId::of(casts::CHAR_LIT_AS_U8),
|
||||||
|
LintId::of(casts::UNNECESSARY_CAST),
|
||||||
|
LintId::of(derivable_impls::DERIVABLE_IMPLS),
|
||||||
|
LintId::of(double_comparison::DOUBLE_COMPARISONS),
|
||||||
|
LintId::of(double_parens::DOUBLE_PARENS),
|
||||||
|
LintId::of(duration_subsec::DURATION_SUBSEC),
|
||||||
|
LintId::of(eval_order_dependence::DIVERGING_SUB_EXPRESSION),
|
||||||
|
LintId::of(explicit_write::EXPLICIT_WRITE),
|
||||||
|
LintId::of(format::USELESS_FORMAT),
|
||||||
|
LintId::of(functions::TOO_MANY_ARGUMENTS),
|
||||||
|
LintId::of(get_last_with_len::GET_LAST_WITH_LEN),
|
||||||
|
LintId::of(identity_op::IDENTITY_OP),
|
||||||
|
LintId::of(int_plus_one::INT_PLUS_ONE),
|
||||||
|
LintId::of(lifetimes::EXTRA_UNUSED_LIFETIMES),
|
||||||
|
LintId::of(lifetimes::NEEDLESS_LIFETIMES),
|
||||||
|
LintId::of(loops::EXPLICIT_COUNTER_LOOP),
|
||||||
|
LintId::of(loops::MANUAL_FLATTEN),
|
||||||
|
LintId::of(loops::SINGLE_ELEMENT_LOOP),
|
||||||
|
LintId::of(loops::WHILE_LET_LOOP),
|
||||||
|
LintId::of(manual_strip::MANUAL_STRIP),
|
||||||
|
LintId::of(manual_unwrap_or::MANUAL_UNWRAP_OR),
|
||||||
|
LintId::of(map_unit_fn::OPTION_MAP_UNIT_FN),
|
||||||
|
LintId::of(map_unit_fn::RESULT_MAP_UNIT_FN),
|
||||||
|
LintId::of(matches::MATCH_AS_REF),
|
||||||
|
LintId::of(matches::MATCH_SINGLE_BINDING),
|
||||||
|
LintId::of(matches::WILDCARD_IN_OR_PATTERNS),
|
||||||
|
LintId::of(methods::BIND_INSTEAD_OF_MAP),
|
||||||
|
LintId::of(methods::CLONE_ON_COPY),
|
||||||
|
LintId::of(methods::FILTER_MAP_IDENTITY),
|
||||||
|
LintId::of(methods::FILTER_NEXT),
|
||||||
|
LintId::of(methods::FLAT_MAP_IDENTITY),
|
||||||
|
LintId::of(methods::INSPECT_FOR_EACH),
|
||||||
|
LintId::of(methods::ITER_COUNT),
|
||||||
|
LintId::of(methods::MANUAL_FILTER_MAP),
|
||||||
|
LintId::of(methods::MANUAL_FIND_MAP),
|
||||||
|
LintId::of(methods::MANUAL_SPLIT_ONCE),
|
||||||
|
LintId::of(methods::MAP_IDENTITY),
|
||||||
|
LintId::of(methods::OPTION_AS_REF_DEREF),
|
||||||
|
LintId::of(methods::OPTION_FILTER_MAP),
|
||||||
|
LintId::of(methods::SEARCH_IS_SOME),
|
||||||
|
LintId::of(methods::SKIP_WHILE_NEXT),
|
||||||
|
LintId::of(methods::UNNECESSARY_FILTER_MAP),
|
||||||
|
LintId::of(methods::USELESS_ASREF),
|
||||||
|
LintId::of(misc::SHORT_CIRCUIT_STATEMENT),
|
||||||
|
LintId::of(misc_early::UNNEEDED_WILDCARD_PATTERN),
|
||||||
|
LintId::of(misc_early::ZERO_PREFIXED_LITERAL),
|
||||||
|
LintId::of(needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE),
|
||||||
|
LintId::of(needless_bool::BOOL_COMPARISON),
|
||||||
|
LintId::of(needless_bool::NEEDLESS_BOOL),
|
||||||
|
LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE),
|
||||||
|
LintId::of(needless_option_as_deref::NEEDLESS_OPTION_AS_DEREF),
|
||||||
|
LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK),
|
||||||
|
LintId::of(needless_update::NEEDLESS_UPDATE),
|
||||||
|
LintId::of(neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD),
|
||||||
|
LintId::of(no_effect::NO_EFFECT),
|
||||||
|
LintId::of(no_effect::UNNECESSARY_OPERATION),
|
||||||
|
LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
|
||||||
|
LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL),
|
||||||
|
LintId::of(precedence::PRECEDENCE),
|
||||||
|
LintId::of(ptr_offset_with_cast::PTR_OFFSET_WITH_CAST),
|
||||||
|
LintId::of(ranges::RANGE_ZIP_WITH_LEN),
|
||||||
|
LintId::of(redundant_closure_call::REDUNDANT_CLOSURE_CALL),
|
||||||
|
LintId::of(redundant_slicing::REDUNDANT_SLICING),
|
||||||
|
LintId::of(reference::DEREF_ADDROF),
|
||||||
|
LintId::of(reference::REF_IN_DEREF),
|
||||||
|
LintId::of(repeat_once::REPEAT_ONCE),
|
||||||
|
LintId::of(strings::STRING_FROM_UTF8_AS_BYTES),
|
||||||
|
LintId::of(strlen_on_c_strings::STRLEN_ON_C_STRINGS),
|
||||||
|
LintId::of(swap::MANUAL_SWAP),
|
||||||
|
LintId::of(temporary_assignment::TEMPORARY_ASSIGNMENT),
|
||||||
|
LintId::of(transmute::CROSSPOINTER_TRANSMUTE),
|
||||||
|
LintId::of(transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS),
|
||||||
|
LintId::of(transmute::TRANSMUTE_BYTES_TO_STR),
|
||||||
|
LintId::of(transmute::TRANSMUTE_FLOAT_TO_INT),
|
||||||
|
LintId::of(transmute::TRANSMUTE_INT_TO_BOOL),
|
||||||
|
LintId::of(transmute::TRANSMUTE_INT_TO_CHAR),
|
||||||
|
LintId::of(transmute::TRANSMUTE_INT_TO_FLOAT),
|
||||||
|
LintId::of(transmute::TRANSMUTE_PTR_TO_REF),
|
||||||
|
LintId::of(types::BORROWED_BOX),
|
||||||
|
LintId::of(types::TYPE_COMPLEXITY),
|
||||||
|
LintId::of(types::VEC_BOX),
|
||||||
|
LintId::of(unit_types::UNIT_ARG),
|
||||||
|
LintId::of(unnecessary_sort_by::UNNECESSARY_SORT_BY),
|
||||||
|
LintId::of(unwrap::UNNECESSARY_UNWRAP),
|
||||||
|
LintId::of(useless_conversion::USELESS_CONVERSION),
|
||||||
|
LintId::of(zero_div_zero::ZERO_DIVIDED_BY_ZERO),
|
||||||
|
])
|
73
clippy_lints/src/lib.register_correctness.rs
Normal file
73
clippy_lints/src/lib.register_correctness.rs
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
// This file was generated by `cargo dev update_lints`.
|
||||||
|
// Use that command to update this file and do not edit by hand.
|
||||||
|
// Manual edits will be overwritten.
|
||||||
|
|
||||||
|
store.register_group(true, "clippy::correctness", Some("clippy_correctness"), vec![
|
||||||
|
LintId::of(absurd_extreme_comparisons::ABSURD_EXTREME_COMPARISONS),
|
||||||
|
LintId::of(approx_const::APPROX_CONSTANT),
|
||||||
|
LintId::of(async_yields_async::ASYNC_YIELDS_ASYNC),
|
||||||
|
LintId::of(attrs::DEPRECATED_SEMVER),
|
||||||
|
LintId::of(attrs::MISMATCHED_TARGET_OS),
|
||||||
|
LintId::of(attrs::USELESS_ATTRIBUTE),
|
||||||
|
LintId::of(bit_mask::BAD_BIT_MASK),
|
||||||
|
LintId::of(bit_mask::INEFFECTIVE_BIT_MASK),
|
||||||
|
LintId::of(booleans::LOGIC_BUG),
|
||||||
|
LintId::of(casts::CAST_REF_TO_MUT),
|
||||||
|
LintId::of(copies::IFS_SAME_COND),
|
||||||
|
LintId::of(copies::IF_SAME_THEN_ELSE),
|
||||||
|
LintId::of(derive::DERIVE_HASH_XOR_EQ),
|
||||||
|
LintId::of(derive::DERIVE_ORD_XOR_PARTIAL_ORD),
|
||||||
|
LintId::of(drop_forget_ref::DROP_COPY),
|
||||||
|
LintId::of(drop_forget_ref::DROP_REF),
|
||||||
|
LintId::of(drop_forget_ref::FORGET_COPY),
|
||||||
|
LintId::of(drop_forget_ref::FORGET_REF),
|
||||||
|
LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT),
|
||||||
|
LintId::of(eq_op::EQ_OP),
|
||||||
|
LintId::of(erasing_op::ERASING_OP),
|
||||||
|
LintId::of(formatting::POSSIBLE_MISSING_COMMA),
|
||||||
|
LintId::of(functions::NOT_UNSAFE_PTR_ARG_DEREF),
|
||||||
|
LintId::of(if_let_mutex::IF_LET_MUTEX),
|
||||||
|
LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING),
|
||||||
|
LintId::of(infinite_iter::INFINITE_ITER),
|
||||||
|
LintId::of(inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY),
|
||||||
|
LintId::of(inline_fn_without_body::INLINE_FN_WITHOUT_BODY),
|
||||||
|
LintId::of(let_underscore::LET_UNDERSCORE_LOCK),
|
||||||
|
LintId::of(literal_representation::MISTYPED_LITERAL_SUFFIXES),
|
||||||
|
LintId::of(loops::ITER_NEXT_LOOP),
|
||||||
|
LintId::of(loops::NEVER_LOOP),
|
||||||
|
LintId::of(loops::WHILE_IMMUTABLE_CONDITION),
|
||||||
|
LintId::of(mem_discriminant::MEM_DISCRIMINANT_NON_ENUM),
|
||||||
|
LintId::of(mem_replace::MEM_REPLACE_WITH_UNINIT),
|
||||||
|
LintId::of(methods::CLONE_DOUBLE_REF),
|
||||||
|
LintId::of(methods::ITERATOR_STEP_BY_ZERO),
|
||||||
|
LintId::of(methods::SUSPICIOUS_SPLITN),
|
||||||
|
LintId::of(methods::UNINIT_ASSUMED_INIT),
|
||||||
|
LintId::of(methods::ZST_OFFSET),
|
||||||
|
LintId::of(minmax::MIN_MAX),
|
||||||
|
LintId::of(misc::CMP_NAN),
|
||||||
|
LintId::of(misc::MODULO_ONE),
|
||||||
|
LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS),
|
||||||
|
LintId::of(open_options::NONSENSICAL_OPEN_OPTIONS),
|
||||||
|
LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP),
|
||||||
|
LintId::of(ptr::INVALID_NULL_PTR_USAGE),
|
||||||
|
LintId::of(ptr::MUT_FROM_REF),
|
||||||
|
LintId::of(ranges::REVERSED_EMPTY_RANGES),
|
||||||
|
LintId::of(regex::INVALID_REGEX),
|
||||||
|
LintId::of(self_assignment::SELF_ASSIGNMENT),
|
||||||
|
LintId::of(serde_api::SERDE_API_MISUSE),
|
||||||
|
LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
|
||||||
|
LintId::of(swap::ALMOST_SWAPPED),
|
||||||
|
LintId::of(to_string_in_display::TO_STRING_IN_DISPLAY),
|
||||||
|
LintId::of(transmute::UNSOUND_COLLECTION_TRANSMUTE),
|
||||||
|
LintId::of(transmute::WRONG_TRANSMUTE),
|
||||||
|
LintId::of(transmuting_null::TRANSMUTING_NULL),
|
||||||
|
LintId::of(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS),
|
||||||
|
LintId::of(unicode::INVISIBLE_CHARACTERS),
|
||||||
|
LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
|
||||||
|
LintId::of(unit_types::UNIT_CMP),
|
||||||
|
LintId::of(unnamed_address::FN_ADDRESS_COMPARISONS),
|
||||||
|
LintId::of(unnamed_address::VTABLE_ADDRESS_COMPARISONS),
|
||||||
|
LintId::of(unused_io_amount::UNUSED_IO_AMOUNT),
|
||||||
|
LintId::of(unwrap::PANICKING_UNWRAP),
|
||||||
|
LintId::of(vec_resize_to_zero::VEC_RESIZE_TO_ZERO),
|
||||||
|
])
|
18
clippy_lints/src/lib.register_internal.rs
Normal file
18
clippy_lints/src/lib.register_internal.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// This file was generated by `cargo dev update_lints`.
|
||||||
|
// Use that command to update this file and do not edit by hand.
|
||||||
|
// Manual edits will be overwritten.
|
||||||
|
|
||||||
|
store.register_group(true, "clippy::internal", Some("clippy_internal"), vec![
|
||||||
|
LintId::of(utils::internal_lints::CLIPPY_LINTS_INTERNAL),
|
||||||
|
LintId::of(utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS),
|
||||||
|
LintId::of(utils::internal_lints::COMPILER_LINT_FUNCTIONS),
|
||||||
|
LintId::of(utils::internal_lints::DEFAULT_LINT),
|
||||||
|
LintId::of(utils::internal_lints::IF_CHAIN_STYLE),
|
||||||
|
LintId::of(utils::internal_lints::INTERNING_DEFINED_SYMBOL),
|
||||||
|
LintId::of(utils::internal_lints::INVALID_PATHS),
|
||||||
|
LintId::of(utils::internal_lints::LINT_WITHOUT_LINT_PASS),
|
||||||
|
LintId::of(utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM),
|
||||||
|
LintId::of(utils::internal_lints::OUTER_EXPN_EXPN_DATA),
|
||||||
|
LintId::of(utils::internal_lints::PRODUCE_ICE),
|
||||||
|
LintId::of(utils::internal_lints::UNNECESSARY_SYMBOL_STR),
|
||||||
|
])
|
510
clippy_lints/src/lib.register_lints.rs
Normal file
510
clippy_lints/src/lib.register_lints.rs
Normal file
|
@ -0,0 +1,510 @@
|
||||||
|
// This file was generated by `cargo dev update_lints`.
|
||||||
|
// Use that command to update this file and do not edit by hand.
|
||||||
|
// Manual edits will be overwritten.
|
||||||
|
|
||||||
|
store.register_lints(&[
|
||||||
|
#[cfg(feature = "internal-lints")]
|
||||||
|
utils::internal_lints::CLIPPY_LINTS_INTERNAL,
|
||||||
|
#[cfg(feature = "internal-lints")]
|
||||||
|
utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS,
|
||||||
|
#[cfg(feature = "internal-lints")]
|
||||||
|
utils::internal_lints::COMPILER_LINT_FUNCTIONS,
|
||||||
|
#[cfg(feature = "internal-lints")]
|
||||||
|
utils::internal_lints::DEFAULT_LINT,
|
||||||
|
#[cfg(feature = "internal-lints")]
|
||||||
|
utils::internal_lints::IF_CHAIN_STYLE,
|
||||||
|
#[cfg(feature = "internal-lints")]
|
||||||
|
utils::internal_lints::INTERNING_DEFINED_SYMBOL,
|
||||||
|
#[cfg(feature = "internal-lints")]
|
||||||
|
utils::internal_lints::INVALID_PATHS,
|
||||||
|
#[cfg(feature = "internal-lints")]
|
||||||
|
utils::internal_lints::LINT_WITHOUT_LINT_PASS,
|
||||||
|
#[cfg(feature = "internal-lints")]
|
||||||
|
utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM,
|
||||||
|
#[cfg(feature = "internal-lints")]
|
||||||
|
utils::internal_lints::OUTER_EXPN_EXPN_DATA,
|
||||||
|
#[cfg(feature = "internal-lints")]
|
||||||
|
utils::internal_lints::PRODUCE_ICE,
|
||||||
|
#[cfg(feature = "internal-lints")]
|
||||||
|
utils::internal_lints::UNNECESSARY_SYMBOL_STR,
|
||||||
|
absurd_extreme_comparisons::ABSURD_EXTREME_COMPARISONS,
|
||||||
|
approx_const::APPROX_CONSTANT,
|
||||||
|
arithmetic::FLOAT_ARITHMETIC,
|
||||||
|
arithmetic::INTEGER_ARITHMETIC,
|
||||||
|
as_conversions::AS_CONVERSIONS,
|
||||||
|
asm_syntax::INLINE_ASM_X86_ATT_SYNTAX,
|
||||||
|
asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX,
|
||||||
|
assertions_on_constants::ASSERTIONS_ON_CONSTANTS,
|
||||||
|
assign_ops::ASSIGN_OP_PATTERN,
|
||||||
|
assign_ops::MISREFACTORED_ASSIGN_OP,
|
||||||
|
async_yields_async::ASYNC_YIELDS_ASYNC,
|
||||||
|
attrs::BLANKET_CLIPPY_RESTRICTION_LINTS,
|
||||||
|
attrs::DEPRECATED_CFG_ATTR,
|
||||||
|
attrs::DEPRECATED_SEMVER,
|
||||||
|
attrs::EMPTY_LINE_AFTER_OUTER_ATTR,
|
||||||
|
attrs::INLINE_ALWAYS,
|
||||||
|
attrs::MISMATCHED_TARGET_OS,
|
||||||
|
attrs::USELESS_ATTRIBUTE,
|
||||||
|
await_holding_invalid::AWAIT_HOLDING_LOCK,
|
||||||
|
await_holding_invalid::AWAIT_HOLDING_REFCELL_REF,
|
||||||
|
bit_mask::BAD_BIT_MASK,
|
||||||
|
bit_mask::INEFFECTIVE_BIT_MASK,
|
||||||
|
bit_mask::VERBOSE_BIT_MASK,
|
||||||
|
blacklisted_name::BLACKLISTED_NAME,
|
||||||
|
blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS,
|
||||||
|
bool_assert_comparison::BOOL_ASSERT_COMPARISON,
|
||||||
|
booleans::LOGIC_BUG,
|
||||||
|
booleans::NONMINIMAL_BOOL,
|
||||||
|
bytecount::NAIVE_BYTECOUNT,
|
||||||
|
cargo_common_metadata::CARGO_COMMON_METADATA,
|
||||||
|
case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS,
|
||||||
|
casts::CAST_LOSSLESS,
|
||||||
|
casts::CAST_POSSIBLE_TRUNCATION,
|
||||||
|
casts::CAST_POSSIBLE_WRAP,
|
||||||
|
casts::CAST_PRECISION_LOSS,
|
||||||
|
casts::CAST_PTR_ALIGNMENT,
|
||||||
|
casts::CAST_REF_TO_MUT,
|
||||||
|
casts::CAST_SIGN_LOSS,
|
||||||
|
casts::CHAR_LIT_AS_U8,
|
||||||
|
casts::FN_TO_NUMERIC_CAST,
|
||||||
|
casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
|
||||||
|
casts::PTR_AS_PTR,
|
||||||
|
casts::UNNECESSARY_CAST,
|
||||||
|
checked_conversions::CHECKED_CONVERSIONS,
|
||||||
|
cognitive_complexity::COGNITIVE_COMPLEXITY,
|
||||||
|
collapsible_if::COLLAPSIBLE_ELSE_IF,
|
||||||
|
collapsible_if::COLLAPSIBLE_IF,
|
||||||
|
collapsible_match::COLLAPSIBLE_MATCH,
|
||||||
|
comparison_chain::COMPARISON_CHAIN,
|
||||||
|
copies::BRANCHES_SHARING_CODE,
|
||||||
|
copies::IFS_SAME_COND,
|
||||||
|
copies::IF_SAME_THEN_ELSE,
|
||||||
|
copies::SAME_FUNCTIONS_IN_IF_CONDITION,
|
||||||
|
copy_iterator::COPY_ITERATOR,
|
||||||
|
create_dir::CREATE_DIR,
|
||||||
|
dbg_macro::DBG_MACRO,
|
||||||
|
default::DEFAULT_TRAIT_ACCESS,
|
||||||
|
default::FIELD_REASSIGN_WITH_DEFAULT,
|
||||||
|
default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK,
|
||||||
|
dereference::EXPLICIT_DEREF_METHODS,
|
||||||
|
derivable_impls::DERIVABLE_IMPLS,
|
||||||
|
derive::DERIVE_HASH_XOR_EQ,
|
||||||
|
derive::DERIVE_ORD_XOR_PARTIAL_ORD,
|
||||||
|
derive::EXPL_IMPL_CLONE_ON_COPY,
|
||||||
|
derive::UNSAFE_DERIVE_DESERIALIZE,
|
||||||
|
disallowed_method::DISALLOWED_METHOD,
|
||||||
|
disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS,
|
||||||
|
disallowed_type::DISALLOWED_TYPE,
|
||||||
|
doc::DOC_MARKDOWN,
|
||||||
|
doc::MISSING_ERRORS_DOC,
|
||||||
|
doc::MISSING_PANICS_DOC,
|
||||||
|
doc::MISSING_SAFETY_DOC,
|
||||||
|
doc::NEEDLESS_DOCTEST_MAIN,
|
||||||
|
double_comparison::DOUBLE_COMPARISONS,
|
||||||
|
double_parens::DOUBLE_PARENS,
|
||||||
|
drop_forget_ref::DROP_COPY,
|
||||||
|
drop_forget_ref::DROP_REF,
|
||||||
|
drop_forget_ref::FORGET_COPY,
|
||||||
|
drop_forget_ref::FORGET_REF,
|
||||||
|
duration_subsec::DURATION_SUBSEC,
|
||||||
|
else_if_without_else::ELSE_IF_WITHOUT_ELSE,
|
||||||
|
empty_enum::EMPTY_ENUM,
|
||||||
|
entry::MAP_ENTRY,
|
||||||
|
enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT,
|
||||||
|
enum_variants::ENUM_VARIANT_NAMES,
|
||||||
|
enum_variants::MODULE_INCEPTION,
|
||||||
|
enum_variants::MODULE_NAME_REPETITIONS,
|
||||||
|
eq_op::EQ_OP,
|
||||||
|
eq_op::OP_REF,
|
||||||
|
equatable_if_let::EQUATABLE_IF_LET,
|
||||||
|
erasing_op::ERASING_OP,
|
||||||
|
escape::BOXED_LOCAL,
|
||||||
|
eta_reduction::REDUNDANT_CLOSURE,
|
||||||
|
eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS,
|
||||||
|
eval_order_dependence::DIVERGING_SUB_EXPRESSION,
|
||||||
|
eval_order_dependence::EVAL_ORDER_DEPENDENCE,
|
||||||
|
excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS,
|
||||||
|
excessive_bools::STRUCT_EXCESSIVE_BOOLS,
|
||||||
|
exhaustive_items::EXHAUSTIVE_ENUMS,
|
||||||
|
exhaustive_items::EXHAUSTIVE_STRUCTS,
|
||||||
|
exit::EXIT,
|
||||||
|
explicit_write::EXPLICIT_WRITE,
|
||||||
|
fallible_impl_from::FALLIBLE_IMPL_FROM,
|
||||||
|
feature_name::NEGATIVE_FEATURE_NAMES,
|
||||||
|
feature_name::REDUNDANT_FEATURE_NAMES,
|
||||||
|
float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS,
|
||||||
|
float_literal::EXCESSIVE_PRECISION,
|
||||||
|
float_literal::LOSSY_FLOAT_LITERAL,
|
||||||
|
floating_point_arithmetic::IMPRECISE_FLOPS,
|
||||||
|
floating_point_arithmetic::SUBOPTIMAL_FLOPS,
|
||||||
|
format::USELESS_FORMAT,
|
||||||
|
formatting::POSSIBLE_MISSING_COMMA,
|
||||||
|
formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING,
|
||||||
|
formatting::SUSPICIOUS_ELSE_FORMATTING,
|
||||||
|
formatting::SUSPICIOUS_UNARY_OP_FORMATTING,
|
||||||
|
from_over_into::FROM_OVER_INTO,
|
||||||
|
from_str_radix_10::FROM_STR_RADIX_10,
|
||||||
|
functions::DOUBLE_MUST_USE,
|
||||||
|
functions::MUST_USE_CANDIDATE,
|
||||||
|
functions::MUST_USE_UNIT,
|
||||||
|
functions::NOT_UNSAFE_PTR_ARG_DEREF,
|
||||||
|
functions::RESULT_UNIT_ERR,
|
||||||
|
functions::TOO_MANY_ARGUMENTS,
|
||||||
|
functions::TOO_MANY_LINES,
|
||||||
|
future_not_send::FUTURE_NOT_SEND,
|
||||||
|
get_last_with_len::GET_LAST_WITH_LEN,
|
||||||
|
identity_op::IDENTITY_OP,
|
||||||
|
if_let_mutex::IF_LET_MUTEX,
|
||||||
|
if_not_else::IF_NOT_ELSE,
|
||||||
|
if_then_panic::IF_THEN_PANIC,
|
||||||
|
if_then_some_else_none::IF_THEN_SOME_ELSE_NONE,
|
||||||
|
implicit_hasher::IMPLICIT_HASHER,
|
||||||
|
implicit_return::IMPLICIT_RETURN,
|
||||||
|
implicit_saturating_sub::IMPLICIT_SATURATING_SUB,
|
||||||
|
inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR,
|
||||||
|
indexing_slicing::INDEXING_SLICING,
|
||||||
|
indexing_slicing::OUT_OF_BOUNDS_INDEXING,
|
||||||
|
infinite_iter::INFINITE_ITER,
|
||||||
|
infinite_iter::MAYBE_INFINITE_ITER,
|
||||||
|
inherent_impl::MULTIPLE_INHERENT_IMPL,
|
||||||
|
inherent_to_string::INHERENT_TO_STRING,
|
||||||
|
inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY,
|
||||||
|
inline_fn_without_body::INLINE_FN_WITHOUT_BODY,
|
||||||
|
int_plus_one::INT_PLUS_ONE,
|
||||||
|
integer_division::INTEGER_DIVISION,
|
||||||
|
invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS,
|
||||||
|
items_after_statements::ITEMS_AFTER_STATEMENTS,
|
||||||
|
iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR,
|
||||||
|
large_const_arrays::LARGE_CONST_ARRAYS,
|
||||||
|
large_enum_variant::LARGE_ENUM_VARIANT,
|
||||||
|
large_stack_arrays::LARGE_STACK_ARRAYS,
|
||||||
|
len_zero::COMPARISON_TO_EMPTY,
|
||||||
|
len_zero::LEN_WITHOUT_IS_EMPTY,
|
||||||
|
len_zero::LEN_ZERO,
|
||||||
|
let_if_seq::USELESS_LET_IF_SEQ,
|
||||||
|
let_underscore::LET_UNDERSCORE_DROP,
|
||||||
|
let_underscore::LET_UNDERSCORE_LOCK,
|
||||||
|
let_underscore::LET_UNDERSCORE_MUST_USE,
|
||||||
|
lifetimes::EXTRA_UNUSED_LIFETIMES,
|
||||||
|
lifetimes::NEEDLESS_LIFETIMES,
|
||||||
|
literal_representation::DECIMAL_LITERAL_REPRESENTATION,
|
||||||
|
literal_representation::INCONSISTENT_DIGIT_GROUPING,
|
||||||
|
literal_representation::LARGE_DIGIT_GROUPS,
|
||||||
|
literal_representation::MISTYPED_LITERAL_SUFFIXES,
|
||||||
|
literal_representation::UNREADABLE_LITERAL,
|
||||||
|
literal_representation::UNUSUAL_BYTE_GROUPINGS,
|
||||||
|
loops::EMPTY_LOOP,
|
||||||
|
loops::EXPLICIT_COUNTER_LOOP,
|
||||||
|
loops::EXPLICIT_INTO_ITER_LOOP,
|
||||||
|
loops::EXPLICIT_ITER_LOOP,
|
||||||
|
loops::FOR_KV_MAP,
|
||||||
|
loops::FOR_LOOPS_OVER_FALLIBLES,
|
||||||
|
loops::ITER_NEXT_LOOP,
|
||||||
|
loops::MANUAL_FLATTEN,
|
||||||
|
loops::MANUAL_MEMCPY,
|
||||||
|
loops::MUT_RANGE_BOUND,
|
||||||
|
loops::NEEDLESS_COLLECT,
|
||||||
|
loops::NEEDLESS_RANGE_LOOP,
|
||||||
|
loops::NEVER_LOOP,
|
||||||
|
loops::SAME_ITEM_PUSH,
|
||||||
|
loops::SINGLE_ELEMENT_LOOP,
|
||||||
|
loops::WHILE_IMMUTABLE_CONDITION,
|
||||||
|
loops::WHILE_LET_LOOP,
|
||||||
|
loops::WHILE_LET_ON_ITERATOR,
|
||||||
|
macro_use::MACRO_USE_IMPORTS,
|
||||||
|
main_recursion::MAIN_RECURSION,
|
||||||
|
manual_async_fn::MANUAL_ASYNC_FN,
|
||||||
|
manual_map::MANUAL_MAP,
|
||||||
|
manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE,
|
||||||
|
manual_ok_or::MANUAL_OK_OR,
|
||||||
|
manual_strip::MANUAL_STRIP,
|
||||||
|
manual_unwrap_or::MANUAL_UNWRAP_OR,
|
||||||
|
map_clone::MAP_CLONE,
|
||||||
|
map_err_ignore::MAP_ERR_IGNORE,
|
||||||
|
map_unit_fn::OPTION_MAP_UNIT_FN,
|
||||||
|
map_unit_fn::RESULT_MAP_UNIT_FN,
|
||||||
|
match_on_vec_items::MATCH_ON_VEC_ITEMS,
|
||||||
|
match_result_ok::MATCH_RESULT_OK,
|
||||||
|
matches::INFALLIBLE_DESTRUCTURING_MATCH,
|
||||||
|
matches::MATCH_AS_REF,
|
||||||
|
matches::MATCH_BOOL,
|
||||||
|
matches::MATCH_LIKE_MATCHES_MACRO,
|
||||||
|
matches::MATCH_OVERLAPPING_ARM,
|
||||||
|
matches::MATCH_REF_PATS,
|
||||||
|
matches::MATCH_SAME_ARMS,
|
||||||
|
matches::MATCH_SINGLE_BINDING,
|
||||||
|
matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
|
||||||
|
matches::MATCH_WILD_ERR_ARM,
|
||||||
|
matches::REDUNDANT_PATTERN_MATCHING,
|
||||||
|
matches::REST_PAT_IN_FULLY_BOUND_STRUCTS,
|
||||||
|
matches::SINGLE_MATCH,
|
||||||
|
matches::SINGLE_MATCH_ELSE,
|
||||||
|
matches::WILDCARD_ENUM_MATCH_ARM,
|
||||||
|
matches::WILDCARD_IN_OR_PATTERNS,
|
||||||
|
mem_discriminant::MEM_DISCRIMINANT_NON_ENUM,
|
||||||
|
mem_forget::MEM_FORGET,
|
||||||
|
mem_replace::MEM_REPLACE_OPTION_WITH_NONE,
|
||||||
|
mem_replace::MEM_REPLACE_WITH_DEFAULT,
|
||||||
|
mem_replace::MEM_REPLACE_WITH_UNINIT,
|
||||||
|
methods::BIND_INSTEAD_OF_MAP,
|
||||||
|
methods::BYTES_NTH,
|
||||||
|
methods::CHARS_LAST_CMP,
|
||||||
|
methods::CHARS_NEXT_CMP,
|
||||||
|
methods::CLONED_INSTEAD_OF_COPIED,
|
||||||
|
methods::CLONE_DOUBLE_REF,
|
||||||
|
methods::CLONE_ON_COPY,
|
||||||
|
methods::CLONE_ON_REF_PTR,
|
||||||
|
methods::EXPECT_FUN_CALL,
|
||||||
|
methods::EXPECT_USED,
|
||||||
|
methods::EXTEND_WITH_DRAIN,
|
||||||
|
methods::FILETYPE_IS_FILE,
|
||||||
|
methods::FILTER_MAP_IDENTITY,
|
||||||
|
methods::FILTER_MAP_NEXT,
|
||||||
|
methods::FILTER_NEXT,
|
||||||
|
methods::FLAT_MAP_IDENTITY,
|
||||||
|
methods::FLAT_MAP_OPTION,
|
||||||
|
methods::FROM_ITER_INSTEAD_OF_COLLECT,
|
||||||
|
methods::GET_UNWRAP,
|
||||||
|
methods::IMPLICIT_CLONE,
|
||||||
|
methods::INEFFICIENT_TO_STRING,
|
||||||
|
methods::INSPECT_FOR_EACH,
|
||||||
|
methods::INTO_ITER_ON_REF,
|
||||||
|
methods::ITERATOR_STEP_BY_ZERO,
|
||||||
|
methods::ITER_CLONED_COLLECT,
|
||||||
|
methods::ITER_COUNT,
|
||||||
|
methods::ITER_NEXT_SLICE,
|
||||||
|
methods::ITER_NTH,
|
||||||
|
methods::ITER_NTH_ZERO,
|
||||||
|
methods::ITER_SKIP_NEXT,
|
||||||
|
methods::MANUAL_FILTER_MAP,
|
||||||
|
methods::MANUAL_FIND_MAP,
|
||||||
|
methods::MANUAL_SATURATING_ARITHMETIC,
|
||||||
|
methods::MANUAL_SPLIT_ONCE,
|
||||||
|
methods::MANUAL_STR_REPEAT,
|
||||||
|
methods::MAP_COLLECT_RESULT_UNIT,
|
||||||
|
methods::MAP_FLATTEN,
|
||||||
|
methods::MAP_IDENTITY,
|
||||||
|
methods::MAP_UNWRAP_OR,
|
||||||
|
methods::NEW_RET_NO_SELF,
|
||||||
|
methods::OK_EXPECT,
|
||||||
|
methods::OPTION_AS_REF_DEREF,
|
||||||
|
methods::OPTION_FILTER_MAP,
|
||||||
|
methods::OPTION_MAP_OR_NONE,
|
||||||
|
methods::OR_FUN_CALL,
|
||||||
|
methods::RESULT_MAP_OR_INTO_OPTION,
|
||||||
|
methods::SEARCH_IS_SOME,
|
||||||
|
methods::SHOULD_IMPLEMENT_TRAIT,
|
||||||
|
methods::SINGLE_CHAR_ADD_STR,
|
||||||
|
methods::SINGLE_CHAR_PATTERN,
|
||||||
|
methods::SKIP_WHILE_NEXT,
|
||||||
|
methods::STRING_EXTEND_CHARS,
|
||||||
|
methods::SUSPICIOUS_MAP,
|
||||||
|
methods::SUSPICIOUS_SPLITN,
|
||||||
|
methods::UNINIT_ASSUMED_INIT,
|
||||||
|
methods::UNNECESSARY_FILTER_MAP,
|
||||||
|
methods::UNNECESSARY_FOLD,
|
||||||
|
methods::UNNECESSARY_LAZY_EVALUATIONS,
|
||||||
|
methods::UNWRAP_OR_ELSE_DEFAULT,
|
||||||
|
methods::UNWRAP_USED,
|
||||||
|
methods::USELESS_ASREF,
|
||||||
|
methods::WRONG_SELF_CONVENTION,
|
||||||
|
methods::ZST_OFFSET,
|
||||||
|
minmax::MIN_MAX,
|
||||||
|
misc::CMP_NAN,
|
||||||
|
misc::CMP_OWNED,
|
||||||
|
misc::FLOAT_CMP,
|
||||||
|
misc::FLOAT_CMP_CONST,
|
||||||
|
misc::MODULO_ONE,
|
||||||
|
misc::SHORT_CIRCUIT_STATEMENT,
|
||||||
|
misc::TOPLEVEL_REF_ARG,
|
||||||
|
misc::USED_UNDERSCORE_BINDING,
|
||||||
|
misc::ZERO_PTR,
|
||||||
|
misc_early::BUILTIN_TYPE_SHADOW,
|
||||||
|
misc_early::DOUBLE_NEG,
|
||||||
|
misc_early::DUPLICATE_UNDERSCORE_ARGUMENT,
|
||||||
|
misc_early::MIXED_CASE_HEX_LITERALS,
|
||||||
|
misc_early::REDUNDANT_PATTERN,
|
||||||
|
misc_early::UNNEEDED_FIELD_PATTERN,
|
||||||
|
misc_early::UNNEEDED_WILDCARD_PATTERN,
|
||||||
|
misc_early::UNSEPARATED_LITERAL_SUFFIX,
|
||||||
|
misc_early::ZERO_PREFIXED_LITERAL,
|
||||||
|
missing_const_for_fn::MISSING_CONST_FOR_FN,
|
||||||
|
missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS,
|
||||||
|
missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES,
|
||||||
|
missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS,
|
||||||
|
module_style::MOD_MODULE_FILES,
|
||||||
|
module_style::SELF_NAMED_MODULE_FILES,
|
||||||
|
modulo_arithmetic::MODULO_ARITHMETIC,
|
||||||
|
multiple_crate_versions::MULTIPLE_CRATE_VERSIONS,
|
||||||
|
mut_key::MUTABLE_KEY_TYPE,
|
||||||
|
mut_mut::MUT_MUT,
|
||||||
|
mut_mutex_lock::MUT_MUTEX_LOCK,
|
||||||
|
mut_reference::UNNECESSARY_MUT_PASSED,
|
||||||
|
mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL,
|
||||||
|
mutex_atomic::MUTEX_ATOMIC,
|
||||||
|
mutex_atomic::MUTEX_INTEGER,
|
||||||
|
needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE,
|
||||||
|
needless_bitwise_bool::NEEDLESS_BITWISE_BOOL,
|
||||||
|
needless_bool::BOOL_COMPARISON,
|
||||||
|
needless_bool::NEEDLESS_BOOL,
|
||||||
|
needless_borrow::NEEDLESS_BORROW,
|
||||||
|
needless_borrow::REF_BINDING_TO_REFERENCE,
|
||||||
|
needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE,
|
||||||
|
needless_continue::NEEDLESS_CONTINUE,
|
||||||
|
needless_for_each::NEEDLESS_FOR_EACH,
|
||||||
|
needless_option_as_deref::NEEDLESS_OPTION_AS_DEREF,
|
||||||
|
needless_pass_by_value::NEEDLESS_PASS_BY_VALUE,
|
||||||
|
needless_question_mark::NEEDLESS_QUESTION_MARK,
|
||||||
|
needless_update::NEEDLESS_UPDATE,
|
||||||
|
neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD,
|
||||||
|
neg_multiply::NEG_MULTIPLY,
|
||||||
|
new_without_default::NEW_WITHOUT_DEFAULT,
|
||||||
|
no_effect::NO_EFFECT,
|
||||||
|
no_effect::UNNECESSARY_OPERATION,
|
||||||
|
non_copy_const::BORROW_INTERIOR_MUTABLE_CONST,
|
||||||
|
non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST,
|
||||||
|
non_expressive_names::JUST_UNDERSCORES_AND_DIGITS,
|
||||||
|
non_expressive_names::MANY_SINGLE_CHAR_NAMES,
|
||||||
|
non_expressive_names::SIMILAR_NAMES,
|
||||||
|
non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS,
|
||||||
|
non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY,
|
||||||
|
nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES,
|
||||||
|
open_options::NONSENSICAL_OPEN_OPTIONS,
|
||||||
|
option_env_unwrap::OPTION_ENV_UNWRAP,
|
||||||
|
option_if_let_else::OPTION_IF_LET_ELSE,
|
||||||
|
overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL,
|
||||||
|
panic_in_result_fn::PANIC_IN_RESULT_FN,
|
||||||
|
panic_unimplemented::PANIC,
|
||||||
|
panic_unimplemented::TODO,
|
||||||
|
panic_unimplemented::UNIMPLEMENTED,
|
||||||
|
panic_unimplemented::UNREACHABLE,
|
||||||
|
partialeq_ne_impl::PARTIALEQ_NE_IMPL,
|
||||||
|
pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE,
|
||||||
|
pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF,
|
||||||
|
path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE,
|
||||||
|
pattern_type_mismatch::PATTERN_TYPE_MISMATCH,
|
||||||
|
precedence::PRECEDENCE,
|
||||||
|
ptr::CMP_NULL,
|
||||||
|
ptr::INVALID_NULL_PTR_USAGE,
|
||||||
|
ptr::MUT_FROM_REF,
|
||||||
|
ptr::PTR_ARG,
|
||||||
|
ptr_eq::PTR_EQ,
|
||||||
|
ptr_offset_with_cast::PTR_OFFSET_WITH_CAST,
|
||||||
|
question_mark::QUESTION_MARK,
|
||||||
|
ranges::MANUAL_RANGE_CONTAINS,
|
||||||
|
ranges::RANGE_MINUS_ONE,
|
||||||
|
ranges::RANGE_PLUS_ONE,
|
||||||
|
ranges::RANGE_ZIP_WITH_LEN,
|
||||||
|
ranges::REVERSED_EMPTY_RANGES,
|
||||||
|
redundant_clone::REDUNDANT_CLONE,
|
||||||
|
redundant_closure_call::REDUNDANT_CLOSURE_CALL,
|
||||||
|
redundant_else::REDUNDANT_ELSE,
|
||||||
|
redundant_field_names::REDUNDANT_FIELD_NAMES,
|
||||||
|
redundant_pub_crate::REDUNDANT_PUB_CRATE,
|
||||||
|
redundant_slicing::REDUNDANT_SLICING,
|
||||||
|
redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES,
|
||||||
|
ref_option_ref::REF_OPTION_REF,
|
||||||
|
reference::DEREF_ADDROF,
|
||||||
|
reference::REF_IN_DEREF,
|
||||||
|
regex::INVALID_REGEX,
|
||||||
|
regex::TRIVIAL_REGEX,
|
||||||
|
repeat_once::REPEAT_ONCE,
|
||||||
|
returns::LET_AND_RETURN,
|
||||||
|
returns::NEEDLESS_RETURN,
|
||||||
|
same_name_method::SAME_NAME_METHOD,
|
||||||
|
self_assignment::SELF_ASSIGNMENT,
|
||||||
|
self_named_constructors::SELF_NAMED_CONSTRUCTORS,
|
||||||
|
semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED,
|
||||||
|
serde_api::SERDE_API_MISUSE,
|
||||||
|
shadow::SHADOW_REUSE,
|
||||||
|
shadow::SHADOW_SAME,
|
||||||
|
shadow::SHADOW_UNRELATED,
|
||||||
|
single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS,
|
||||||
|
size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT,
|
||||||
|
slow_vector_initialization::SLOW_VECTOR_INITIALIZATION,
|
||||||
|
stable_sort_primitive::STABLE_SORT_PRIMITIVE,
|
||||||
|
strings::STRING_ADD,
|
||||||
|
strings::STRING_ADD_ASSIGN,
|
||||||
|
strings::STRING_FROM_UTF8_AS_BYTES,
|
||||||
|
strings::STRING_LIT_AS_BYTES,
|
||||||
|
strings::STRING_TO_STRING,
|
||||||
|
strings::STR_TO_STRING,
|
||||||
|
strlen_on_c_strings::STRLEN_ON_C_STRINGS,
|
||||||
|
suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS,
|
||||||
|
suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL,
|
||||||
|
suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL,
|
||||||
|
swap::ALMOST_SWAPPED,
|
||||||
|
swap::MANUAL_SWAP,
|
||||||
|
tabs_in_doc_comments::TABS_IN_DOC_COMMENTS,
|
||||||
|
temporary_assignment::TEMPORARY_ASSIGNMENT,
|
||||||
|
to_digit_is_some::TO_DIGIT_IS_SOME,
|
||||||
|
to_string_in_display::TO_STRING_IN_DISPLAY,
|
||||||
|
trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS,
|
||||||
|
trait_bounds::TYPE_REPETITION_IN_BOUNDS,
|
||||||
|
transmute::CROSSPOINTER_TRANSMUTE,
|
||||||
|
transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS,
|
||||||
|
transmute::TRANSMUTE_BYTES_TO_STR,
|
||||||
|
transmute::TRANSMUTE_FLOAT_TO_INT,
|
||||||
|
transmute::TRANSMUTE_INT_TO_BOOL,
|
||||||
|
transmute::TRANSMUTE_INT_TO_CHAR,
|
||||||
|
transmute::TRANSMUTE_INT_TO_FLOAT,
|
||||||
|
transmute::TRANSMUTE_PTR_TO_PTR,
|
||||||
|
transmute::TRANSMUTE_PTR_TO_REF,
|
||||||
|
transmute::UNSOUND_COLLECTION_TRANSMUTE,
|
||||||
|
transmute::USELESS_TRANSMUTE,
|
||||||
|
transmute::WRONG_TRANSMUTE,
|
||||||
|
transmuting_null::TRANSMUTING_NULL,
|
||||||
|
try_err::TRY_ERR,
|
||||||
|
types::BORROWED_BOX,
|
||||||
|
types::BOX_COLLECTION,
|
||||||
|
types::LINKEDLIST,
|
||||||
|
types::OPTION_OPTION,
|
||||||
|
types::RC_BUFFER,
|
||||||
|
types::RC_MUTEX,
|
||||||
|
types::REDUNDANT_ALLOCATION,
|
||||||
|
types::TYPE_COMPLEXITY,
|
||||||
|
types::VEC_BOX,
|
||||||
|
undropped_manually_drops::UNDROPPED_MANUALLY_DROPS,
|
||||||
|
unicode::INVISIBLE_CHARACTERS,
|
||||||
|
unicode::NON_ASCII_LITERAL,
|
||||||
|
unicode::UNICODE_NOT_NFC,
|
||||||
|
unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD,
|
||||||
|
unit_types::LET_UNIT_VALUE,
|
||||||
|
unit_types::UNIT_ARG,
|
||||||
|
unit_types::UNIT_CMP,
|
||||||
|
unnamed_address::FN_ADDRESS_COMPARISONS,
|
||||||
|
unnamed_address::VTABLE_ADDRESS_COMPARISONS,
|
||||||
|
unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS,
|
||||||
|
unnecessary_sort_by::UNNECESSARY_SORT_BY,
|
||||||
|
unnecessary_wraps::UNNECESSARY_WRAPS,
|
||||||
|
unnested_or_patterns::UNNESTED_OR_PATTERNS,
|
||||||
|
unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME,
|
||||||
|
unused_async::UNUSED_ASYNC,
|
||||||
|
unused_io_amount::UNUSED_IO_AMOUNT,
|
||||||
|
unused_self::UNUSED_SELF,
|
||||||
|
unused_unit::UNUSED_UNIT,
|
||||||
|
unwrap::PANICKING_UNWRAP,
|
||||||
|
unwrap::UNNECESSARY_UNWRAP,
|
||||||
|
unwrap_in_result::UNWRAP_IN_RESULT,
|
||||||
|
upper_case_acronyms::UPPER_CASE_ACRONYMS,
|
||||||
|
use_self::USE_SELF,
|
||||||
|
useless_conversion::USELESS_CONVERSION,
|
||||||
|
vec::USELESS_VEC,
|
||||||
|
vec_init_then_push::VEC_INIT_THEN_PUSH,
|
||||||
|
vec_resize_to_zero::VEC_RESIZE_TO_ZERO,
|
||||||
|
verbose_file_reads::VERBOSE_FILE_READS,
|
||||||
|
wildcard_dependencies::WILDCARD_DEPENDENCIES,
|
||||||
|
wildcard_imports::ENUM_GLOB_USE,
|
||||||
|
wildcard_imports::WILDCARD_IMPORTS,
|
||||||
|
write::PRINTLN_EMPTY_STRING,
|
||||||
|
write::PRINT_LITERAL,
|
||||||
|
write::PRINT_STDERR,
|
||||||
|
write::PRINT_STDOUT,
|
||||||
|
write::PRINT_WITH_NEWLINE,
|
||||||
|
write::USE_DEBUG,
|
||||||
|
write::WRITELN_EMPTY_STRING,
|
||||||
|
write::WRITE_LITERAL,
|
||||||
|
write::WRITE_WITH_NEWLINE,
|
||||||
|
zero_div_zero::ZERO_DIVIDED_BY_ZERO,
|
||||||
|
zero_sized_map_values::ZERO_SIZED_MAP_VALUES,
|
||||||
|
])
|
30
clippy_lints/src/lib.register_nursery.rs
Normal file
30
clippy_lints/src/lib.register_nursery.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// This file was generated by `cargo dev update_lints`.
|
||||||
|
// Use that command to update this file and do not edit by hand.
|
||||||
|
// Manual edits will be overwritten.
|
||||||
|
|
||||||
|
store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
|
||||||
|
LintId::of(attrs::EMPTY_LINE_AFTER_OUTER_ATTR),
|
||||||
|
LintId::of(cognitive_complexity::COGNITIVE_COMPLEXITY),
|
||||||
|
LintId::of(copies::BRANCHES_SHARING_CODE),
|
||||||
|
LintId::of(disallowed_method::DISALLOWED_METHOD),
|
||||||
|
LintId::of(disallowed_type::DISALLOWED_TYPE),
|
||||||
|
LintId::of(equatable_if_let::EQUATABLE_IF_LET),
|
||||||
|
LintId::of(fallible_impl_from::FALLIBLE_IMPL_FROM),
|
||||||
|
LintId::of(floating_point_arithmetic::IMPRECISE_FLOPS),
|
||||||
|
LintId::of(floating_point_arithmetic::SUBOPTIMAL_FLOPS),
|
||||||
|
LintId::of(future_not_send::FUTURE_NOT_SEND),
|
||||||
|
LintId::of(let_if_seq::USELESS_LET_IF_SEQ),
|
||||||
|
LintId::of(missing_const_for_fn::MISSING_CONST_FOR_FN),
|
||||||
|
LintId::of(mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL),
|
||||||
|
LintId::of(mutex_atomic::MUTEX_INTEGER),
|
||||||
|
LintId::of(non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY),
|
||||||
|
LintId::of(nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES),
|
||||||
|
LintId::of(option_if_let_else::OPTION_IF_LET_ELSE),
|
||||||
|
LintId::of(path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE),
|
||||||
|
LintId::of(redundant_pub_crate::REDUNDANT_PUB_CRATE),
|
||||||
|
LintId::of(regex::TRIVIAL_REGEX),
|
||||||
|
LintId::of(strings::STRING_LIT_AS_BYTES),
|
||||||
|
LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
|
||||||
|
LintId::of(transmute::USELESS_TRANSMUTE),
|
||||||
|
LintId::of(use_self::USE_SELF),
|
||||||
|
])
|
100
clippy_lints/src/lib.register_pedantic.rs
Normal file
100
clippy_lints/src/lib.register_pedantic.rs
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
// This file was generated by `cargo dev update_lints`.
|
||||||
|
// Use that command to update this file and do not edit by hand.
|
||||||
|
// Manual edits will be overwritten.
|
||||||
|
|
||||||
|
store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
|
||||||
|
LintId::of(attrs::INLINE_ALWAYS),
|
||||||
|
LintId::of(await_holding_invalid::AWAIT_HOLDING_LOCK),
|
||||||
|
LintId::of(await_holding_invalid::AWAIT_HOLDING_REFCELL_REF),
|
||||||
|
LintId::of(bit_mask::VERBOSE_BIT_MASK),
|
||||||
|
LintId::of(bytecount::NAIVE_BYTECOUNT),
|
||||||
|
LintId::of(case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS),
|
||||||
|
LintId::of(casts::CAST_LOSSLESS),
|
||||||
|
LintId::of(casts::CAST_POSSIBLE_TRUNCATION),
|
||||||
|
LintId::of(casts::CAST_POSSIBLE_WRAP),
|
||||||
|
LintId::of(casts::CAST_PRECISION_LOSS),
|
||||||
|
LintId::of(casts::CAST_PTR_ALIGNMENT),
|
||||||
|
LintId::of(casts::CAST_SIGN_LOSS),
|
||||||
|
LintId::of(casts::PTR_AS_PTR),
|
||||||
|
LintId::of(checked_conversions::CHECKED_CONVERSIONS),
|
||||||
|
LintId::of(copies::SAME_FUNCTIONS_IN_IF_CONDITION),
|
||||||
|
LintId::of(copy_iterator::COPY_ITERATOR),
|
||||||
|
LintId::of(default::DEFAULT_TRAIT_ACCESS),
|
||||||
|
LintId::of(dereference::EXPLICIT_DEREF_METHODS),
|
||||||
|
LintId::of(derive::EXPL_IMPL_CLONE_ON_COPY),
|
||||||
|
LintId::of(derive::UNSAFE_DERIVE_DESERIALIZE),
|
||||||
|
LintId::of(doc::DOC_MARKDOWN),
|
||||||
|
LintId::of(doc::MISSING_ERRORS_DOC),
|
||||||
|
LintId::of(doc::MISSING_PANICS_DOC),
|
||||||
|
LintId::of(empty_enum::EMPTY_ENUM),
|
||||||
|
LintId::of(enum_variants::MODULE_NAME_REPETITIONS),
|
||||||
|
LintId::of(eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS),
|
||||||
|
LintId::of(excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS),
|
||||||
|
LintId::of(excessive_bools::STRUCT_EXCESSIVE_BOOLS),
|
||||||
|
LintId::of(functions::MUST_USE_CANDIDATE),
|
||||||
|
LintId::of(functions::TOO_MANY_LINES),
|
||||||
|
LintId::of(if_not_else::IF_NOT_ELSE),
|
||||||
|
LintId::of(implicit_hasher::IMPLICIT_HASHER),
|
||||||
|
LintId::of(implicit_saturating_sub::IMPLICIT_SATURATING_SUB),
|
||||||
|
LintId::of(inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR),
|
||||||
|
LintId::of(infinite_iter::MAYBE_INFINITE_ITER),
|
||||||
|
LintId::of(invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS),
|
||||||
|
LintId::of(items_after_statements::ITEMS_AFTER_STATEMENTS),
|
||||||
|
LintId::of(iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR),
|
||||||
|
LintId::of(large_stack_arrays::LARGE_STACK_ARRAYS),
|
||||||
|
LintId::of(let_underscore::LET_UNDERSCORE_DROP),
|
||||||
|
LintId::of(literal_representation::LARGE_DIGIT_GROUPS),
|
||||||
|
LintId::of(literal_representation::UNREADABLE_LITERAL),
|
||||||
|
LintId::of(loops::EXPLICIT_INTO_ITER_LOOP),
|
||||||
|
LintId::of(loops::EXPLICIT_ITER_LOOP),
|
||||||
|
LintId::of(macro_use::MACRO_USE_IMPORTS),
|
||||||
|
LintId::of(manual_ok_or::MANUAL_OK_OR),
|
||||||
|
LintId::of(match_on_vec_items::MATCH_ON_VEC_ITEMS),
|
||||||
|
LintId::of(matches::MATCH_BOOL),
|
||||||
|
LintId::of(matches::MATCH_SAME_ARMS),
|
||||||
|
LintId::of(matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS),
|
||||||
|
LintId::of(matches::MATCH_WILD_ERR_ARM),
|
||||||
|
LintId::of(matches::SINGLE_MATCH_ELSE),
|
||||||
|
LintId::of(methods::CLONED_INSTEAD_OF_COPIED),
|
||||||
|
LintId::of(methods::FILTER_MAP_NEXT),
|
||||||
|
LintId::of(methods::FLAT_MAP_OPTION),
|
||||||
|
LintId::of(methods::FROM_ITER_INSTEAD_OF_COLLECT),
|
||||||
|
LintId::of(methods::IMPLICIT_CLONE),
|
||||||
|
LintId::of(methods::INEFFICIENT_TO_STRING),
|
||||||
|
LintId::of(methods::MAP_FLATTEN),
|
||||||
|
LintId::of(methods::MAP_UNWRAP_OR),
|
||||||
|
LintId::of(misc::FLOAT_CMP),
|
||||||
|
LintId::of(misc::USED_UNDERSCORE_BINDING),
|
||||||
|
LintId::of(misc_early::UNSEPARATED_LITERAL_SUFFIX),
|
||||||
|
LintId::of(mut_mut::MUT_MUT),
|
||||||
|
LintId::of(needless_bitwise_bool::NEEDLESS_BITWISE_BOOL),
|
||||||
|
LintId::of(needless_borrow::REF_BINDING_TO_REFERENCE),
|
||||||
|
LintId::of(needless_continue::NEEDLESS_CONTINUE),
|
||||||
|
LintId::of(needless_for_each::NEEDLESS_FOR_EACH),
|
||||||
|
LintId::of(needless_pass_by_value::NEEDLESS_PASS_BY_VALUE),
|
||||||
|
LintId::of(non_expressive_names::MANY_SINGLE_CHAR_NAMES),
|
||||||
|
LintId::of(non_expressive_names::SIMILAR_NAMES),
|
||||||
|
LintId::of(pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE),
|
||||||
|
LintId::of(pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF),
|
||||||
|
LintId::of(ranges::RANGE_MINUS_ONE),
|
||||||
|
LintId::of(ranges::RANGE_PLUS_ONE),
|
||||||
|
LintId::of(redundant_else::REDUNDANT_ELSE),
|
||||||
|
LintId::of(ref_option_ref::REF_OPTION_REF),
|
||||||
|
LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED),
|
||||||
|
LintId::of(strings::STRING_ADD_ASSIGN),
|
||||||
|
LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS),
|
||||||
|
LintId::of(trait_bounds::TYPE_REPETITION_IN_BOUNDS),
|
||||||
|
LintId::of(transmute::TRANSMUTE_PTR_TO_PTR),
|
||||||
|
LintId::of(types::LINKEDLIST),
|
||||||
|
LintId::of(types::OPTION_OPTION),
|
||||||
|
LintId::of(unicode::NON_ASCII_LITERAL),
|
||||||
|
LintId::of(unicode::UNICODE_NOT_NFC),
|
||||||
|
LintId::of(unit_types::LET_UNIT_VALUE),
|
||||||
|
LintId::of(unnecessary_wraps::UNNECESSARY_WRAPS),
|
||||||
|
LintId::of(unnested_or_patterns::UNNESTED_OR_PATTERNS),
|
||||||
|
LintId::of(unused_async::UNUSED_ASYNC),
|
||||||
|
LintId::of(unused_self::UNUSED_SELF),
|
||||||
|
LintId::of(wildcard_imports::ENUM_GLOB_USE),
|
||||||
|
LintId::of(wildcard_imports::WILDCARD_IMPORTS),
|
||||||
|
LintId::of(zero_sized_map_values::ZERO_SIZED_MAP_VALUES),
|
||||||
|
])
|
27
clippy_lints/src/lib.register_perf.rs
Normal file
27
clippy_lints/src/lib.register_perf.rs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// This file was generated by `cargo dev update_lints`.
|
||||||
|
// Use that command to update this file and do not edit by hand.
|
||||||
|
// Manual edits will be overwritten.
|
||||||
|
|
||||||
|
store.register_group(true, "clippy::perf", Some("clippy_perf"), vec![
|
||||||
|
LintId::of(entry::MAP_ENTRY),
|
||||||
|
LintId::of(escape::BOXED_LOCAL),
|
||||||
|
LintId::of(large_const_arrays::LARGE_CONST_ARRAYS),
|
||||||
|
LintId::of(large_enum_variant::LARGE_ENUM_VARIANT),
|
||||||
|
LintId::of(loops::MANUAL_MEMCPY),
|
||||||
|
LintId::of(loops::NEEDLESS_COLLECT),
|
||||||
|
LintId::of(methods::EXPECT_FUN_CALL),
|
||||||
|
LintId::of(methods::EXTEND_WITH_DRAIN),
|
||||||
|
LintId::of(methods::ITER_NTH),
|
||||||
|
LintId::of(methods::MANUAL_STR_REPEAT),
|
||||||
|
LintId::of(methods::OR_FUN_CALL),
|
||||||
|
LintId::of(methods::SINGLE_CHAR_PATTERN),
|
||||||
|
LintId::of(misc::CMP_OWNED),
|
||||||
|
LintId::of(mutex_atomic::MUTEX_ATOMIC),
|
||||||
|
LintId::of(redundant_clone::REDUNDANT_CLONE),
|
||||||
|
LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
|
||||||
|
LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE),
|
||||||
|
LintId::of(types::BOX_COLLECTION),
|
||||||
|
LintId::of(types::REDUNDANT_ALLOCATION),
|
||||||
|
LintId::of(vec::USELESS_VEC),
|
||||||
|
LintId::of(vec_init_then_push::VEC_INIT_THEN_PUSH),
|
||||||
|
])
|
65
clippy_lints/src/lib.register_restriction.rs
Normal file
65
clippy_lints/src/lib.register_restriction.rs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
// This file was generated by `cargo dev update_lints`.
|
||||||
|
// Use that command to update this file and do not edit by hand.
|
||||||
|
// Manual edits will be overwritten.
|
||||||
|
|
||||||
|
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
|
||||||
|
LintId::of(arithmetic::FLOAT_ARITHMETIC),
|
||||||
|
LintId::of(arithmetic::INTEGER_ARITHMETIC),
|
||||||
|
LintId::of(as_conversions::AS_CONVERSIONS),
|
||||||
|
LintId::of(asm_syntax::INLINE_ASM_X86_ATT_SYNTAX),
|
||||||
|
LintId::of(asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX),
|
||||||
|
LintId::of(create_dir::CREATE_DIR),
|
||||||
|
LintId::of(dbg_macro::DBG_MACRO),
|
||||||
|
LintId::of(default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK),
|
||||||
|
LintId::of(disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS),
|
||||||
|
LintId::of(else_if_without_else::ELSE_IF_WITHOUT_ELSE),
|
||||||
|
LintId::of(exhaustive_items::EXHAUSTIVE_ENUMS),
|
||||||
|
LintId::of(exhaustive_items::EXHAUSTIVE_STRUCTS),
|
||||||
|
LintId::of(exit::EXIT),
|
||||||
|
LintId::of(float_literal::LOSSY_FLOAT_LITERAL),
|
||||||
|
LintId::of(if_then_some_else_none::IF_THEN_SOME_ELSE_NONE),
|
||||||
|
LintId::of(implicit_return::IMPLICIT_RETURN),
|
||||||
|
LintId::of(indexing_slicing::INDEXING_SLICING),
|
||||||
|
LintId::of(inherent_impl::MULTIPLE_INHERENT_IMPL),
|
||||||
|
LintId::of(integer_division::INTEGER_DIVISION),
|
||||||
|
LintId::of(let_underscore::LET_UNDERSCORE_MUST_USE),
|
||||||
|
LintId::of(literal_representation::DECIMAL_LITERAL_REPRESENTATION),
|
||||||
|
LintId::of(map_err_ignore::MAP_ERR_IGNORE),
|
||||||
|
LintId::of(matches::REST_PAT_IN_FULLY_BOUND_STRUCTS),
|
||||||
|
LintId::of(matches::WILDCARD_ENUM_MATCH_ARM),
|
||||||
|
LintId::of(mem_forget::MEM_FORGET),
|
||||||
|
LintId::of(methods::CLONE_ON_REF_PTR),
|
||||||
|
LintId::of(methods::EXPECT_USED),
|
||||||
|
LintId::of(methods::FILETYPE_IS_FILE),
|
||||||
|
LintId::of(methods::GET_UNWRAP),
|
||||||
|
LintId::of(methods::UNWRAP_USED),
|
||||||
|
LintId::of(misc::FLOAT_CMP_CONST),
|
||||||
|
LintId::of(misc_early::UNNEEDED_FIELD_PATTERN),
|
||||||
|
LintId::of(missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS),
|
||||||
|
LintId::of(missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES),
|
||||||
|
LintId::of(missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS),
|
||||||
|
LintId::of(module_style::MOD_MODULE_FILES),
|
||||||
|
LintId::of(module_style::SELF_NAMED_MODULE_FILES),
|
||||||
|
LintId::of(modulo_arithmetic::MODULO_ARITHMETIC),
|
||||||
|
LintId::of(panic_in_result_fn::PANIC_IN_RESULT_FN),
|
||||||
|
LintId::of(panic_unimplemented::PANIC),
|
||||||
|
LintId::of(panic_unimplemented::TODO),
|
||||||
|
LintId::of(panic_unimplemented::UNIMPLEMENTED),
|
||||||
|
LintId::of(panic_unimplemented::UNREACHABLE),
|
||||||
|
LintId::of(pattern_type_mismatch::PATTERN_TYPE_MISMATCH),
|
||||||
|
LintId::of(same_name_method::SAME_NAME_METHOD),
|
||||||
|
LintId::of(shadow::SHADOW_REUSE),
|
||||||
|
LintId::of(shadow::SHADOW_SAME),
|
||||||
|
LintId::of(shadow::SHADOW_UNRELATED),
|
||||||
|
LintId::of(strings::STRING_ADD),
|
||||||
|
LintId::of(strings::STRING_TO_STRING),
|
||||||
|
LintId::of(strings::STR_TO_STRING),
|
||||||
|
LintId::of(types::RC_BUFFER),
|
||||||
|
LintId::of(types::RC_MUTEX),
|
||||||
|
LintId::of(unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS),
|
||||||
|
LintId::of(unwrap_in_result::UNWRAP_IN_RESULT),
|
||||||
|
LintId::of(verbose_file_reads::VERBOSE_FILE_READS),
|
||||||
|
LintId::of(write::PRINT_STDERR),
|
||||||
|
LintId::of(write::PRINT_STDOUT),
|
||||||
|
LintId::of(write::USE_DEBUG),
|
||||||
|
])
|
114
clippy_lints/src/lib.register_style.rs
Normal file
114
clippy_lints/src/lib.register_style.rs
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
// This file was generated by `cargo dev update_lints`.
|
||||||
|
// Use that command to update this file and do not edit by hand.
|
||||||
|
// Manual edits will be overwritten.
|
||||||
|
|
||||||
|
store.register_group(true, "clippy::style", Some("clippy_style"), vec![
|
||||||
|
LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS),
|
||||||
|
LintId::of(assign_ops::ASSIGN_OP_PATTERN),
|
||||||
|
LintId::of(blacklisted_name::BLACKLISTED_NAME),
|
||||||
|
LintId::of(blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS),
|
||||||
|
LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON),
|
||||||
|
LintId::of(casts::FN_TO_NUMERIC_CAST),
|
||||||
|
LintId::of(casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION),
|
||||||
|
LintId::of(collapsible_if::COLLAPSIBLE_ELSE_IF),
|
||||||
|
LintId::of(collapsible_if::COLLAPSIBLE_IF),
|
||||||
|
LintId::of(collapsible_match::COLLAPSIBLE_MATCH),
|
||||||
|
LintId::of(comparison_chain::COMPARISON_CHAIN),
|
||||||
|
LintId::of(default::FIELD_REASSIGN_WITH_DEFAULT),
|
||||||
|
LintId::of(doc::MISSING_SAFETY_DOC),
|
||||||
|
LintId::of(doc::NEEDLESS_DOCTEST_MAIN),
|
||||||
|
LintId::of(enum_variants::ENUM_VARIANT_NAMES),
|
||||||
|
LintId::of(enum_variants::MODULE_INCEPTION),
|
||||||
|
LintId::of(eq_op::OP_REF),
|
||||||
|
LintId::of(eta_reduction::REDUNDANT_CLOSURE),
|
||||||
|
LintId::of(float_literal::EXCESSIVE_PRECISION),
|
||||||
|
LintId::of(from_over_into::FROM_OVER_INTO),
|
||||||
|
LintId::of(from_str_radix_10::FROM_STR_RADIX_10),
|
||||||
|
LintId::of(functions::DOUBLE_MUST_USE),
|
||||||
|
LintId::of(functions::MUST_USE_UNIT),
|
||||||
|
LintId::of(functions::RESULT_UNIT_ERR),
|
||||||
|
LintId::of(if_then_panic::IF_THEN_PANIC),
|
||||||
|
LintId::of(inherent_to_string::INHERENT_TO_STRING),
|
||||||
|
LintId::of(len_zero::COMPARISON_TO_EMPTY),
|
||||||
|
LintId::of(len_zero::LEN_WITHOUT_IS_EMPTY),
|
||||||
|
LintId::of(len_zero::LEN_ZERO),
|
||||||
|
LintId::of(literal_representation::INCONSISTENT_DIGIT_GROUPING),
|
||||||
|
LintId::of(literal_representation::UNUSUAL_BYTE_GROUPINGS),
|
||||||
|
LintId::of(loops::FOR_KV_MAP),
|
||||||
|
LintId::of(loops::NEEDLESS_RANGE_LOOP),
|
||||||
|
LintId::of(loops::SAME_ITEM_PUSH),
|
||||||
|
LintId::of(loops::WHILE_LET_ON_ITERATOR),
|
||||||
|
LintId::of(main_recursion::MAIN_RECURSION),
|
||||||
|
LintId::of(manual_async_fn::MANUAL_ASYNC_FN),
|
||||||
|
LintId::of(manual_map::MANUAL_MAP),
|
||||||
|
LintId::of(manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE),
|
||||||
|
LintId::of(map_clone::MAP_CLONE),
|
||||||
|
LintId::of(match_result_ok::MATCH_RESULT_OK),
|
||||||
|
LintId::of(matches::INFALLIBLE_DESTRUCTURING_MATCH),
|
||||||
|
LintId::of(matches::MATCH_LIKE_MATCHES_MACRO),
|
||||||
|
LintId::of(matches::MATCH_OVERLAPPING_ARM),
|
||||||
|
LintId::of(matches::MATCH_REF_PATS),
|
||||||
|
LintId::of(matches::REDUNDANT_PATTERN_MATCHING),
|
||||||
|
LintId::of(matches::SINGLE_MATCH),
|
||||||
|
LintId::of(mem_replace::MEM_REPLACE_OPTION_WITH_NONE),
|
||||||
|
LintId::of(mem_replace::MEM_REPLACE_WITH_DEFAULT),
|
||||||
|
LintId::of(methods::BYTES_NTH),
|
||||||
|
LintId::of(methods::CHARS_LAST_CMP),
|
||||||
|
LintId::of(methods::CHARS_NEXT_CMP),
|
||||||
|
LintId::of(methods::INTO_ITER_ON_REF),
|
||||||
|
LintId::of(methods::ITER_CLONED_COLLECT),
|
||||||
|
LintId::of(methods::ITER_NEXT_SLICE),
|
||||||
|
LintId::of(methods::ITER_NTH_ZERO),
|
||||||
|
LintId::of(methods::ITER_SKIP_NEXT),
|
||||||
|
LintId::of(methods::MANUAL_SATURATING_ARITHMETIC),
|
||||||
|
LintId::of(methods::MAP_COLLECT_RESULT_UNIT),
|
||||||
|
LintId::of(methods::NEW_RET_NO_SELF),
|
||||||
|
LintId::of(methods::OK_EXPECT),
|
||||||
|
LintId::of(methods::OPTION_MAP_OR_NONE),
|
||||||
|
LintId::of(methods::RESULT_MAP_OR_INTO_OPTION),
|
||||||
|
LintId::of(methods::SHOULD_IMPLEMENT_TRAIT),
|
||||||
|
LintId::of(methods::SINGLE_CHAR_ADD_STR),
|
||||||
|
LintId::of(methods::STRING_EXTEND_CHARS),
|
||||||
|
LintId::of(methods::UNNECESSARY_FOLD),
|
||||||
|
LintId::of(methods::UNNECESSARY_LAZY_EVALUATIONS),
|
||||||
|
LintId::of(methods::UNWRAP_OR_ELSE_DEFAULT),
|
||||||
|
LintId::of(methods::WRONG_SELF_CONVENTION),
|
||||||
|
LintId::of(misc::TOPLEVEL_REF_ARG),
|
||||||
|
LintId::of(misc::ZERO_PTR),
|
||||||
|
LintId::of(misc_early::BUILTIN_TYPE_SHADOW),
|
||||||
|
LintId::of(misc_early::DOUBLE_NEG),
|
||||||
|
LintId::of(misc_early::DUPLICATE_UNDERSCORE_ARGUMENT),
|
||||||
|
LintId::of(misc_early::MIXED_CASE_HEX_LITERALS),
|
||||||
|
LintId::of(misc_early::REDUNDANT_PATTERN),
|
||||||
|
LintId::of(mut_mutex_lock::MUT_MUTEX_LOCK),
|
||||||
|
LintId::of(mut_reference::UNNECESSARY_MUT_PASSED),
|
||||||
|
LintId::of(needless_borrow::NEEDLESS_BORROW),
|
||||||
|
LintId::of(neg_multiply::NEG_MULTIPLY),
|
||||||
|
LintId::of(new_without_default::NEW_WITHOUT_DEFAULT),
|
||||||
|
LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST),
|
||||||
|
LintId::of(non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST),
|
||||||
|
LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
|
||||||
|
LintId::of(ptr::CMP_NULL),
|
||||||
|
LintId::of(ptr::PTR_ARG),
|
||||||
|
LintId::of(ptr_eq::PTR_EQ),
|
||||||
|
LintId::of(question_mark::QUESTION_MARK),
|
||||||
|
LintId::of(ranges::MANUAL_RANGE_CONTAINS),
|
||||||
|
LintId::of(redundant_field_names::REDUNDANT_FIELD_NAMES),
|
||||||
|
LintId::of(redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
|
||||||
|
LintId::of(returns::LET_AND_RETURN),
|
||||||
|
LintId::of(returns::NEEDLESS_RETURN),
|
||||||
|
LintId::of(self_named_constructors::SELF_NAMED_CONSTRUCTORS),
|
||||||
|
LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
|
||||||
|
LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
|
||||||
|
LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME),
|
||||||
|
LintId::of(try_err::TRY_ERR),
|
||||||
|
LintId::of(unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME),
|
||||||
|
LintId::of(unused_unit::UNUSED_UNIT),
|
||||||
|
LintId::of(upper_case_acronyms::UPPER_CASE_ACRONYMS),
|
||||||
|
LintId::of(write::PRINTLN_EMPTY_STRING),
|
||||||
|
LintId::of(write::PRINT_LITERAL),
|
||||||
|
LintId::of(write::PRINT_WITH_NEWLINE),
|
||||||
|
LintId::of(write::WRITELN_EMPTY_STRING),
|
||||||
|
LintId::of(write::WRITE_LITERAL),
|
||||||
|
LintId::of(write::WRITE_WITH_NEWLINE),
|
||||||
|
])
|
20
clippy_lints/src/lib.register_suspicious.rs
Normal file
20
clippy_lints/src/lib.register_suspicious.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// This file was generated by `cargo dev update_lints`.
|
||||||
|
// Use that command to update this file and do not edit by hand.
|
||||||
|
// Manual edits will be overwritten.
|
||||||
|
|
||||||
|
store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), vec![
|
||||||
|
LintId::of(assign_ops::MISREFACTORED_ASSIGN_OP),
|
||||||
|
LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS),
|
||||||
|
LintId::of(eval_order_dependence::EVAL_ORDER_DEPENDENCE),
|
||||||
|
LintId::of(float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS),
|
||||||
|
LintId::of(formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING),
|
||||||
|
LintId::of(formatting::SUSPICIOUS_ELSE_FORMATTING),
|
||||||
|
LintId::of(formatting::SUSPICIOUS_UNARY_OP_FORMATTING),
|
||||||
|
LintId::of(loops::EMPTY_LOOP),
|
||||||
|
LintId::of(loops::FOR_LOOPS_OVER_FALLIBLES),
|
||||||
|
LintId::of(loops::MUT_RANGE_BOUND),
|
||||||
|
LintId::of(methods::SUSPICIOUS_MAP),
|
||||||
|
LintId::of(mut_key::MUTABLE_KEY_TYPE),
|
||||||
|
LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
|
||||||
|
LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
|
||||||
|
])
|
File diff suppressed because it is too large
Load diff
|
@ -92,7 +92,7 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
|
||||||
fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
||||||
|
|
||||||
fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, bk: ty::BorrowKind) {
|
fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, bk: ty::BorrowKind) {
|
||||||
if let ty::BorrowKind::MutBorrow = bk {
|
if bk == ty::BorrowKind::MutBorrow {
|
||||||
if let PlaceBase::Local(id) = cmt.place.base {
|
if let PlaceBase::Local(id) = cmt.place.base {
|
||||||
if Some(id) == self.hir_id_low && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) {
|
if Some(id) == self.hir_id_low && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) {
|
||||||
self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id));
|
self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id));
|
||||||
|
|
|
@ -95,7 +95,7 @@ pub(super) fn check<'tcx>(
|
||||||
let mut take_expr = end;
|
let mut take_expr = end;
|
||||||
|
|
||||||
if let ExprKind::Binary(ref op, left, right) = end.kind {
|
if let ExprKind::Binary(ref op, left, right) = end.kind {
|
||||||
if let BinOpKind::Add = op.node {
|
if op.node == BinOpKind::Add {
|
||||||
let start_equal_left = SpanlessEq::new(cx).eq_expr(start, left);
|
let start_equal_left = SpanlessEq::new(cx).eq_expr(start, left);
|
||||||
let start_equal_right = SpanlessEq::new(cx).eq_expr(start, right);
|
let start_equal_right = SpanlessEq::new(cx).eq_expr(start, right);
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||||
NeverLoopResult::AlwaysBreak => {
|
NeverLoopResult::AlwaysBreak => {
|
||||||
span_lint_and_then(cx, NEVER_LOOP, expr.span, "this loop never actually loops", |diag| {
|
span_lint_and_then(cx, NEVER_LOOP, expr.span, "this loop never actually loops", |diag| {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let LoopSource::ForLoop = source;
|
if source == LoopSource::ForLoop;
|
||||||
if let Some((_, Node::Expr(parent_match))) = cx.tcx.hir().parent_iter(expr.hir_id).nth(1);
|
if let Some((_, Node::Expr(parent_match))) = cx.tcx.hir().parent_iter(expr.hir_id).nth(1);
|
||||||
if let Some(ForLoop { arg: iterator, pat, span: for_span, .. }) = ForLoop::hir(parent_match);
|
if let Some(ForLoop { arg: iterator, pat, span: for_span, .. }) = ForLoop::hir(parent_match);
|
||||||
then {
|
then {
|
||||||
|
|
|
@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
|
||||||
) {
|
) {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let Some(header) = kind.header();
|
if let Some(header) = kind.header();
|
||||||
if let IsAsync::NotAsync = header.asyncness;
|
if header.asyncness == IsAsync::NotAsync;
|
||||||
// Check that this function returns `impl Future`
|
// Check that this function returns `impl Future`
|
||||||
if let FnRetTy::Return(ret_ty) = decl.output;
|
if let FnRetTy::Return(ret_ty) = decl.output;
|
||||||
if let Some((trait_ref, output_lifetimes)) = future_trait_ref(cx, ret_ty);
|
if let Some((trait_ref, output_lifetimes)) = future_trait_ref(cx, ret_ty);
|
||||||
|
@ -178,7 +178,7 @@ fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>)
|
||||||
if args.len() == 1;
|
if args.len() == 1;
|
||||||
if let Expr{kind: ExprKind::Closure(_, _, body_id, ..), ..} = args[0];
|
if let Expr{kind: ExprKind::Closure(_, _, body_id, ..), ..} = args[0];
|
||||||
let closure_body = cx.tcx.hir().body(body_id);
|
let closure_body = cx.tcx.hir().body(body_id);
|
||||||
if let Some(GeneratorKind::Async(AsyncGeneratorKind::Block)) = closure_body.generator_kind;
|
if closure_body.generator_kind == Some(GeneratorKind::Async(AsyncGeneratorKind::Block));
|
||||||
then {
|
then {
|
||||||
return Some(closure_body);
|
return Some(closure_body);
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,14 +205,13 @@ fn suggestion_msg(function_type: &str, map_type: &str) -> String {
|
||||||
fn lint_map_unit_fn(cx: &LateContext<'_>, stmt: &hir::Stmt<'_>, expr: &hir::Expr<'_>, map_args: &[hir::Expr<'_>]) {
|
fn lint_map_unit_fn(cx: &LateContext<'_>, stmt: &hir::Stmt<'_>, expr: &hir::Expr<'_>, map_args: &[hir::Expr<'_>]) {
|
||||||
let var_arg = &map_args[0];
|
let var_arg = &map_args[0];
|
||||||
|
|
||||||
let (map_type, variant, lint) =
|
let (map_type, variant, lint) = if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(var_arg), sym::Option) {
|
||||||
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(var_arg), sym::Option) {
|
("Option", "Some", OPTION_MAP_UNIT_FN)
|
||||||
("Option", "Some", OPTION_MAP_UNIT_FN)
|
} else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(var_arg), sym::Result) {
|
||||||
} else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(var_arg), sym::Result) {
|
("Result", "Ok", RESULT_MAP_UNIT_FN)
|
||||||
("Result", "Ok", RESULT_MAP_UNIT_FN)
|
} else {
|
||||||
} else {
|
return;
|
||||||
return;
|
};
|
||||||
};
|
|
||||||
let fn_arg = &map_args[1];
|
let fn_arg = &map_args[1];
|
||||||
|
|
||||||
if is_unit_function(cx, fn_arg) {
|
if is_unit_function(cx, fn_arg) {
|
||||||
|
|
|
@ -1025,8 +1025,7 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
|
||||||
let adt_def = match ty.kind() {
|
let adt_def = match ty.kind() {
|
||||||
ty::Adt(adt_def, _)
|
ty::Adt(adt_def, _)
|
||||||
if adt_def.is_enum()
|
if adt_def.is_enum()
|
||||||
&& !(is_type_diagnostic_item(cx, ty, sym::Option)
|
&& !(is_type_diagnostic_item(cx, ty, sym::Option) || is_type_diagnostic_item(cx, ty, sym::Result)) =>
|
||||||
|| is_type_diagnostic_item(cx, ty, sym::Result)) =>
|
|
||||||
{
|
{
|
||||||
adt_def
|
adt_def
|
||||||
},
|
},
|
||||||
|
|
|
@ -1284,8 +1284,9 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// ### Why is this bad?
|
/// ### Why is this bad?
|
||||||
/// It looks suspicious. Maybe `map` was confused with `filter`.
|
/// It looks suspicious. Maybe `map` was confused with `filter`.
|
||||||
/// If the `map` call is intentional, this should be rewritten. Or, if you intend to
|
/// If the `map` call is intentional, this should be rewritten
|
||||||
/// drive the iterator to completion, you can just use `for_each` instead.
|
/// using `inspect`. Or, if you intend to drive the iterator to
|
||||||
|
/// completion, you can just use `for_each` instead.
|
||||||
///
|
///
|
||||||
/// ### Example
|
/// ### Example
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
|
|
@ -178,15 +178,15 @@ pub(super) fn check<'tcx>(
|
||||||
hir::ExprKind::Index(..) | hir::ExprKind::MethodCall(..) => {
|
hir::ExprKind::Index(..) | hir::ExprKind::MethodCall(..) => {
|
||||||
check_general_case(cx, name, method_span, &args[0], &args[1], expr.span, None);
|
check_general_case(cx, name, method_span, &args[0], &args[1], expr.span, None);
|
||||||
},
|
},
|
||||||
hir::ExprKind::Block(block, _) => {
|
hir::ExprKind::Block(block, _)
|
||||||
if let BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) = block.rules {
|
if block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) =>
|
||||||
if let Some(block_expr) = block.expr {
|
{
|
||||||
if let hir::ExprKind::MethodCall(..) = block_expr.kind {
|
if let Some(block_expr) = block.expr {
|
||||||
check_general_case(cx, name, method_span, &args[0], &args[1], expr.span, None);
|
if let hir::ExprKind::MethodCall(..) = block_expr.kind {
|
||||||
}
|
check_general_case(cx, name, method_span, &args[0], &args[1], expr.span, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, count_recv: &hi
|
||||||
expr.span,
|
expr.span,
|
||||||
"this call to `map()` won't have an effect on the call to `count()`",
|
"this call to `map()` won't have an effect on the call to `count()`",
|
||||||
None,
|
None,
|
||||||
"make sure you did not confuse `map` with `filter` or `for_each`",
|
"make sure you did not confuse `map` with `filter`, `for_each` or `inspect`",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<
|
||||||
let in_ty = cx.typeck_results().node_type(body.params[0].hir_id);
|
let in_ty = cx.typeck_results().node_type(body.params[0].hir_id);
|
||||||
match cx.typeck_results().expr_ty(&body.value).kind() {
|
match cx.typeck_results().expr_ty(&body.value).kind() {
|
||||||
ty::Adt(adt, subst)
|
ty::Adt(adt, subst)
|
||||||
if cx.tcx.is_diagnostic_item(sym::Option, adt.did)
|
if cx.tcx.is_diagnostic_item(sym::Option, adt.did) && TyS::same_type(in_ty, subst.type_at(0)) =>
|
||||||
&& TyS::same_type(in_ty, subst.type_at(0)) =>
|
|
||||||
{
|
{
|
||||||
"filter"
|
"filter"
|
||||||
},
|
},
|
||||||
|
|
|
@ -128,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for ModuloArithmetic {
|
||||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||||
match &expr.kind {
|
match &expr.kind {
|
||||||
ExprKind::Binary(op, lhs, rhs) | ExprKind::AssignOp(op, lhs, rhs) => {
|
ExprKind::Binary(op, lhs, rhs) | ExprKind::AssignOp(op, lhs, rhs) => {
|
||||||
if let BinOpKind::Rem = op.node {
|
if op.node == BinOpKind::Rem {
|
||||||
let lhs_operand = analyze_operand(lhs, cx, expr);
|
let lhs_operand = analyze_operand(lhs, cx, expr);
|
||||||
let rhs_operand = analyze_operand(rhs, cx, expr);
|
let rhs_operand = analyze_operand(rhs, cx, expr);
|
||||||
if_chain! {
|
if_chain! {
|
||||||
|
|
|
@ -248,7 +248,7 @@ fn check_comparison<'a, 'tcx>(
|
||||||
if l_ty.is_bool() && r_ty.is_bool() {
|
if l_ty.is_bool() && r_ty.is_bool() {
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
|
|
||||||
if let BinOpKind::Eq = op.node {
|
if op.node == BinOpKind::Eq {
|
||||||
let expression_info = one_side_is_unary_not(left_side, right_side);
|
let expression_info = one_side_is_unary_not(left_side, right_side);
|
||||||
if expression_info.one_side_is_unary_not {
|
if expression_info.one_side_is_unary_not {
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
|
|
|
@ -46,7 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for NegMultiply {
|
||||||
fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) {
|
fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let ExprKind::Lit(ref l) = lit.kind;
|
if let ExprKind::Lit(ref l) = lit.kind;
|
||||||
if let Constant::Int(1) = consts::lit_to_constant(&l.node, cx.typeck_results().expr_ty_opt(lit));
|
if consts::lit_to_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)) == Constant::Int(1);
|
||||||
if cx.typeck_results().expr_ty(exp).is_integral();
|
if cx.typeck_results().expr_ty(exp).is_integral();
|
||||||
then {
|
then {
|
||||||
span_lint(cx, NEG_MULTIPLY, span, "negation by multiplying with `-1`");
|
span_lint(cx, NEG_MULTIPLY, span, "negation by multiplying with `-1`");
|
||||||
|
|
|
@ -69,7 +69,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
|
||||||
}) = item.kind
|
}) = item.kind
|
||||||
{
|
{
|
||||||
for assoc_item in items {
|
for assoc_item in items {
|
||||||
if let hir::AssocItemKind::Fn { has_self: false } = assoc_item.kind {
|
if assoc_item.kind == (hir::AssocItemKind::Fn { has_self: false }) {
|
||||||
let impl_item = cx.tcx.hir().impl_item(assoc_item.id);
|
let impl_item = cx.tcx.hir().impl_item(assoc_item.id);
|
||||||
if in_external_macro(cx.sess(), impl_item.span) {
|
if in_external_macro(cx.sess(), impl_item.span) {
|
||||||
return;
|
return;
|
||||||
|
|
238
clippy_lints/src/non_send_fields_in_send_ty.rs
Normal file
238
clippy_lints/src/non_send_fields_in_send_ty.rs
Normal file
|
@ -0,0 +1,238 @@
|
||||||
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
|
use clippy_utils::is_lint_allowed;
|
||||||
|
use clippy_utils::source::snippet;
|
||||||
|
use clippy_utils::ty::{implements_trait, is_copy};
|
||||||
|
use rustc_ast::ImplPolarity;
|
||||||
|
use rustc_hir::def_id::DefId;
|
||||||
|
use rustc_hir::{FieldDef, Item, ItemKind, Node};
|
||||||
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
|
use rustc_middle::ty::{self, subst::GenericArgKind, Ty};
|
||||||
|
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||||
|
use rustc_span::sym;
|
||||||
|
|
||||||
|
declare_clippy_lint! {
|
||||||
|
/// ### What it does
|
||||||
|
/// Warns about fields in struct implementing `Send` that are neither `Send` nor `Copy`.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// Sending the struct to another thread will transfer the ownership to
|
||||||
|
/// the new thread by dropping in the current thread during the transfer.
|
||||||
|
/// This causes soundness issues for non-`Send` fields, as they are also
|
||||||
|
/// dropped and might not be set up to handle this.
|
||||||
|
///
|
||||||
|
/// See:
|
||||||
|
/// * [*The Rustonomicon* about *Send and Sync*](https://doc.rust-lang.org/nomicon/send-and-sync.html)
|
||||||
|
/// * [The documentation of `Send`](https://doc.rust-lang.org/std/marker/trait.Send.html)
|
||||||
|
///
|
||||||
|
/// ### Known Problems
|
||||||
|
/// Data structures that contain raw pointers may cause false positives.
|
||||||
|
/// They are sometimes safe to be sent across threads but do not implement
|
||||||
|
/// the `Send` trait. This lint has a heuristic to filter out basic cases
|
||||||
|
/// such as `Vec<*const T>`, but it's not perfect. Feel free to create an
|
||||||
|
/// issue if you have a suggestion on how this heuristic can be improved.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// struct ExampleStruct<T> {
|
||||||
|
/// rc_is_not_send: Rc<String>,
|
||||||
|
/// unbounded_generic_field: T,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // This impl is unsound because it allows sending `!Send` types through `ExampleStruct`
|
||||||
|
/// unsafe impl<T> Send for ExampleStruct<T> {}
|
||||||
|
/// ```
|
||||||
|
/// Use thread-safe types like [`std::sync::Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html)
|
||||||
|
/// or specify correct bounds on generic type parameters (`T: Send`).
|
||||||
|
pub NON_SEND_FIELDS_IN_SEND_TY,
|
||||||
|
nursery,
|
||||||
|
"there is field that does not implement `Send` in a `Send` struct"
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct NonSendFieldInSendTy {
|
||||||
|
enable_raw_pointer_heuristic: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NonSendFieldInSendTy {
|
||||||
|
pub fn new(enable_raw_pointer_heuristic: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
enable_raw_pointer_heuristic,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_lint_pass!(NonSendFieldInSendTy => [NON_SEND_FIELDS_IN_SEND_TY]);
|
||||||
|
|
||||||
|
impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy {
|
||||||
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||||
|
let ty_allowed_in_send = if self.enable_raw_pointer_heuristic {
|
||||||
|
ty_allowed_with_raw_pointer_heuristic
|
||||||
|
} else {
|
||||||
|
ty_allowed_without_raw_pointer_heuristic
|
||||||
|
};
|
||||||
|
|
||||||
|
// Checks if we are in `Send` impl item.
|
||||||
|
// We start from `Send` impl instead of `check_field_def()` because
|
||||||
|
// single `AdtDef` may have multiple `Send` impls due to generic
|
||||||
|
// parameters, and the lint is much easier to implement in this way.
|
||||||
|
if_chain! {
|
||||||
|
if let Some(send_trait) = cx.tcx.get_diagnostic_item(sym::Send);
|
||||||
|
if let ItemKind::Impl(hir_impl) = &item.kind;
|
||||||
|
if let Some(trait_ref) = &hir_impl.of_trait;
|
||||||
|
if let Some(trait_id) = trait_ref.trait_def_id();
|
||||||
|
if send_trait == trait_id;
|
||||||
|
if hir_impl.polarity == ImplPolarity::Positive;
|
||||||
|
if let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.def_id);
|
||||||
|
if let self_ty = ty_trait_ref.self_ty();
|
||||||
|
if let ty::Adt(adt_def, impl_trait_substs) = self_ty.kind();
|
||||||
|
then {
|
||||||
|
let mut non_send_fields = Vec::new();
|
||||||
|
|
||||||
|
let hir_map = cx.tcx.hir();
|
||||||
|
for variant in &adt_def.variants {
|
||||||
|
for field in &variant.fields {
|
||||||
|
if_chain! {
|
||||||
|
if let Some(field_hir_id) = field
|
||||||
|
.did
|
||||||
|
.as_local()
|
||||||
|
.map(|local_def_id| hir_map.local_def_id_to_hir_id(local_def_id));
|
||||||
|
if !is_lint_allowed(cx, NON_SEND_FIELDS_IN_SEND_TY, field_hir_id);
|
||||||
|
if let field_ty = field.ty(cx.tcx, impl_trait_substs);
|
||||||
|
if !ty_allowed_in_send(cx, field_ty, send_trait);
|
||||||
|
if let Node::Field(field_def) = hir_map.get(field_hir_id);
|
||||||
|
then {
|
||||||
|
non_send_fields.push(NonSendField {
|
||||||
|
def: field_def,
|
||||||
|
ty: field_ty,
|
||||||
|
generic_params: collect_generic_params(cx, field_ty),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !non_send_fields.is_empty() {
|
||||||
|
span_lint_and_then(
|
||||||
|
cx,
|
||||||
|
NON_SEND_FIELDS_IN_SEND_TY,
|
||||||
|
item.span,
|
||||||
|
&format!(
|
||||||
|
"this implementation is unsound, as some fields in `{}` are `!Send`",
|
||||||
|
snippet(cx, hir_impl.self_ty.span, "Unknown")
|
||||||
|
),
|
||||||
|
|diag| {
|
||||||
|
for field in non_send_fields {
|
||||||
|
diag.span_note(
|
||||||
|
field.def.span,
|
||||||
|
&format!("the type of field `{}` is `!Send`", field.def.ident.name),
|
||||||
|
);
|
||||||
|
|
||||||
|
match field.generic_params.len() {
|
||||||
|
0 => diag.help("use a thread-safe type that implements `Send`"),
|
||||||
|
1 if is_ty_param(field.ty) => diag.help(&format!("add `{}: Send` bound in `Send` impl", field.ty)),
|
||||||
|
_ => diag.help(&format!(
|
||||||
|
"add bounds on type parameter{} `{}` that satisfy `{}: Send`",
|
||||||
|
if field.generic_params.len() > 1 { "s" } else { "" },
|
||||||
|
field.generic_params_string(),
|
||||||
|
snippet(cx, field.def.ty.span, "Unknown"),
|
||||||
|
)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NonSendField<'tcx> {
|
||||||
|
def: &'tcx FieldDef<'tcx>,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
generic_params: Vec<Ty<'tcx>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> NonSendField<'tcx> {
|
||||||
|
fn generic_params_string(&self) -> String {
|
||||||
|
self.generic_params
|
||||||
|
.iter()
|
||||||
|
.map(ToString::to_string)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Given a type, collect all of its generic parameters.
|
||||||
|
/// Example: `MyStruct<P, Box<Q, R>>` => `vec![P, Q, R]`
|
||||||
|
fn collect_generic_params<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Vec<Ty<'tcx>> {
|
||||||
|
ty.walk(cx.tcx)
|
||||||
|
.filter_map(|inner| match inner.unpack() {
|
||||||
|
GenericArgKind::Type(inner_ty) => Some(inner_ty),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.filter(|&inner_ty| is_ty_param(inner_ty))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Be more strict when the heuristic is disabled
|
||||||
|
fn ty_allowed_without_raw_pointer_heuristic<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, send_trait: DefId) -> bool {
|
||||||
|
if implements_trait(cx, ty, send_trait, &[]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_copy(cx, ty) && !contains_raw_pointer(cx, ty) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Heuristic to allow cases like `Vec<*const u8>`
|
||||||
|
fn ty_allowed_with_raw_pointer_heuristic<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, send_trait: DefId) -> bool {
|
||||||
|
if implements_trait(cx, ty, send_trait, &[]) || is_copy(cx, ty) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The type is known to be `!Send` and `!Copy`
|
||||||
|
match ty.kind() {
|
||||||
|
ty::Tuple(_) => ty
|
||||||
|
.tuple_fields()
|
||||||
|
.all(|ty| ty_allowed_with_raw_pointer_heuristic(cx, ty, send_trait)),
|
||||||
|
ty::Array(ty, _) | ty::Slice(ty) => ty_allowed_with_raw_pointer_heuristic(cx, ty, send_trait),
|
||||||
|
ty::Adt(_, substs) => {
|
||||||
|
if contains_raw_pointer(cx, ty) {
|
||||||
|
// descends only if ADT contains any raw pointers
|
||||||
|
substs.iter().all(|generic_arg| match generic_arg.unpack() {
|
||||||
|
GenericArgKind::Type(ty) => ty_allowed_with_raw_pointer_heuristic(cx, ty, send_trait),
|
||||||
|
// Lifetimes and const generics are not solid part of ADT and ignored
|
||||||
|
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => true,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Raw pointers are `!Send` but allowed by the heuristic
|
||||||
|
ty::RawPtr(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if the type contains any raw pointers in substs (including nested ones).
|
||||||
|
fn contains_raw_pointer<'tcx>(cx: &LateContext<'tcx>, target_ty: Ty<'tcx>) -> bool {
|
||||||
|
for ty_node in target_ty.walk(cx.tcx) {
|
||||||
|
if_chain! {
|
||||||
|
if let GenericArgKind::Type(inner_ty) = ty_node.unpack();
|
||||||
|
if let ty::RawPtr(_) = inner_ty.kind();
|
||||||
|
then {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the type is a type parameter such as `T`.
|
||||||
|
fn is_ty_param(target_ty: Ty<'_>) -> bool {
|
||||||
|
matches!(target_ty.kind(), ty::Param(_))
|
||||||
|
}
|
|
@ -26,6 +26,9 @@ declare_clippy_lint! {
|
||||||
|
|
||||||
declare_lint_pass!(OverflowCheckConditional => [OVERFLOW_CHECK_CONDITIONAL]);
|
declare_lint_pass!(OverflowCheckConditional => [OVERFLOW_CHECK_CONDITIONAL]);
|
||||||
|
|
||||||
|
const OVERFLOW_MSG: &str = "you are trying to use classic C overflow conditions that will fail in Rust";
|
||||||
|
const UNDERFLOW_MSG: &str = "you are trying to use classic C underflow conditions that will fail in Rust";
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for OverflowCheckConditional {
|
impl<'tcx> LateLintPass<'tcx> for OverflowCheckConditional {
|
||||||
// a + b < a, a > a + b, a < a - b, a - b > a
|
// a + b < a, a > a + b, a < a - b, a - b > a
|
||||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||||
|
@ -40,17 +43,11 @@ impl<'tcx> LateLintPass<'tcx> for OverflowCheckConditional {
|
||||||
if cx.typeck_results().expr_ty(ident1).is_integral();
|
if cx.typeck_results().expr_ty(ident1).is_integral();
|
||||||
if cx.typeck_results().expr_ty(ident2).is_integral();
|
if cx.typeck_results().expr_ty(ident2).is_integral();
|
||||||
then {
|
then {
|
||||||
if let BinOpKind::Lt = op.node {
|
if op.node == BinOpKind::Lt && op2.node == BinOpKind::Add {
|
||||||
if let BinOpKind::Add = op2.node {
|
span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, OVERFLOW_MSG);
|
||||||
span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span,
|
|
||||||
"you are trying to use classic C overflow conditions that will fail in Rust");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if let BinOpKind::Gt = op.node {
|
if op.node == BinOpKind::Gt && op2.node == BinOpKind::Sub {
|
||||||
if let BinOpKind::Sub = op2.node {
|
span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, UNDERFLOW_MSG);
|
||||||
span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span,
|
|
||||||
"you are trying to use classic C underflow conditions that will fail in Rust");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,17 +62,11 @@ impl<'tcx> LateLintPass<'tcx> for OverflowCheckConditional {
|
||||||
if cx.typeck_results().expr_ty(ident1).is_integral();
|
if cx.typeck_results().expr_ty(ident1).is_integral();
|
||||||
if cx.typeck_results().expr_ty(ident2).is_integral();
|
if cx.typeck_results().expr_ty(ident2).is_integral();
|
||||||
then {
|
then {
|
||||||
if let BinOpKind::Gt = op.node {
|
if op.node == BinOpKind::Gt && op2.node == BinOpKind::Add {
|
||||||
if let BinOpKind::Add = op2.node {
|
span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, OVERFLOW_MSG);
|
||||||
span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span,
|
|
||||||
"you are trying to use classic C overflow conditions that will fail in Rust");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if let BinOpKind::Lt = op.node {
|
if op.node == BinOpKind::Lt && op2.node == BinOpKind::Sub {
|
||||||
if let BinOpKind::Sub = op2.node {
|
span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, UNDERFLOW_MSG);
|
||||||
span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span,
|
|
||||||
"you are trying to use classic C underflow conditions that will fail in Rust");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,25 +41,23 @@ impl_lint_pass!(RedundantPubCrate => [REDUNDANT_PUB_CRATE]);
|
||||||
impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
|
impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||||
if let VisibilityKind::Crate { .. } = item.vis.node {
|
if let VisibilityKind::Crate { .. } = item.vis.node {
|
||||||
if !cx.access_levels.is_exported(item.def_id) {
|
if !cx.access_levels.is_exported(item.def_id) && self.is_exported.last() == Some(&false) {
|
||||||
if let Some(false) = self.is_exported.last() {
|
let span = item.span.with_hi(item.ident.span.hi());
|
||||||
let span = item.span.with_hi(item.ident.span.hi());
|
let descr = cx.tcx.def_kind(item.def_id).descr(item.def_id.to_def_id());
|
||||||
let descr = cx.tcx.def_kind(item.def_id).descr(item.def_id.to_def_id());
|
span_lint_and_then(
|
||||||
span_lint_and_then(
|
cx,
|
||||||
cx,
|
REDUNDANT_PUB_CRATE,
|
||||||
REDUNDANT_PUB_CRATE,
|
span,
|
||||||
span,
|
&format!("pub(crate) {} inside private module", descr),
|
||||||
&format!("pub(crate) {} inside private module", descr),
|
|diag| {
|
||||||
|diag| {
|
diag.span_suggestion(
|
||||||
diag.span_suggestion(
|
item.vis.span,
|
||||||
item.vis.span,
|
"consider using",
|
||||||
"consider using",
|
"pub".to_string(),
|
||||||
"pub".to_string(),
|
Applicability::MachineApplicable,
|
||||||
Applicability::MachineApplicable,
|
);
|
||||||
);
|
},
|
||||||
},
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for RepeatOnce {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let ExprKind::MethodCall(path, _, [receiver, count], _) = &expr.kind;
|
if let ExprKind::MethodCall(path, _, [receiver, count], _) = &expr.kind;
|
||||||
if path.ident.name == sym!(repeat);
|
if path.ident.name == sym!(repeat);
|
||||||
if let Some(Constant::Int(1)) = constant_context(cx, cx.typeck_results()).expr(count);
|
if constant_context(cx, cx.typeck_results()).expr(count) == Some(Constant::Int(1));
|
||||||
if !in_macro(receiver.span);
|
if !in_macro(receiver.span);
|
||||||
then {
|
then {
|
||||||
let ty = cx.typeck_results().expr_ty(receiver).peel_refs();
|
let ty = cx.typeck_results().expr_ty(receiver).peel_refs();
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_note;
|
||||||
use clippy_utils::source::snippet;
|
use clippy_utils::source::snippet;
|
||||||
use clippy_utils::{contains_name, higher, iter_input_pats};
|
use clippy_utils::visitors::is_local_used;
|
||||||
use rustc_hir::intravisit::FnKind;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_hir::{
|
use rustc_hir::def::Res;
|
||||||
Block, Body, Expr, ExprKind, FnDecl, Guard, HirId, Local, MutTy, Pat, PatKind, Path, QPath, StmtKind, Ty, TyKind,
|
use rustc_hir::def_id::LocalDefId;
|
||||||
UnOp,
|
use rustc_hir::hir_id::ItemLocalId;
|
||||||
};
|
use rustc_hir::{Block, Body, BodyOwnerKind, Expr, ExprKind, HirId, Node, Pat, PatKind, QPath, UnOp};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||||
use rustc_middle::ty;
|
use rustc_span::{Span, Symbol};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
|
||||||
use rustc_span::source_map::Span;
|
|
||||||
use rustc_span::symbol::Symbol;
|
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
|
@ -23,10 +20,6 @@ declare_clippy_lint! {
|
||||||
/// code. Still, some may opt to avoid it in their code base, they can set this
|
/// code. Still, some may opt to avoid it in their code base, they can set this
|
||||||
/// lint to `Warn`.
|
/// lint to `Warn`.
|
||||||
///
|
///
|
||||||
/// ### Known problems
|
|
||||||
/// This lint, as the other shadowing related lints,
|
|
||||||
/// currently only catches very simple patterns.
|
|
||||||
///
|
|
||||||
/// ### Example
|
/// ### Example
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # let x = 1;
|
/// # let x = 1;
|
||||||
|
@ -52,10 +45,6 @@ declare_clippy_lint! {
|
||||||
/// because a value may be bound to different things depending on position in
|
/// because a value may be bound to different things depending on position in
|
||||||
/// the code.
|
/// the code.
|
||||||
///
|
///
|
||||||
/// ### Known problems
|
|
||||||
/// This lint, as the other shadowing related lints,
|
|
||||||
/// currently only catches very simple patterns.
|
|
||||||
///
|
|
||||||
/// ### Example
|
/// ### Example
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let x = 2;
|
/// let x = 2;
|
||||||
|
@ -83,12 +72,6 @@ declare_clippy_lint! {
|
||||||
/// any place in the code. This can be alleviated by either giving more specific
|
/// any place in the code. This can be alleviated by either giving more specific
|
||||||
/// names to bindings or introducing more scopes to contain the bindings.
|
/// names to bindings or introducing more scopes to contain the bindings.
|
||||||
///
|
///
|
||||||
/// ### Known problems
|
|
||||||
/// This lint, as the other shadowing related lints,
|
|
||||||
/// currently only catches very simple patterns. Note that
|
|
||||||
/// `allow`/`warn`/`deny`/`forbid` attributes only work on the function level
|
|
||||||
/// for this lint.
|
|
||||||
///
|
|
||||||
/// ### Example
|
/// ### Example
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # let y = 1;
|
/// # let y = 1;
|
||||||
|
@ -102,307 +85,151 @@ declare_clippy_lint! {
|
||||||
/// let w = z; // use different variable name
|
/// let w = z; // use different variable name
|
||||||
/// ```
|
/// ```
|
||||||
pub SHADOW_UNRELATED,
|
pub SHADOW_UNRELATED,
|
||||||
pedantic,
|
restriction,
|
||||||
"rebinding a name without even using the original value"
|
"rebinding a name without even using the original value"
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_lint_pass!(Shadow => [SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED]);
|
#[derive(Default)]
|
||||||
|
pub(crate) struct Shadow {
|
||||||
|
bindings: Vec<FxHashMap<Symbol, Vec<ItemLocalId>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_lint_pass!(Shadow => [SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED]);
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for Shadow {
|
impl<'tcx> LateLintPass<'tcx> for Shadow {
|
||||||
fn check_fn(
|
fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
|
||||||
&mut self,
|
let (id, ident) = match pat.kind {
|
||||||
cx: &LateContext<'tcx>,
|
PatKind::Binding(_, hir_id, ident, _) => (hir_id, ident),
|
||||||
_: FnKind<'tcx>,
|
_ => return,
|
||||||
decl: &'tcx FnDecl<'_>,
|
};
|
||||||
body: &'tcx Body<'_>,
|
if ident.span.from_expansion() || ident.span.is_dummy() {
|
||||||
_: Span,
|
|
||||||
_: HirId,
|
|
||||||
) {
|
|
||||||
if in_external_macro(cx.sess(), body.value.span) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
check_fn(cx, decl, body);
|
let HirId { owner, local_id } = id;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_fn<'tcx>(cx: &LateContext<'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Body<'_>) {
|
// get (or insert) the list of items for this owner and symbol
|
||||||
let mut bindings = Vec::with_capacity(decl.inputs.len());
|
let data = self.bindings.last_mut().unwrap();
|
||||||
for arg in iter_input_pats(decl, body) {
|
let items_with_name = data.entry(ident.name).or_default();
|
||||||
if let PatKind::Binding(.., ident, _) = arg.pat.kind {
|
|
||||||
bindings.push((ident.name, ident.span));
|
// check other bindings with the same name, most recently seen first
|
||||||
|
for &prev in items_with_name.iter().rev() {
|
||||||
|
if prev == local_id {
|
||||||
|
// repeated binding in an `Or` pattern
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_shadow(cx, owner, prev, local_id) {
|
||||||
|
let prev_hir_id = HirId { owner, local_id: prev };
|
||||||
|
lint_shadow(cx, pat, prev_hir_id, ident.span);
|
||||||
|
// only lint against the "nearest" shadowed binding
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// store the binding
|
||||||
|
items_with_name.push(local_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_body(&mut self, cx: &LateContext<'_>, body: &Body<'_>) {
|
||||||
|
let hir = cx.tcx.hir();
|
||||||
|
if !matches!(hir.body_owner_kind(hir.body_owner(body.id())), BodyOwnerKind::Closure) {
|
||||||
|
self.bindings.push(FxHashMap::default());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
check_expr(cx, &body.value, &mut bindings);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'_>, bindings: &mut Vec<(Symbol, Span)>) {
|
fn check_body_post(&mut self, cx: &LateContext<'_>, body: &Body<'_>) {
|
||||||
let len = bindings.len();
|
let hir = cx.tcx.hir();
|
||||||
for stmt in block.stmts {
|
if !matches!(hir.body_owner_kind(hir.body_owner(body.id())), BodyOwnerKind::Closure) {
|
||||||
match stmt.kind {
|
self.bindings.pop();
|
||||||
StmtKind::Local(local) => check_local(cx, local, bindings),
|
|
||||||
StmtKind::Expr(e) | StmtKind::Semi(e) => check_expr(cx, e, bindings),
|
|
||||||
StmtKind::Item(..) => {},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(o) = block.expr {
|
|
||||||
check_expr(cx, o, bindings);
|
|
||||||
}
|
|
||||||
bindings.truncate(len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: &mut Vec<(Symbol, Span)>) {
|
fn is_shadow(cx: &LateContext<'_>, owner: LocalDefId, first: ItemLocalId, second: ItemLocalId) -> bool {
|
||||||
if in_external_macro(cx.sess(), local.span) {
|
let scope_tree = cx.tcx.region_scope_tree(owner.to_def_id());
|
||||||
return;
|
let first_scope = scope_tree.var_scope(first);
|
||||||
}
|
let second_scope = scope_tree.var_scope(second);
|
||||||
if higher::is_from_for_desugar(local) {
|
scope_tree.is_subscope_of(second_scope, first_scope)
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
let Local {
|
fn lint_shadow(cx: &LateContext<'_>, pat: &Pat<'_>, shadowed: HirId, span: Span) {
|
||||||
pat,
|
let (lint, msg) = match find_init(cx, pat.hir_id) {
|
||||||
ref ty,
|
Some(expr) if is_self_shadow(cx, pat, expr, shadowed) => {
|
||||||
ref init,
|
let msg = format!(
|
||||||
|
"`{}` is shadowed by itself in `{}`",
|
||||||
|
snippet(cx, pat.span, "_"),
|
||||||
|
snippet(cx, expr.span, "..")
|
||||||
|
);
|
||||||
|
(SHADOW_SAME, msg)
|
||||||
|
},
|
||||||
|
Some(expr) if is_local_used(cx, expr, shadowed) => {
|
||||||
|
let msg = format!(
|
||||||
|
"`{}` is shadowed by `{}` which reuses the original value",
|
||||||
|
snippet(cx, pat.span, "_"),
|
||||||
|
snippet(cx, expr.span, "..")
|
||||||
|
);
|
||||||
|
(SHADOW_REUSE, msg)
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
let msg = format!("`{}` shadows a previous, unrelated binding", snippet(cx, pat.span, "_"));
|
||||||
|
(SHADOW_UNRELATED, msg)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
span_lint_and_note(
|
||||||
|
cx,
|
||||||
|
lint,
|
||||||
span,
|
span,
|
||||||
..
|
&msg,
|
||||||
} = *local;
|
Some(cx.tcx.hir().span(shadowed)),
|
||||||
if let Some(t) = *ty {
|
"previous binding is here",
|
||||||
check_ty(cx, t, bindings);
|
);
|
||||||
}
|
|
||||||
if let Some(o) = *init {
|
|
||||||
check_expr(cx, o, bindings);
|
|
||||||
check_pat(cx, pat, Some(o), span, bindings);
|
|
||||||
} else {
|
|
||||||
check_pat(cx, pat, None, span, bindings);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_binding(cx: &LateContext<'_>, pat_id: HirId) -> bool {
|
/// Returns true if the expression is a simple transformation of a local binding such as `&x`
|
||||||
let var_ty = cx.typeck_results().node_type_opt(pat_id);
|
fn is_self_shadow(cx: &LateContext<'_>, pat: &Pat<'_>, mut expr: &Expr<'_>, hir_id: HirId) -> bool {
|
||||||
var_ty.map_or(false, |var_ty| !matches!(var_ty.kind(), ty::Adt(..)))
|
let hir = cx.tcx.hir();
|
||||||
}
|
let is_direct_binding = hir
|
||||||
|
.parent_iter(pat.hir_id)
|
||||||
fn check_pat<'tcx>(
|
.map_while(|(_id, node)| match node {
|
||||||
cx: &LateContext<'tcx>,
|
Node::Pat(pat) => Some(pat),
|
||||||
pat: &'tcx Pat<'_>,
|
_ => None,
|
||||||
init: Option<&'tcx Expr<'_>>,
|
})
|
||||||
span: Span,
|
.all(|pat| matches!(pat.kind, PatKind::Ref(..) | PatKind::Or(_)));
|
||||||
bindings: &mut Vec<(Symbol, Span)>,
|
if !is_direct_binding {
|
||||||
) {
|
return false;
|
||||||
// TODO: match more stuff / destructuring
|
|
||||||
match pat.kind {
|
|
||||||
PatKind::Binding(.., ident, ref inner) => {
|
|
||||||
let name = ident.name;
|
|
||||||
if is_binding(cx, pat.hir_id) {
|
|
||||||
let mut new_binding = true;
|
|
||||||
for tup in bindings.iter_mut() {
|
|
||||||
if tup.0 == name {
|
|
||||||
lint_shadow(cx, name, span, pat.span, init, tup.1);
|
|
||||||
tup.1 = ident.span;
|
|
||||||
new_binding = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if new_binding {
|
|
||||||
bindings.push((name, ident.span));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(p) = *inner {
|
|
||||||
check_pat(cx, p, init, span, bindings);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
PatKind::Struct(_, pfields, _) => {
|
|
||||||
if let Some(init_struct) = init {
|
|
||||||
if let ExprKind::Struct(_, efields, _) = init_struct.kind {
|
|
||||||
for field in pfields {
|
|
||||||
let name = field.ident.name;
|
|
||||||
let efield = efields
|
|
||||||
.iter()
|
|
||||||
.find_map(|f| if f.ident.name == name { Some(&*f.expr) } else { None });
|
|
||||||
check_pat(cx, field.pat, efield, span, bindings);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for field in pfields {
|
|
||||||
check_pat(cx, field.pat, init, span, bindings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for field in pfields {
|
|
||||||
check_pat(cx, field.pat, None, span, bindings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
PatKind::Tuple(inner, _) => {
|
|
||||||
if let Some(init_tup) = init {
|
|
||||||
if let ExprKind::Tup(tup) = init_tup.kind {
|
|
||||||
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, None, span, bindings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
PatKind::Box(inner) => {
|
|
||||||
if let Some(initp) = init {
|
|
||||||
if let ExprKind::Box(inner_init) = initp.kind {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
PatKind::Ref(inner, _) => check_pat(cx, inner, init, span, bindings),
|
|
||||||
// PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>),
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
}
|
loop {
|
||||||
|
expr = match expr.kind {
|
||||||
fn lint_shadow<'tcx>(
|
ExprKind::Box(e)
|
||||||
cx: &LateContext<'tcx>,
|
| ExprKind::AddrOf(_, _, e)
|
||||||
name: Symbol,
|
| ExprKind::Block(
|
||||||
span: Span,
|
&Block {
|
||||||
pattern_span: Span,
|
stmts: [],
|
||||||
init: Option<&'tcx Expr<'_>>,
|
expr: Some(e),
|
||||||
prev_span: Span,
|
..
|
||||||
) {
|
|
||||||
if let Some(expr) = init {
|
|
||||||
if is_self_shadow(name, expr) {
|
|
||||||
span_lint_and_then(
|
|
||||||
cx,
|
|
||||||
SHADOW_SAME,
|
|
||||||
span,
|
|
||||||
&format!(
|
|
||||||
"`{}` is shadowed by itself in `{}`",
|
|
||||||
snippet(cx, pattern_span, "_"),
|
|
||||||
snippet(cx, expr.span, "..")
|
|
||||||
),
|
|
||||||
|diag| {
|
|
||||||
diag.span_note(prev_span, "previous binding is here");
|
|
||||||
},
|
},
|
||||||
);
|
_,
|
||||||
} else if contains_name(name, expr) {
|
)
|
||||||
span_lint_and_then(
|
| ExprKind::Unary(UnOp::Deref, e) => e,
|
||||||
cx,
|
ExprKind::Path(QPath::Resolved(None, path)) => break path.res == Res::Local(hir_id),
|
||||||
SHADOW_REUSE,
|
_ => break false,
|
||||||
pattern_span,
|
|
||||||
&format!(
|
|
||||||
"`{}` is shadowed by `{}` which reuses the original value",
|
|
||||||
snippet(cx, pattern_span, "_"),
|
|
||||||
snippet(cx, expr.span, "..")
|
|
||||||
),
|
|
||||||
|diag| {
|
|
||||||
diag.span_note(expr.span, "initialization happens here");
|
|
||||||
diag.span_note(prev_span, "previous binding is here");
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
span_lint_and_then(
|
|
||||||
cx,
|
|
||||||
SHADOW_UNRELATED,
|
|
||||||
pattern_span,
|
|
||||||
&format!("`{}` is being shadowed", snippet(cx, pattern_span, "_")),
|
|
||||||
|diag| {
|
|
||||||
diag.span_note(expr.span, "initialization happens here");
|
|
||||||
diag.span_note(prev_span, "previous binding is here");
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
span_lint_and_then(
|
}
|
||||||
cx,
|
|
||||||
SHADOW_UNRELATED,
|
/// Finds the "init" expression for a pattern: `let <pat> = <init>;` or
|
||||||
span,
|
/// `match <init> { .., <pat> => .., .. }`
|
||||||
&format!("`{}` shadows a previous declaration", snippet(cx, pattern_span, "_")),
|
fn find_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> {
|
||||||
|diag| {
|
for (_, node) in cx.tcx.hir().parent_iter(hir_id) {
|
||||||
diag.span_note(prev_span, "previous binding is here");
|
let init = match node {
|
||||||
|
Node::Arm(_) | Node::Pat(_) => continue,
|
||||||
|
Node::Expr(expr) => match expr.kind {
|
||||||
|
ExprKind::Match(e, _, _) => Some(e),
|
||||||
|
_ => None,
|
||||||
},
|
},
|
||||||
);
|
Node::Local(local) => local.init,
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
return init;
|
||||||
}
|
}
|
||||||
}
|
None
|
||||||
|
|
||||||
fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut Vec<(Symbol, Span)>) {
|
|
||||||
if in_external_macro(cx.sess(), expr.span) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
match expr.kind {
|
|
||||||
ExprKind::Unary(_, e) | ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) | ExprKind::Box(e) => {
|
|
||||||
check_expr(cx, e, bindings);
|
|
||||||
},
|
|
||||||
ExprKind::Block(block, _) | ExprKind::Loop(block, ..) => check_block(cx, block, bindings),
|
|
||||||
// ExprKind::Call
|
|
||||||
// ExprKind::MethodCall
|
|
||||||
ExprKind::Array(v) | ExprKind::Tup(v) => {
|
|
||||||
for e in v {
|
|
||||||
check_expr(cx, e, bindings);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ExprKind::If(cond, then, ref otherwise) => {
|
|
||||||
check_expr(cx, cond, bindings);
|
|
||||||
check_expr(cx, then, bindings);
|
|
||||||
if let Some(o) = *otherwise {
|
|
||||||
check_expr(cx, o, bindings);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ExprKind::Match(init, arms, _) => {
|
|
||||||
check_expr(cx, init, bindings);
|
|
||||||
let len = bindings.len();
|
|
||||||
for arm in arms {
|
|
||||||
check_pat(cx, arm.pat, Some(init), arm.pat.span, bindings);
|
|
||||||
// This is ugly, but needed to get the right type
|
|
||||||
if let Some(ref guard) = arm.guard {
|
|
||||||
match guard {
|
|
||||||
Guard::If(if_expr) => check_expr(cx, if_expr, bindings),
|
|
||||||
Guard::IfLet(guard_pat, guard_expr) => {
|
|
||||||
check_pat(cx, guard_pat, Some(*guard_expr), guard_pat.span, bindings);
|
|
||||||
check_expr(cx, guard_expr, bindings);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
check_expr(cx, arm.body, bindings);
|
|
||||||
bindings.truncate(len);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<(Symbol, Span)>) {
|
|
||||||
match ty.kind {
|
|
||||||
TyKind::Slice(sty) => check_ty(cx, sty, bindings),
|
|
||||||
TyKind::Array(fty, ref anon_const) => {
|
|
||||||
check_ty(cx, fty, bindings);
|
|
||||||
check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings);
|
|
||||||
},
|
|
||||||
TyKind::Ptr(MutTy { ty: mty, .. }) | TyKind::Rptr(_, MutTy { ty: mty, .. }) => check_ty(cx, mty, bindings),
|
|
||||||
TyKind::Tup(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),
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_self_shadow(name: Symbol, expr: &Expr<'_>) -> bool {
|
|
||||||
match expr.kind {
|
|
||||||
ExprKind::Box(inner) | ExprKind::AddrOf(_, _, inner) => is_self_shadow(name, inner),
|
|
||||||
ExprKind::Block(block, _) => {
|
|
||||||
block.stmts.is_empty() && block.expr.as_ref().map_or(false, |e| is_self_shadow(name, e))
|
|
||||||
},
|
|
||||||
ExprKind::Unary(op, inner) => (UnOp::Deref == op) && is_self_shadow(name, inner),
|
|
||||||
ExprKind::Path(QPath::Resolved(_, path)) => path_eq_name(name, path),
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn path_eq_name(name: Symbol, path: &Path<'_>) -> bool {
|
|
||||||
!path.is_global() && path.segments.len() == 1 && path.segments[0].ident.name == name
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,8 +49,8 @@ impl<'tcx> LateLintPass<'tcx> for TransmutingNull {
|
||||||
let mut const_eval_context = constant_context(cx, cx.typeck_results());
|
let mut const_eval_context = constant_context(cx, cx.typeck_results());
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let ExprKind::Path(ref _qpath) = arg.kind;
|
if let ExprKind::Path(ref _qpath) = arg.kind;
|
||||||
let x = const_eval_context.expr(arg);
|
if let Some(Constant::RawPtr(x)) = const_eval_context.expr(arg);
|
||||||
if let Some(Constant::RawPtr(0)) = x;
|
if x == 0;
|
||||||
then {
|
then {
|
||||||
span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG)
|
span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,7 @@ use rustc_span::symbol::sym;
|
||||||
use super::OPTION_OPTION;
|
use super::OPTION_OPTION;
|
||||||
|
|
||||||
pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
|
pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
|
||||||
if cx.tcx.is_diagnostic_item(sym::Option, def_id)
|
if cx.tcx.is_diagnostic_item(sym::Option, def_id) && is_ty_param_diagnostic_item(cx, qpath, sym::Option).is_some() {
|
||||||
&& is_ty_param_diagnostic_item(cx, qpath, sym::Option).is_some()
|
|
||||||
{
|
|
||||||
span_lint(
|
span_lint(
|
||||||
cx,
|
cx,
|
||||||
OPTION_OPTION,
|
OPTION_OPTION,
|
||||||
|
|
|
@ -284,6 +284,10 @@ define_Conf! {
|
||||||
///
|
///
|
||||||
/// The list of unicode scripts allowed to be used in the scope.
|
/// The list of unicode scripts allowed to be used in the scope.
|
||||||
(allowed_scripts: Vec<String> = vec!["Latin".to_string()]),
|
(allowed_scripts: Vec<String> = vec!["Latin".to_string()]),
|
||||||
|
/// Lint: NON_SEND_FIELDS_IN_SEND_TY.
|
||||||
|
///
|
||||||
|
/// Whether to apply the raw pointer heuristic to determine if a type is `Send`.
|
||||||
|
(enable_raw_pointer_heuristic_for_send: bool = true),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Search for the configuration file.
|
/// Search for the configuration file.
|
||||||
|
|
|
@ -8,7 +8,7 @@ use clippy_utils::{
|
||||||
paths, SpanlessEq,
|
paths, SpanlessEq,
|
||||||
};
|
};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_ast::ast::{Crate as AstCrate, ItemKind, LitKind, ModKind, NodeId};
|
use rustc_ast::ast::{Crate, ItemKind, LitKind, ModKind, NodeId};
|
||||||
use rustc_ast::visit::FnKind;
|
use rustc_ast::visit::FnKind;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
|
@ -18,8 +18,8 @@ use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::hir_id::CRATE_HIR_ID;
|
use rustc_hir::hir_id::CRATE_HIR_ID;
|
||||||
use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
|
use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
BinOpKind, Block, Crate, Expr, ExprKind, HirId, Item, Local, MutTy, Mutability, Node, Path, Stmt, StmtKind, Ty,
|
BinOpKind, Block, Expr, ExprKind, HirId, Item, Local, MutTy, Mutability, Node, Path, Stmt, StmtKind, Ty, TyKind,
|
||||||
TyKind, UnOp,
|
UnOp,
|
||||||
};
|
};
|
||||||
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
|
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
|
||||||
use rustc_middle::hir::map::Map;
|
use rustc_middle::hir::map::Map;
|
||||||
|
@ -317,7 +317,7 @@ declare_clippy_lint! {
|
||||||
declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]);
|
declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]);
|
||||||
|
|
||||||
impl EarlyLintPass for ClippyLintsInternal {
|
impl EarlyLintPass for ClippyLintsInternal {
|
||||||
fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &AstCrate) {
|
fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) {
|
||||||
if let Some(utils) = krate.items.iter().find(|item| item.ident.name.as_str() == "utils") {
|
if let Some(utils) = krate.items.iter().find(|item| item.ident.name.as_str() == "utils") {
|
||||||
if let ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) = utils.kind {
|
if let ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) = utils.kind {
|
||||||
if let Some(paths) = items.iter().find(|item| item.ident.name.as_str() == "paths") {
|
if let Some(paths) = items.iter().find(|item| item.ident.name.as_str() == "paths") {
|
||||||
|
@ -412,7 +412,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_crate_post(&mut self, cx: &LateContext<'tcx>, _: &'tcx Crate<'_>) {
|
fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
|
||||||
if is_lint_allowed(cx, LINT_WITHOUT_LINT_PASS, CRATE_HIR_ID) {
|
if is_lint_allowed(cx, LINT_WITHOUT_LINT_PASS, CRATE_HIR_ID) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -907,7 +907,7 @@ pub struct InterningDefinedSymbol {
|
||||||
impl_lint_pass!(InterningDefinedSymbol => [INTERNING_DEFINED_SYMBOL, UNNECESSARY_SYMBOL_STR]);
|
impl_lint_pass!(InterningDefinedSymbol => [INTERNING_DEFINED_SYMBOL, UNNECESSARY_SYMBOL_STR]);
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
|
impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
|
||||||
fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) {
|
fn check_crate(&mut self, cx: &LateContext<'_>) {
|
||||||
if !self.symbol_map.is_empty() {
|
if !self.symbol_map.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ impl<'tcx> LateLintPass<'tcx> for ZeroDiv {
|
||||||
// check for instances of 0.0/0.0
|
// check for instances of 0.0/0.0
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let ExprKind::Binary(ref op, left, right) = expr.kind;
|
if let ExprKind::Binary(ref op, left, right) = expr.kind;
|
||||||
if let BinOpKind::Div = op.node;
|
if op.node == BinOpKind::Div;
|
||||||
// TODO - constant_simple does not fold many operations involving floats.
|
// TODO - constant_simple does not fold many operations involving floats.
|
||||||
// That's probably fine for this lint - it's pretty unlikely that someone would
|
// That's probably fine for this lint - it's pretty unlikely that someone would
|
||||||
// do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too.
|
// do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too.
|
||||||
|
|
|
@ -509,7 +509,6 @@ pub fn path_to_local_id(expr: &Expr<'_>, id: HirId) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the definition associated to a path.
|
/// Gets the definition associated to a path.
|
||||||
#[allow(clippy::shadow_unrelated)] // false positive #6563
|
|
||||||
pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
|
pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
|
||||||
macro_rules! try_res {
|
macro_rules! try_res {
|
||||||
($e:expr) => {
|
($e:expr) => {
|
||||||
|
@ -683,7 +682,17 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)),
|
ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)),
|
||||||
ExprKind::Repeat(x, _) => is_default_equivalent(cx, x),
|
ExprKind::Repeat(x, y) => if_chain! {
|
||||||
|
if let ExprKind::Lit(ref const_lit) = cx.tcx.hir().body(y.body).value.kind;
|
||||||
|
if let LitKind::Int(v, _) = const_lit.node;
|
||||||
|
if v <= 32 && is_default_equivalent(cx, x);
|
||||||
|
then {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
},
|
||||||
ExprKind::Call(repl_func, _) => if_chain! {
|
ExprKind::Call(repl_func, _) => if_chain! {
|
||||||
if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
|
if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
|
||||||
if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
|
if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
|
||||||
|
@ -1498,7 +1507,7 @@ pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tc
|
||||||
|
|
||||||
if let ExprKind::Match(_, arms, ref source) = expr.kind {
|
if let ExprKind::Match(_, arms, ref source) = expr.kind {
|
||||||
// desugared from a `?` operator
|
// desugared from a `?` operator
|
||||||
if let MatchSource::TryDesugar = *source {
|
if *source == MatchSource::TryDesugar {
|
||||||
return Some(expr);
|
return Some(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ impl<'a> NumericLiteral<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Grab part of the literal after prefix, if present.
|
// Grab part of the literal after prefix, if present.
|
||||||
let (prefix, mut sans_prefix) = if let Radix::Decimal = radix {
|
let (prefix, mut sans_prefix) = if radix == Radix::Decimal {
|
||||||
(None, lit)
|
(None, lit)
|
||||||
} else {
|
} else {
|
||||||
let (p, s) = lit.split_at(2);
|
let (p, s) = lit.split_at(2);
|
||||||
|
@ -157,8 +157,10 @@ impl<'a> NumericLiteral<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((separator, exponent)) = self.exponent {
|
if let Some((separator, exponent)) = self.exponent {
|
||||||
output.push_str(separator);
|
if exponent != "0" {
|
||||||
Self::group_digits(&mut output, exponent, group_size, true, false);
|
output.push_str(separator);
|
||||||
|
Self::group_digits(&mut output, exponent, group_size, true, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(suffix) = self.suffix {
|
if let Some(suffix) = self.suffix {
|
||||||
|
@ -177,6 +179,13 @@ impl<'a> NumericLiteral<'a> {
|
||||||
|
|
||||||
let mut digits = input.chars().filter(|&c| c != '_');
|
let mut digits = input.chars().filter(|&c| c != '_');
|
||||||
|
|
||||||
|
// The exponent may have a sign, output it early, otherwise it will be
|
||||||
|
// treated as a digit
|
||||||
|
if digits.clone().next() == Some('-') {
|
||||||
|
let _ = digits.next();
|
||||||
|
output.push('-');
|
||||||
|
}
|
||||||
|
|
||||||
let first_group_size;
|
let first_group_size;
|
||||||
|
|
||||||
if partial_group_first {
|
if partial_group_first {
|
||||||
|
|
|
@ -129,11 +129,17 @@ pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"];
|
||||||
pub const RC_PTR_EQ: [&str; 4] = ["alloc", "rc", "Rc", "ptr_eq"];
|
pub const RC_PTR_EQ: [&str; 4] = ["alloc", "rc", "Rc", "ptr_eq"];
|
||||||
pub const REFCELL_REF: [&str; 3] = ["core", "cell", "Ref"];
|
pub const REFCELL_REF: [&str; 3] = ["core", "cell", "Ref"];
|
||||||
pub const REFCELL_REFMUT: [&str; 3] = ["core", "cell", "RefMut"];
|
pub const REFCELL_REFMUT: [&str; 3] = ["core", "cell", "RefMut"];
|
||||||
|
#[allow(clippy::invalid_paths)] // internal lints do not know about all external crates
|
||||||
pub const REGEX_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"];
|
pub const REGEX_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"];
|
||||||
|
#[allow(clippy::invalid_paths)] // internal lints do not know about all external crates
|
||||||
pub const REGEX_BYTES_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "bytes", "RegexBuilder", "new"];
|
pub const REGEX_BYTES_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "bytes", "RegexBuilder", "new"];
|
||||||
|
#[allow(clippy::invalid_paths)] // internal lints do not know about all external crates
|
||||||
pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "re_bytes", "Regex", "new"];
|
pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "re_bytes", "Regex", "new"];
|
||||||
|
#[allow(clippy::invalid_paths)] // internal lints do not know about all external crates
|
||||||
pub const REGEX_BYTES_SET_NEW: [&str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"];
|
pub const REGEX_BYTES_SET_NEW: [&str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"];
|
||||||
|
#[allow(clippy::invalid_paths)] // internal lints do not know about all external crates
|
||||||
pub const REGEX_NEW: [&str; 4] = ["regex", "re_unicode", "Regex", "new"];
|
pub const REGEX_NEW: [&str; 4] = ["regex", "re_unicode", "Regex", "new"];
|
||||||
|
#[allow(clippy::invalid_paths)] // internal lints do not know about all external crates
|
||||||
pub const REGEX_SET_NEW: [&str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"];
|
pub const REGEX_SET_NEW: [&str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"];
|
||||||
/// Preferably use the diagnostic item `sym::Result` where possible
|
/// Preferably use the diagnostic item `sym::Result` where possible
|
||||||
pub const RESULT: [&str; 3] = ["core", "result", "Result"];
|
pub const RESULT: [&str; 3] = ["core", "result", "Result"];
|
||||||
|
|
|
@ -311,7 +311,7 @@ impl<'a> Sugg<'a> {
|
||||||
/// Return `true` if `sugg` is enclosed in parenthesis.
|
/// Return `true` if `sugg` is enclosed in parenthesis.
|
||||||
fn has_enclosing_paren(sugg: impl AsRef<str>) -> bool {
|
fn has_enclosing_paren(sugg: impl AsRef<str>) -> bool {
|
||||||
let mut chars = sugg.as_ref().chars();
|
let mut chars = sugg.as_ref().chars();
|
||||||
if let Some('(') = chars.next() {
|
if chars.next() == Some('(') {
|
||||||
let mut depth = 1;
|
let mut depth = 1;
|
||||||
for c in &mut chars {
|
for c in &mut chars {
|
||||||
if c == '(' {
|
if c == '(' {
|
||||||
|
|
|
@ -224,15 +224,15 @@ fn is_normalizable_helper<'tcx>(
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true iff the given type is a non aggregate primitive (a bool or char, any integer or
|
/// Returns `true` if the given type is a non aggregate primitive (a `bool` or `char`, any
|
||||||
/// floating-point number type). For checking aggregation of primitive types (e.g. tuples and slices
|
/// integer or floating-point number type). For checking aggregation of primitive types (e.g.
|
||||||
/// of primitive type) see `is_recursively_primitive_type`
|
/// tuples and slices of primitive type) see `is_recursively_primitive_type`
|
||||||
pub fn is_non_aggregate_primitive_type(ty: Ty<'_>) -> bool {
|
pub fn is_non_aggregate_primitive_type(ty: Ty<'_>) -> bool {
|
||||||
matches!(ty.kind(), ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_))
|
matches!(ty.kind(), ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true iff the given type is a primitive (a bool or char, any integer or floating-point
|
/// Returns `true` if the given type is a primitive (a `bool` or `char`, any integer or
|
||||||
/// number type, a str, or an array, slice, or tuple of those types).
|
/// floating-point number type, a `str`, or an array, slice, or tuple of those types).
|
||||||
pub fn is_recursively_primitive_type(ty: Ty<'_>) -> bool {
|
pub fn is_recursively_primitive_type(ty: Ty<'_>) -> bool {
|
||||||
match ty.kind() {
|
match ty.kind() {
|
||||||
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => true,
|
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => true,
|
||||||
|
|
|
@ -65,7 +65,7 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate {
|
||||||
fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
||||||
|
|
||||||
fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, bk: ty::BorrowKind) {
|
fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, bk: ty::BorrowKind) {
|
||||||
if let ty::BorrowKind::MutBorrow = bk {
|
if bk == ty::BorrowKind::MutBorrow {
|
||||||
self.update(cmt);
|
self.update(cmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly-2021-09-28"
|
channel = "nightly-2021-10-07"
|
||||||
components = ["llvm-tools-preview", "rustc-dev", "rust-src"]
|
components = ["llvm-tools-preview", "rustc-dev", "rust-src"]
|
||||||
|
|
|
@ -92,7 +92,9 @@ fn extern_flags() -> String {
|
||||||
.collect();
|
.collect();
|
||||||
assert!(
|
assert!(
|
||||||
not_found.is_empty(),
|
not_found.is_empty(),
|
||||||
"dependencies not found in depinfo: {:?}",
|
"dependencies not found in depinfo: {:?}\n\
|
||||||
|
help: Make sure the `-Z binary-dep-depinfo` rust flag is enabled\n\
|
||||||
|
help: Try adding to dev-dependencies in Cargo.toml",
|
||||||
not_found
|
not_found
|
||||||
);
|
);
|
||||||
crates
|
crates
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
enable-raw-pointer-heuristic-for-send = false
|
43
tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs
Normal file
43
tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#![warn(clippy::non_send_fields_in_send_ty)]
|
||||||
|
#![feature(extern_types)]
|
||||||
|
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
// Basic tests should not be affected
|
||||||
|
pub struct NoGeneric {
|
||||||
|
rc_is_not_send: Rc<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for NoGeneric {}
|
||||||
|
|
||||||
|
pub struct MultiField<T> {
|
||||||
|
field1: T,
|
||||||
|
field2: T,
|
||||||
|
field3: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<T> Send for MultiField<T> {}
|
||||||
|
|
||||||
|
pub enum MyOption<T> {
|
||||||
|
MySome(T),
|
||||||
|
MyNone,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<T> Send for MyOption<T> {}
|
||||||
|
|
||||||
|
// All fields are disallowed when raw pointer heuristic is off
|
||||||
|
extern "C" {
|
||||||
|
type NonSend;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HeuristicTest {
|
||||||
|
field1: Vec<*const NonSend>,
|
||||||
|
field2: [*const NonSend; 3],
|
||||||
|
field3: (*const NonSend, *const NonSend, *const NonSend),
|
||||||
|
field4: (*const NonSend, Rc<u8>),
|
||||||
|
field5: Vec<Vec<*const NonSend>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for HeuristicTest {}
|
||||||
|
|
||||||
|
fn main() {}
|
91
tests/ui-toml/strict_non_send_fields_in_send_ty/test.stderr
Normal file
91
tests/ui-toml/strict_non_send_fields_in_send_ty/test.stderr
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
error: this implementation is unsound, as some fields in `NoGeneric` are `!Send`
|
||||||
|
--> $DIR/test.rs:11:1
|
||||||
|
|
|
||||||
|
LL | unsafe impl Send for NoGeneric {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `-D clippy::non-send-fields-in-send-ty` implied by `-D warnings`
|
||||||
|
note: the type of field `rc_is_not_send` is `!Send`
|
||||||
|
--> $DIR/test.rs:8:5
|
||||||
|
|
|
||||||
|
LL | rc_is_not_send: Rc<String>,
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= help: use a thread-safe type that implements `Send`
|
||||||
|
|
||||||
|
error: this implementation is unsound, as some fields in `MultiField<T>` are `!Send`
|
||||||
|
--> $DIR/test.rs:19:1
|
||||||
|
|
|
||||||
|
LL | unsafe impl<T> Send for MultiField<T> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: the type of field `field1` is `!Send`
|
||||||
|
--> $DIR/test.rs:14:5
|
||||||
|
|
|
||||||
|
LL | field1: T,
|
||||||
|
| ^^^^^^^^^
|
||||||
|
= help: add `T: Send` bound in `Send` impl
|
||||||
|
note: the type of field `field2` is `!Send`
|
||||||
|
--> $DIR/test.rs:15:5
|
||||||
|
|
|
||||||
|
LL | field2: T,
|
||||||
|
| ^^^^^^^^^
|
||||||
|
= help: add `T: Send` bound in `Send` impl
|
||||||
|
note: the type of field `field3` is `!Send`
|
||||||
|
--> $DIR/test.rs:16:5
|
||||||
|
|
|
||||||
|
LL | field3: T,
|
||||||
|
| ^^^^^^^^^
|
||||||
|
= help: add `T: Send` bound in `Send` impl
|
||||||
|
|
||||||
|
error: this implementation is unsound, as some fields in `MyOption<T>` are `!Send`
|
||||||
|
--> $DIR/test.rs:26:1
|
||||||
|
|
|
||||||
|
LL | unsafe impl<T> Send for MyOption<T> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: the type of field `0` is `!Send`
|
||||||
|
--> $DIR/test.rs:22:12
|
||||||
|
|
|
||||||
|
LL | MySome(T),
|
||||||
|
| ^
|
||||||
|
= help: add `T: Send` bound in `Send` impl
|
||||||
|
|
||||||
|
error: this implementation is unsound, as some fields in `HeuristicTest` are `!Send`
|
||||||
|
--> $DIR/test.rs:41:1
|
||||||
|
|
|
||||||
|
LL | unsafe impl Send for HeuristicTest {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: the type of field `field1` is `!Send`
|
||||||
|
--> $DIR/test.rs:34:5
|
||||||
|
|
|
||||||
|
LL | field1: Vec<*const NonSend>,
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= help: use a thread-safe type that implements `Send`
|
||||||
|
note: the type of field `field2` is `!Send`
|
||||||
|
--> $DIR/test.rs:35:5
|
||||||
|
|
|
||||||
|
LL | field2: [*const NonSend; 3],
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= help: use a thread-safe type that implements `Send`
|
||||||
|
note: the type of field `field3` is `!Send`
|
||||||
|
--> $DIR/test.rs:36:5
|
||||||
|
|
|
||||||
|
LL | field3: (*const NonSend, *const NonSend, *const NonSend),
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= help: use a thread-safe type that implements `Send`
|
||||||
|
note: the type of field `field4` is `!Send`
|
||||||
|
--> $DIR/test.rs:37:5
|
||||||
|
|
|
||||||
|
LL | field4: (*const NonSend, Rc<u8>),
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= help: use a thread-safe type that implements `Send`
|
||||||
|
note: the type of field `field5` is `!Send`
|
||||||
|
--> $DIR/test.rs:38:5
|
||||||
|
|
|
||||||
|
LL | field5: Vec<Vec<*const NonSend>>,
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= help: use a thread-safe type that implements `Send`
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `avoid-breaking-exported-api`, `msrv`, `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `disallowed-types`, `unreadable-literal-lint-fractions`, `upper-case-acronyms-aggressive`, `cargo-ignore-publish`, `standard-macro-braces`, `enforced-import-renames`, `allowed-scripts`, `third-party` at line 5 column 1
|
error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `avoid-breaking-exported-api`, `msrv`, `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `disallowed-types`, `unreadable-literal-lint-fractions`, `upper-case-acronyms-aggressive`, `cargo-ignore-publish`, `standard-macro-braces`, `enforced-import-renames`, `allowed-scripts`, `enable-raw-pointer-heuristic-for-send`, `third-party` at line 5 column 1
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#[warn(clippy::approx_constant)]
|
#[warn(clippy::approx_constant)]
|
||||||
#[allow(unused, clippy::shadow_unrelated, clippy::similar_names)]
|
#[allow(clippy::similar_names)]
|
||||||
fn main() {
|
fn main() {
|
||||||
let my_e = 2.7182;
|
let my_e = 2.7182;
|
||||||
let almost_e = 2.718;
|
let almost_e = 2.718;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code, clippy::equatable_if_let)]
|
||||||
#![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
|
#![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
|
||||||
|
|
||||||
// This tests the branches_sharing_code lint at the end of blocks
|
// This tests the branches_sharing_code lint at the end of blocks
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// run-rustfix
|
// run-rustfix
|
||||||
#![allow(clippy::assertions_on_constants)]
|
#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
#[warn(clippy::collapsible_if)]
|
#[warn(clippy::collapsible_if)]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// run-rustfix
|
// run-rustfix
|
||||||
#![allow(clippy::assertions_on_constants)]
|
#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
#[warn(clippy::collapsible_if)]
|
#[warn(clippy::collapsible_if)]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// run-rustfix
|
// run-rustfix
|
||||||
#![allow(clippy::assertions_on_constants)]
|
#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
#[warn(clippy::collapsible_if)]
|
#[warn(clippy::collapsible_if)]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// run-rustfix
|
// run-rustfix
|
||||||
#![allow(clippy::assertions_on_constants)]
|
#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
#[warn(clippy::collapsible_if)]
|
#[warn(clippy::collapsible_if)]
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
#![warn(clippy::collapsible_match)]
|
#![warn(clippy::collapsible_match)]
|
||||||
#![allow(clippy::needless_return, clippy::no_effect, clippy::single_match)]
|
#![allow(
|
||||||
|
clippy::needless_return,
|
||||||
|
clippy::no_effect,
|
||||||
|
clippy::single_match,
|
||||||
|
clippy::equatable_if_let
|
||||||
|
)]
|
||||||
|
|
||||||
fn lint_cases(opt_opt: Option<Option<u32>>, res_opt: Result<Option<u32>, String>) {
|
fn lint_cases(opt_opt: Option<Option<u32>>, res_opt: Result<Option<u32>, String>) {
|
||||||
// match without block
|
// match without block
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: this `match` can be collapsed into the outer `match`
|
error: this `match` can be collapsed into the outer `match`
|
||||||
--> $DIR/collapsible_match.rs:7:20
|
--> $DIR/collapsible_match.rs:12:20
|
||||||
|
|
|
|
||||||
LL | Ok(val) => match val {
|
LL | Ok(val) => match val {
|
||||||
| ____________________^
|
| ____________________^
|
||||||
|
@ -10,7 +10,7 @@ LL | | },
|
||||||
|
|
|
|
||||||
= note: `-D clippy::collapsible-match` implied by `-D warnings`
|
= note: `-D clippy::collapsible-match` implied by `-D warnings`
|
||||||
help: the outer pattern can be modified to include the inner pattern
|
help: the outer pattern can be modified to include the inner pattern
|
||||||
--> $DIR/collapsible_match.rs:7:12
|
--> $DIR/collapsible_match.rs:12:12
|
||||||
|
|
|
|
||||||
LL | Ok(val) => match val {
|
LL | Ok(val) => match val {
|
||||||
| ^^^ replace this binding
|
| ^^^ replace this binding
|
||||||
|
@ -18,7 +18,7 @@ LL | Some(n) => foo(n),
|
||||||
| ^^^^^^^ with this pattern
|
| ^^^^^^^ with this pattern
|
||||||
|
|
||||||
error: this `match` can be collapsed into the outer `match`
|
error: this `match` can be collapsed into the outer `match`
|
||||||
--> $DIR/collapsible_match.rs:16:20
|
--> $DIR/collapsible_match.rs:21:20
|
||||||
|
|
|
|
||||||
LL | Ok(val) => match val {
|
LL | Ok(val) => match val {
|
||||||
| ____________________^
|
| ____________________^
|
||||||
|
@ -28,7 +28,7 @@ LL | | },
|
||||||
| |_________^
|
| |_________^
|
||||||
|
|
|
|
||||||
help: the outer pattern can be modified to include the inner pattern
|
help: the outer pattern can be modified to include the inner pattern
|
||||||
--> $DIR/collapsible_match.rs:16:12
|
--> $DIR/collapsible_match.rs:21:12
|
||||||
|
|
|
|
||||||
LL | Ok(val) => match val {
|
LL | Ok(val) => match val {
|
||||||
| ^^^ replace this binding
|
| ^^^ replace this binding
|
||||||
|
@ -36,7 +36,7 @@ LL | Some(n) => foo(n),
|
||||||
| ^^^^^^^ with this pattern
|
| ^^^^^^^ with this pattern
|
||||||
|
|
||||||
error: this `if let` can be collapsed into the outer `if let`
|
error: this `if let` can be collapsed into the outer `if let`
|
||||||
--> $DIR/collapsible_match.rs:25:9
|
--> $DIR/collapsible_match.rs:30:9
|
||||||
|
|
|
|
||||||
LL | / if let Some(n) = val {
|
LL | / if let Some(n) = val {
|
||||||
LL | | take(n);
|
LL | | take(n);
|
||||||
|
@ -44,7 +44,7 @@ LL | | }
|
||||||
| |_________^
|
| |_________^
|
||||||
|
|
|
|
||||||
help: the outer pattern can be modified to include the inner pattern
|
help: the outer pattern can be modified to include the inner pattern
|
||||||
--> $DIR/collapsible_match.rs:24:15
|
--> $DIR/collapsible_match.rs:29:15
|
||||||
|
|
|
|
||||||
LL | if let Ok(val) = res_opt {
|
LL | if let Ok(val) = res_opt {
|
||||||
| ^^^ replace this binding
|
| ^^^ replace this binding
|
||||||
|
@ -52,7 +52,7 @@ LL | if let Some(n) = val {
|
||||||
| ^^^^^^^ with this pattern
|
| ^^^^^^^ with this pattern
|
||||||
|
|
||||||
error: this `if let` can be collapsed into the outer `if let`
|
error: this `if let` can be collapsed into the outer `if let`
|
||||||
--> $DIR/collapsible_match.rs:32:9
|
--> $DIR/collapsible_match.rs:37:9
|
||||||
|
|
|
|
||||||
LL | / if let Some(n) = val {
|
LL | / if let Some(n) = val {
|
||||||
LL | | take(n);
|
LL | | take(n);
|
||||||
|
@ -62,7 +62,7 @@ LL | | }
|
||||||
| |_________^
|
| |_________^
|
||||||
|
|
|
|
||||||
help: the outer pattern can be modified to include the inner pattern
|
help: the outer pattern can be modified to include the inner pattern
|
||||||
--> $DIR/collapsible_match.rs:31:15
|
--> $DIR/collapsible_match.rs:36:15
|
||||||
|
|
|
|
||||||
LL | if let Ok(val) = res_opt {
|
LL | if let Ok(val) = res_opt {
|
||||||
| ^^^ replace this binding
|
| ^^^ replace this binding
|
||||||
|
@ -70,7 +70,7 @@ LL | if let Some(n) = val {
|
||||||
| ^^^^^^^ with this pattern
|
| ^^^^^^^ with this pattern
|
||||||
|
|
||||||
error: this `match` can be collapsed into the outer `if let`
|
error: this `match` can be collapsed into the outer `if let`
|
||||||
--> $DIR/collapsible_match.rs:43:9
|
--> $DIR/collapsible_match.rs:48:9
|
||||||
|
|
|
|
||||||
LL | / match val {
|
LL | / match val {
|
||||||
LL | | Some(n) => foo(n),
|
LL | | Some(n) => foo(n),
|
||||||
|
@ -79,7 +79,7 @@ LL | | }
|
||||||
| |_________^
|
| |_________^
|
||||||
|
|
|
|
||||||
help: the outer pattern can be modified to include the inner pattern
|
help: the outer pattern can be modified to include the inner pattern
|
||||||
--> $DIR/collapsible_match.rs:42:15
|
--> $DIR/collapsible_match.rs:47:15
|
||||||
|
|
|
|
||||||
LL | if let Ok(val) = res_opt {
|
LL | if let Ok(val) = res_opt {
|
||||||
| ^^^ replace this binding
|
| ^^^ replace this binding
|
||||||
|
@ -88,7 +88,7 @@ LL | Some(n) => foo(n),
|
||||||
| ^^^^^^^ with this pattern
|
| ^^^^^^^ with this pattern
|
||||||
|
|
||||||
error: this `if let` can be collapsed into the outer `match`
|
error: this `if let` can be collapsed into the outer `match`
|
||||||
--> $DIR/collapsible_match.rs:52:13
|
--> $DIR/collapsible_match.rs:57:13
|
||||||
|
|
|
|
||||||
LL | / if let Some(n) = val {
|
LL | / if let Some(n) = val {
|
||||||
LL | | take(n);
|
LL | | take(n);
|
||||||
|
@ -96,7 +96,7 @@ LL | | }
|
||||||
| |_____________^
|
| |_____________^
|
||||||
|
|
|
|
||||||
help: the outer pattern can be modified to include the inner pattern
|
help: the outer pattern can be modified to include the inner pattern
|
||||||
--> $DIR/collapsible_match.rs:51:12
|
--> $DIR/collapsible_match.rs:56:12
|
||||||
|
|
|
|
||||||
LL | Ok(val) => {
|
LL | Ok(val) => {
|
||||||
| ^^^ replace this binding
|
| ^^^ replace this binding
|
||||||
|
@ -104,7 +104,7 @@ LL | if let Some(n) = val {
|
||||||
| ^^^^^^^ with this pattern
|
| ^^^^^^^ with this pattern
|
||||||
|
|
||||||
error: this `match` can be collapsed into the outer `if let`
|
error: this `match` can be collapsed into the outer `if let`
|
||||||
--> $DIR/collapsible_match.rs:61:9
|
--> $DIR/collapsible_match.rs:66:9
|
||||||
|
|
|
|
||||||
LL | / match val {
|
LL | / match val {
|
||||||
LL | | Some(n) => foo(n),
|
LL | | Some(n) => foo(n),
|
||||||
|
@ -113,7 +113,7 @@ LL | | }
|
||||||
| |_________^
|
| |_________^
|
||||||
|
|
|
|
||||||
help: the outer pattern can be modified to include the inner pattern
|
help: the outer pattern can be modified to include the inner pattern
|
||||||
--> $DIR/collapsible_match.rs:60:15
|
--> $DIR/collapsible_match.rs:65:15
|
||||||
|
|
|
|
||||||
LL | if let Ok(val) = res_opt {
|
LL | if let Ok(val) = res_opt {
|
||||||
| ^^^ replace this binding
|
| ^^^ replace this binding
|
||||||
|
@ -122,7 +122,7 @@ LL | Some(n) => foo(n),
|
||||||
| ^^^^^^^ with this pattern
|
| ^^^^^^^ with this pattern
|
||||||
|
|
||||||
error: this `if let` can be collapsed into the outer `match`
|
error: this `if let` can be collapsed into the outer `match`
|
||||||
--> $DIR/collapsible_match.rs:72:13
|
--> $DIR/collapsible_match.rs:77:13
|
||||||
|
|
|
|
||||||
LL | / if let Some(n) = val {
|
LL | / if let Some(n) = val {
|
||||||
LL | | take(n);
|
LL | | take(n);
|
||||||
|
@ -132,7 +132,7 @@ LL | | }
|
||||||
| |_____________^
|
| |_____________^
|
||||||
|
|
|
|
||||||
help: the outer pattern can be modified to include the inner pattern
|
help: the outer pattern can be modified to include the inner pattern
|
||||||
--> $DIR/collapsible_match.rs:71:12
|
--> $DIR/collapsible_match.rs:76:12
|
||||||
|
|
|
|
||||||
LL | Ok(val) => {
|
LL | Ok(val) => {
|
||||||
| ^^^ replace this binding
|
| ^^^ replace this binding
|
||||||
|
@ -140,7 +140,7 @@ LL | if let Some(n) = val {
|
||||||
| ^^^^^^^ with this pattern
|
| ^^^^^^^ with this pattern
|
||||||
|
|
||||||
error: this `match` can be collapsed into the outer `match`
|
error: this `match` can be collapsed into the outer `match`
|
||||||
--> $DIR/collapsible_match.rs:83:20
|
--> $DIR/collapsible_match.rs:88:20
|
||||||
|
|
|
|
||||||
LL | Ok(val) => match val {
|
LL | Ok(val) => match val {
|
||||||
| ____________________^
|
| ____________________^
|
||||||
|
@ -150,7 +150,7 @@ LL | | },
|
||||||
| |_________^
|
| |_________^
|
||||||
|
|
|
|
||||||
help: the outer pattern can be modified to include the inner pattern
|
help: the outer pattern can be modified to include the inner pattern
|
||||||
--> $DIR/collapsible_match.rs:83:12
|
--> $DIR/collapsible_match.rs:88:12
|
||||||
|
|
|
|
||||||
LL | Ok(val) => match val {
|
LL | Ok(val) => match val {
|
||||||
| ^^^ replace this binding
|
| ^^^ replace this binding
|
||||||
|
@ -158,7 +158,7 @@ LL | Some(n) => foo(n),
|
||||||
| ^^^^^^^ with this pattern
|
| ^^^^^^^ with this pattern
|
||||||
|
|
||||||
error: this `match` can be collapsed into the outer `match`
|
error: this `match` can be collapsed into the outer `match`
|
||||||
--> $DIR/collapsible_match.rs:92:22
|
--> $DIR/collapsible_match.rs:97:22
|
||||||
|
|
|
|
||||||
LL | Some(val) => match val {
|
LL | Some(val) => match val {
|
||||||
| ______________________^
|
| ______________________^
|
||||||
|
@ -168,7 +168,7 @@ LL | | },
|
||||||
| |_________^
|
| |_________^
|
||||||
|
|
|
|
||||||
help: the outer pattern can be modified to include the inner pattern
|
help: the outer pattern can be modified to include the inner pattern
|
||||||
--> $DIR/collapsible_match.rs:92:14
|
--> $DIR/collapsible_match.rs:97:14
|
||||||
|
|
|
|
||||||
LL | Some(val) => match val {
|
LL | Some(val) => match val {
|
||||||
| ^^^ replace this binding
|
| ^^^ replace this binding
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#![warn(clippy::all)]
|
#![warn(clippy::all)]
|
||||||
#![allow(clippy::blacklisted_name)]
|
#![allow(clippy::blacklisted_name, clippy::equatable_if_let)]
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
|
|
||||||
/// Test for https://github.com/rust-lang/rust-clippy/issues/3462
|
/// Test for https://github.com/rust-lang/rust-clippy/issues/3462
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#![feature(no_core, lang_items, start)]
|
#![feature(no_core, lang_items, start)]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
|
#![allow(clippy::missing_safety_doc)]
|
||||||
|
|
||||||
#[link(name = "c")]
|
#[link(name = "c")]
|
||||||
extern "C" {}
|
extern "C" {}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
|
error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
|
||||||
--> $DIR/def_id_nocore.rs:27:19
|
--> $DIR/def_id_nocore.rs:28:19
|
||||||
|
|
|
|
||||||
LL | pub fn as_ref(self) -> &'static str {
|
LL | pub fn as_ref(self) -> &'static str {
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
|
@ -207,4 +207,37 @@ impl Default for Color2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct RepeatDefault1 {
|
||||||
|
a: [i8; 32],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for RepeatDefault1 {
|
||||||
|
fn default() -> Self {
|
||||||
|
RepeatDefault1 { a: [0; 32] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RepeatDefault2 {
|
||||||
|
a: [i8; 33],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for RepeatDefault2 {
|
||||||
|
fn default() -> Self {
|
||||||
|
RepeatDefault2 { a: [0; 33] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust-clippy/issues/7753
|
||||||
|
|
||||||
|
pub enum IntOrString {
|
||||||
|
Int(i32),
|
||||||
|
String(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for IntOrString {
|
||||||
|
fn default() -> Self {
|
||||||
|
IntOrString::Int(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -73,5 +73,17 @@ LL | | }
|
||||||
|
|
|
|
||||||
= help: try annotating `WithoutSelfParan` with `#[derive(Default)]`
|
= help: try annotating `WithoutSelfParan` with `#[derive(Default)]`
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
error: this `impl` can be derived
|
||||||
|
--> $DIR/derivable_impls.rs:214:1
|
||||||
|
|
|
||||||
|
LL | / impl Default for RepeatDefault1 {
|
||||||
|
LL | | fn default() -> Self {
|
||||||
|
LL | | RepeatDefault1 { a: [0; 32] }
|
||||||
|
LL | | }
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
|
||||||
|
= help: try annotating `RepeatDefault1` with `#[derive(Default)]`
|
||||||
|
|
||||||
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
|
|
|
@ -203,6 +203,11 @@ fn issue_2343() {}
|
||||||
/// __|_ _|__||_|
|
/// __|_ _|__||_|
|
||||||
fn pulldown_cmark_crash() {}
|
fn pulldown_cmark_crash() {}
|
||||||
|
|
||||||
|
/// This should not lint
|
||||||
|
/// (regression test for #7758)
|
||||||
|
/// [plain text][path::to::item]
|
||||||
|
fn intra_doc_link() {}
|
||||||
|
|
||||||
// issue #7033 - generic_const_exprs ICE
|
// issue #7033 - generic_const_exprs ICE
|
||||||
struct S<T, const N: usize>
|
struct S<T, const N: usize>
|
||||||
where [(); N.checked_next_power_of_two().unwrap()]: {
|
where [(); N.checked_next_power_of_two().unwrap()]: {
|
||||||
|
|
|
@ -34,16 +34,25 @@ mod private_mod {
|
||||||
|
|
||||||
pub use private_mod::republished;
|
pub use private_mod::republished;
|
||||||
|
|
||||||
pub trait UnsafeTrait {
|
pub trait SafeTraitUnsafeMethods {
|
||||||
unsafe fn woefully_underdocumented(self);
|
unsafe fn woefully_underdocumented(self);
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
unsafe fn at_least_somewhat_documented(self);
|
unsafe fn at_least_somewhat_documented(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe trait UnsafeTrait {
|
||||||
|
fn method();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
pub unsafe trait DocumentedUnsafeTrait {
|
||||||
|
fn method2();
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Struct;
|
pub struct Struct;
|
||||||
|
|
||||||
impl UnsafeTrait for Struct {
|
impl SafeTraitUnsafeMethods for Struct {
|
||||||
unsafe fn woefully_underdocumented(self) {
|
unsafe fn woefully_underdocumented(self) {
|
||||||
// all is well
|
// all is well
|
||||||
}
|
}
|
||||||
|
@ -53,6 +62,14 @@ impl UnsafeTrait for Struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl UnsafeTrait for Struct {
|
||||||
|
fn method() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl DocumentedUnsafeTrait for Struct {
|
||||||
|
fn method2() {}
|
||||||
|
}
|
||||||
|
|
||||||
impl Struct {
|
impl Struct {
|
||||||
pub unsafe fn more_undocumented_unsafe() -> Self {
|
pub unsafe fn more_undocumented_unsafe() -> Self {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
|
|
|
@ -22,8 +22,16 @@ error: unsafe function's docs miss `# Safety` section
|
||||||
LL | unsafe fn woefully_underdocumented(self);
|
LL | unsafe fn woefully_underdocumented(self);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: docs for unsafe trait missing `# Safety` section
|
||||||
|
--> $DIR/doc_unsafe.rs:44:1
|
||||||
|
|
|
||||||
|
LL | / pub unsafe trait UnsafeTrait {
|
||||||
|
LL | | fn method();
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
||||||
error: unsafe function's docs miss `# Safety` section
|
error: unsafe function's docs miss `# Safety` section
|
||||||
--> $DIR/doc_unsafe.rs:57:5
|
--> $DIR/doc_unsafe.rs:74:5
|
||||||
|
|
|
|
||||||
LL | / pub unsafe fn more_undocumented_unsafe() -> Self {
|
LL | / pub unsafe fn more_undocumented_unsafe() -> Self {
|
||||||
LL | | unimplemented!();
|
LL | | unimplemented!();
|
||||||
|
@ -31,7 +39,7 @@ LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
||||||
error: unsafe function's docs miss `# Safety` section
|
error: unsafe function's docs miss `# Safety` section
|
||||||
--> $DIR/doc_unsafe.rs:73:9
|
--> $DIR/doc_unsafe.rs:90:9
|
||||||
|
|
|
|
||||||
LL | / pub unsafe fn whee() {
|
LL | / pub unsafe fn whee() {
|
||||||
LL | | unimplemented!()
|
LL | | unimplemented!()
|
||||||
|
@ -43,5 +51,5 @@ LL | very_unsafe!();
|
||||||
|
|
|
|
||||||
= note: this error originates in the macro `very_unsafe` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `very_unsafe` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
|
|
69
tests/ui/equatable_if_let.fixed
Normal file
69
tests/ui/equatable_if_let.fixed
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#![allow(unused_variables, dead_code)]
|
||||||
|
#![warn(clippy::equatable_if_let)]
|
||||||
|
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
enum Enum {
|
||||||
|
TupleVariant(i32, u64),
|
||||||
|
RecordVariant { a: i64, b: u32 },
|
||||||
|
UnitVariant,
|
||||||
|
Recursive(Struct),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
struct Struct {
|
||||||
|
a: i32,
|
||||||
|
b: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum NotPartialEq {
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum NotStructuralEq {
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for NotStructuralEq {
|
||||||
|
fn eq(&self, _: &NotStructuralEq) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a = 2;
|
||||||
|
let b = 3;
|
||||||
|
let c = Some(2);
|
||||||
|
let d = Struct { a: 2, b: false };
|
||||||
|
let e = Enum::UnitVariant;
|
||||||
|
let f = NotPartialEq::A;
|
||||||
|
let g = NotStructuralEq::A;
|
||||||
|
|
||||||
|
// true
|
||||||
|
|
||||||
|
if a == 2 {}
|
||||||
|
if a.cmp(&b) == Ordering::Greater {}
|
||||||
|
if c == Some(2) {}
|
||||||
|
if d == (Struct { a: 2, b: false }) {}
|
||||||
|
if e == Enum::TupleVariant(32, 64) {}
|
||||||
|
if e == (Enum::RecordVariant { a: 64, b: 32 }) {}
|
||||||
|
if e == Enum::UnitVariant {}
|
||||||
|
if (e, &d) == (Enum::UnitVariant, &Struct { a: 2, b: false }) {}
|
||||||
|
|
||||||
|
// false
|
||||||
|
|
||||||
|
if let 2 | 3 = a {}
|
||||||
|
if let x @ 2 = a {}
|
||||||
|
if let Some(3 | 4) = c {}
|
||||||
|
if let Struct { a, b: false } = d {}
|
||||||
|
if let Struct { a: 2, b: x } = d {}
|
||||||
|
if let NotPartialEq::A = f {}
|
||||||
|
if g == NotStructuralEq::A {}
|
||||||
|
if let Some(NotPartialEq::A) = Some(f) {}
|
||||||
|
if Some(g) == Some(NotStructuralEq::A) {}
|
||||||
|
}
|
69
tests/ui/equatable_if_let.rs
Normal file
69
tests/ui/equatable_if_let.rs
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#![allow(unused_variables, dead_code)]
|
||||||
|
#![warn(clippy::equatable_if_let)]
|
||||||
|
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
enum Enum {
|
||||||
|
TupleVariant(i32, u64),
|
||||||
|
RecordVariant { a: i64, b: u32 },
|
||||||
|
UnitVariant,
|
||||||
|
Recursive(Struct),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
struct Struct {
|
||||||
|
a: i32,
|
||||||
|
b: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum NotPartialEq {
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum NotStructuralEq {
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for NotStructuralEq {
|
||||||
|
fn eq(&self, _: &NotStructuralEq) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a = 2;
|
||||||
|
let b = 3;
|
||||||
|
let c = Some(2);
|
||||||
|
let d = Struct { a: 2, b: false };
|
||||||
|
let e = Enum::UnitVariant;
|
||||||
|
let f = NotPartialEq::A;
|
||||||
|
let g = NotStructuralEq::A;
|
||||||
|
|
||||||
|
// true
|
||||||
|
|
||||||
|
if let 2 = a {}
|
||||||
|
if let Ordering::Greater = a.cmp(&b) {}
|
||||||
|
if let Some(2) = c {}
|
||||||
|
if let Struct { a: 2, b: false } = d {}
|
||||||
|
if let Enum::TupleVariant(32, 64) = e {}
|
||||||
|
if let Enum::RecordVariant { a: 64, b: 32 } = e {}
|
||||||
|
if let Enum::UnitVariant = e {}
|
||||||
|
if let (Enum::UnitVariant, &Struct { a: 2, b: false }) = (e, &d) {}
|
||||||
|
|
||||||
|
// false
|
||||||
|
|
||||||
|
if let 2 | 3 = a {}
|
||||||
|
if let x @ 2 = a {}
|
||||||
|
if let Some(3 | 4) = c {}
|
||||||
|
if let Struct { a, b: false } = d {}
|
||||||
|
if let Struct { a: 2, b: x } = d {}
|
||||||
|
if let NotPartialEq::A = f {}
|
||||||
|
if let NotStructuralEq::A = g {}
|
||||||
|
if let Some(NotPartialEq::A) = Some(f) {}
|
||||||
|
if let Some(NotStructuralEq::A) = Some(g) {}
|
||||||
|
}
|
64
tests/ui/equatable_if_let.stderr
Normal file
64
tests/ui/equatable_if_let.stderr
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
error: this pattern matching can be expressed using equality
|
||||||
|
--> $DIR/equatable_if_let.rs:49:8
|
||||||
|
|
|
||||||
|
LL | if let 2 = a {}
|
||||||
|
| ^^^^^^^^^ help: try: `a == 2`
|
||||||
|
|
|
||||||
|
= note: `-D clippy::equatable-if-let` implied by `-D warnings`
|
||||||
|
|
||||||
|
error: this pattern matching can be expressed using equality
|
||||||
|
--> $DIR/equatable_if_let.rs:50:8
|
||||||
|
|
|
||||||
|
LL | if let Ordering::Greater = a.cmp(&b) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.cmp(&b) == Ordering::Greater`
|
||||||
|
|
||||||
|
error: this pattern matching can be expressed using equality
|
||||||
|
--> $DIR/equatable_if_let.rs:51:8
|
||||||
|
|
|
||||||
|
LL | if let Some(2) = c {}
|
||||||
|
| ^^^^^^^^^^^^^^^ help: try: `c == Some(2)`
|
||||||
|
|
||||||
|
error: this pattern matching can be expressed using equality
|
||||||
|
--> $DIR/equatable_if_let.rs:52:8
|
||||||
|
|
|
||||||
|
LL | if let Struct { a: 2, b: false } = d {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `d == (Struct { a: 2, b: false })`
|
||||||
|
|
||||||
|
error: this pattern matching can be expressed using equality
|
||||||
|
--> $DIR/equatable_if_let.rs:53:8
|
||||||
|
|
|
||||||
|
LL | if let Enum::TupleVariant(32, 64) = e {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::TupleVariant(32, 64)`
|
||||||
|
|
||||||
|
error: this pattern matching can be expressed using equality
|
||||||
|
--> $DIR/equatable_if_let.rs:54:8
|
||||||
|
|
|
||||||
|
LL | if let Enum::RecordVariant { a: 64, b: 32 } = e {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == (Enum::RecordVariant { a: 64, b: 32 })`
|
||||||
|
|
||||||
|
error: this pattern matching can be expressed using equality
|
||||||
|
--> $DIR/equatable_if_let.rs:55:8
|
||||||
|
|
|
||||||
|
LL | if let Enum::UnitVariant = e {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::UnitVariant`
|
||||||
|
|
||||||
|
error: this pattern matching can be expressed using equality
|
||||||
|
--> $DIR/equatable_if_let.rs:56:8
|
||||||
|
|
|
||||||
|
LL | if let (Enum::UnitVariant, &Struct { a: 2, b: false }) = (e, &d) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(e, &d) == (Enum::UnitVariant, &Struct { a: 2, b: false })`
|
||||||
|
|
||||||
|
error: this pattern matching can be expressed using equality
|
||||||
|
--> $DIR/equatable_if_let.rs:66:8
|
||||||
|
|
|
||||||
|
LL | if let NotStructuralEq::A = g {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `g == NotStructuralEq::A`
|
||||||
|
|
||||||
|
error: this pattern matching can be expressed using equality
|
||||||
|
--> $DIR/equatable_if_let.rs:68:8
|
||||||
|
|
|
||||||
|
LL | if let Some(NotStructuralEq::A) = Some(g) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(g) == Some(NotStructuralEq::A)`
|
||||||
|
|
||||||
|
error: aborting due to 10 previous errors
|
||||||
|
|
|
@ -60,4 +60,10 @@ fn main() {
|
||||||
|
|
||||||
// issue #2840
|
// issue #2840
|
||||||
let num = 0.000_000_000_01e-10f64;
|
let num = 0.000_000_000_01e-10f64;
|
||||||
|
|
||||||
|
// issue #7744
|
||||||
|
let _ = 2.225_073_858_507_201e-308_f64;
|
||||||
|
|
||||||
|
// issue #7745
|
||||||
|
let _ = 0_f64;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,4 +60,10 @@ fn main() {
|
||||||
|
|
||||||
// issue #2840
|
// issue #2840
|
||||||
let num = 0.000_000_000_01e-10f64;
|
let num = 0.000_000_000_01e-10f64;
|
||||||
|
|
||||||
|
// issue #7744
|
||||||
|
let _ = 2.225_073_858_507_201_1e-308_f64;
|
||||||
|
|
||||||
|
// issue #7745
|
||||||
|
let _ = 1.000_000_000_000_001e-324_f64;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,5 +78,17 @@ error: float has excessive precision
|
||||||
LL | let bad_bige32: f32 = 1.123_456_788_888E-10;
|
LL | let bad_bige32: f32 = 1.123_456_788_888E-10;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8E-10`
|
| ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8E-10`
|
||||||
|
|
||||||
error: aborting due to 13 previous errors
|
error: float has excessive precision
|
||||||
|
--> $DIR/excessive_precision.rs:65:13
|
||||||
|
|
|
||||||
|
LL | let _ = 2.225_073_858_507_201_1e-308_f64;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `2.225_073_858_507_201e-308_f64`
|
||||||
|
|
||||||
|
error: float has excessive precision
|
||||||
|
--> $DIR/excessive_precision.rs:68:13
|
||||||
|
|
|
||||||
|
LL | let _ = 1.000_000_000_000_001e-324_f64;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0_f64`
|
||||||
|
|
||||||
|
error: aborting due to 15 previous errors
|
||||||
|
|
||||||
|
|
|
@ -23,12 +23,7 @@ impl Unrelated {
|
||||||
clippy::iter_next_loop,
|
clippy::iter_next_loop,
|
||||||
clippy::for_kv_map
|
clippy::for_kv_map
|
||||||
)]
|
)]
|
||||||
#[allow(
|
#[allow(clippy::linkedlist, clippy::unnecessary_mut_passed, clippy::similar_names)]
|
||||||
clippy::linkedlist,
|
|
||||||
clippy::shadow_unrelated,
|
|
||||||
clippy::unnecessary_mut_passed,
|
|
||||||
clippy::similar_names
|
|
||||||
)]
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut vec = vec![1, 2, 3, 4];
|
let mut vec = vec![1, 2, 3, 4];
|
||||||
|
|
|
@ -23,12 +23,7 @@ impl Unrelated {
|
||||||
clippy::iter_next_loop,
|
clippy::iter_next_loop,
|
||||||
clippy::for_kv_map
|
clippy::for_kv_map
|
||||||
)]
|
)]
|
||||||
#[allow(
|
#[allow(clippy::linkedlist, clippy::unnecessary_mut_passed, clippy::similar_names)]
|
||||||
clippy::linkedlist,
|
|
||||||
clippy::shadow_unrelated,
|
|
||||||
clippy::unnecessary_mut_passed,
|
|
||||||
clippy::similar_names
|
|
||||||
)]
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut vec = vec![1, 2, 3, 4];
|
let mut vec = vec![1, 2, 3, 4];
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||||
--> $DIR/for_loop_fixable.rs:43:15
|
--> $DIR/for_loop_fixable.rs:38:15
|
||||||
|
|
|
|
||||||
LL | for _v in vec.iter() {}
|
LL | for _v in vec.iter() {}
|
||||||
| ^^^^^^^^^^ help: to write this more concisely, try: `&vec`
|
| ^^^^^^^^^^ help: to write this more concisely, try: `&vec`
|
||||||
|
@ -7,13 +7,13 @@ LL | for _v in vec.iter() {}
|
||||||
= note: `-D clippy::explicit-iter-loop` implied by `-D warnings`
|
= note: `-D clippy::explicit-iter-loop` implied by `-D warnings`
|
||||||
|
|
||||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||||
--> $DIR/for_loop_fixable.rs:45:15
|
--> $DIR/for_loop_fixable.rs:40:15
|
||||||
|
|
|
|
||||||
LL | for _v in vec.iter_mut() {}
|
LL | for _v in vec.iter_mut() {}
|
||||||
| ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec`
|
| ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec`
|
||||||
|
|
||||||
error: it is more concise to loop over containers instead of using explicit iteration methods
|
error: it is more concise to loop over containers instead of using explicit iteration methods
|
||||||
--> $DIR/for_loop_fixable.rs:48:15
|
--> $DIR/for_loop_fixable.rs:43:15
|
||||||
|
|
|
|
||||||
LL | for _v in out_vec.into_iter() {}
|
LL | for _v in out_vec.into_iter() {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec`
|
| ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec`
|
||||||
|
@ -21,73 +21,73 @@ LL | for _v in out_vec.into_iter() {}
|
||||||
= note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings`
|
= note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings`
|
||||||
|
|
||||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||||
--> $DIR/for_loop_fixable.rs:53:15
|
--> $DIR/for_loop_fixable.rs:48:15
|
||||||
|
|
|
|
||||||
LL | for _v in [1, 2, 3].iter() {}
|
LL | for _v in [1, 2, 3].iter() {}
|
||||||
| ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]`
|
| ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]`
|
||||||
|
|
||||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||||
--> $DIR/for_loop_fixable.rs:57:15
|
--> $DIR/for_loop_fixable.rs:52:15
|
||||||
|
|
|
|
||||||
LL | for _v in [0; 32].iter() {}
|
LL | for _v in [0; 32].iter() {}
|
||||||
| ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]`
|
| ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]`
|
||||||
|
|
||||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||||
--> $DIR/for_loop_fixable.rs:62:15
|
--> $DIR/for_loop_fixable.rs:57:15
|
||||||
|
|
|
|
||||||
LL | for _v in ll.iter() {}
|
LL | for _v in ll.iter() {}
|
||||||
| ^^^^^^^^^ help: to write this more concisely, try: `&ll`
|
| ^^^^^^^^^ help: to write this more concisely, try: `&ll`
|
||||||
|
|
||||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||||
--> $DIR/for_loop_fixable.rs:65:15
|
--> $DIR/for_loop_fixable.rs:60:15
|
||||||
|
|
|
|
||||||
LL | for _v in vd.iter() {}
|
LL | for _v in vd.iter() {}
|
||||||
| ^^^^^^^^^ help: to write this more concisely, try: `&vd`
|
| ^^^^^^^^^ help: to write this more concisely, try: `&vd`
|
||||||
|
|
||||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||||
--> $DIR/for_loop_fixable.rs:68:15
|
--> $DIR/for_loop_fixable.rs:63:15
|
||||||
|
|
|
|
||||||
LL | for _v in bh.iter() {}
|
LL | for _v in bh.iter() {}
|
||||||
| ^^^^^^^^^ help: to write this more concisely, try: `&bh`
|
| ^^^^^^^^^ help: to write this more concisely, try: `&bh`
|
||||||
|
|
||||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||||
--> $DIR/for_loop_fixable.rs:71:15
|
--> $DIR/for_loop_fixable.rs:66:15
|
||||||
|
|
|
|
||||||
LL | for _v in hm.iter() {}
|
LL | for _v in hm.iter() {}
|
||||||
| ^^^^^^^^^ help: to write this more concisely, try: `&hm`
|
| ^^^^^^^^^ help: to write this more concisely, try: `&hm`
|
||||||
|
|
||||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||||
--> $DIR/for_loop_fixable.rs:74:15
|
--> $DIR/for_loop_fixable.rs:69:15
|
||||||
|
|
|
|
||||||
LL | for _v in bt.iter() {}
|
LL | for _v in bt.iter() {}
|
||||||
| ^^^^^^^^^ help: to write this more concisely, try: `&bt`
|
| ^^^^^^^^^ help: to write this more concisely, try: `&bt`
|
||||||
|
|
||||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||||
--> $DIR/for_loop_fixable.rs:77:15
|
--> $DIR/for_loop_fixable.rs:72:15
|
||||||
|
|
|
|
||||||
LL | for _v in hs.iter() {}
|
LL | for _v in hs.iter() {}
|
||||||
| ^^^^^^^^^ help: to write this more concisely, try: `&hs`
|
| ^^^^^^^^^ help: to write this more concisely, try: `&hs`
|
||||||
|
|
||||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||||
--> $DIR/for_loop_fixable.rs:80:15
|
--> $DIR/for_loop_fixable.rs:75:15
|
||||||
|
|
|
|
||||||
LL | for _v in bs.iter() {}
|
LL | for _v in bs.iter() {}
|
||||||
| ^^^^^^^^^ help: to write this more concisely, try: `&bs`
|
| ^^^^^^^^^ help: to write this more concisely, try: `&bs`
|
||||||
|
|
||||||
error: it is more concise to loop over containers instead of using explicit iteration methods
|
error: it is more concise to loop over containers instead of using explicit iteration methods
|
||||||
--> $DIR/for_loop_fixable.rs:255:18
|
--> $DIR/for_loop_fixable.rs:250:18
|
||||||
|
|
|
|
||||||
LL | for i in iterator.into_iter() {
|
LL | for i in iterator.into_iter() {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `iterator`
|
| ^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `iterator`
|
||||||
|
|
||||||
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
error: it is more concise to loop over references to containers instead of using explicit iteration methods
|
||||||
--> $DIR/for_loop_fixable.rs:275:18
|
--> $DIR/for_loop_fixable.rs:270:18
|
||||||
|
|
|
|
||||||
LL | for _ in t.into_iter() {}
|
LL | for _ in t.into_iter() {}
|
||||||
| ^^^^^^^^^^^^^ help: to write this more concisely, try: `&t`
|
| ^^^^^^^^^^^^^ help: to write this more concisely, try: `&t`
|
||||||
|
|
||||||
error: it is more concise to loop over containers instead of using explicit iteration methods
|
error: it is more concise to loop over containers instead of using explicit iteration methods
|
||||||
--> $DIR/for_loop_fixable.rs:277:18
|
--> $DIR/for_loop_fixable.rs:272:18
|
||||||
|
|
|
|
||||||
LL | for _ in r.into_iter() {}
|
LL | for _ in r.into_iter() {}
|
||||||
| ^^^^^^^^^^^^^ help: to write this more concisely, try: `r`
|
| ^^^^^^^^^^^^^ help: to write this more concisely, try: `r`
|
||||||
|
|
|
@ -7,14 +7,7 @@
|
||||||
clippy::iter_next_loop,
|
clippy::iter_next_loop,
|
||||||
clippy::for_kv_map
|
clippy::for_kv_map
|
||||||
)]
|
)]
|
||||||
#[allow(
|
#[allow(clippy::linkedlist, clippy::unnecessary_mut_passed, clippy::similar_names)]
|
||||||
clippy::linkedlist,
|
|
||||||
clippy::shadow_unrelated,
|
|
||||||
clippy::unnecessary_mut_passed,
|
|
||||||
clippy::similar_names,
|
|
||||||
unused,
|
|
||||||
dead_code
|
|
||||||
)]
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let vec = vec![1, 2, 3, 4];
|
let vec = vec![1, 2, 3, 4];
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want
|
error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want
|
||||||
--> $DIR/for_loop_unfixable.rs:21:15
|
--> $DIR/for_loop_unfixable.rs:14:15
|
||||||
|
|
|
|
||||||
LL | for _v in vec.iter().next() {}
|
LL | for _v in vec.iter().next() {}
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#![allow(
|
#![allow(
|
||||||
clippy::blacklisted_name,
|
clippy::blacklisted_name,
|
||||||
clippy::collapsible_else_if,
|
clippy::collapsible_else_if,
|
||||||
|
clippy::equatable_if_let,
|
||||||
clippy::collapsible_if,
|
clippy::collapsible_if,
|
||||||
clippy::ifs_same_cond,
|
clippy::ifs_same_cond,
|
||||||
clippy::needless_return,
|
clippy::needless_return,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: this `if` has identical blocks
|
error: this `if` has identical blocks
|
||||||
--> $DIR/if_same_then_else2.rs:13:13
|
--> $DIR/if_same_then_else2.rs:14:13
|
||||||
|
|
|
|
||||||
LL | if true {
|
LL | if true {
|
||||||
| _____________^
|
| _____________^
|
||||||
|
@ -13,7 +13,7 @@ LL | | } else {
|
||||||
|
|
|
|
||||||
= note: `-D clippy::if-same-then-else` implied by `-D warnings`
|
= note: `-D clippy::if-same-then-else` implied by `-D warnings`
|
||||||
note: same as this
|
note: same as this
|
||||||
--> $DIR/if_same_then_else2.rs:22:12
|
--> $DIR/if_same_then_else2.rs:23:12
|
||||||
|
|
|
|
||||||
LL | } else {
|
LL | } else {
|
||||||
| ____________^
|
| ____________^
|
||||||
|
@ -26,7 +26,7 @@ LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
||||||
error: this `if` has identical blocks
|
error: this `if` has identical blocks
|
||||||
--> $DIR/if_same_then_else2.rs:34:13
|
--> $DIR/if_same_then_else2.rs:35:13
|
||||||
|
|
|
|
||||||
LL | if true {
|
LL | if true {
|
||||||
| _____________^
|
| _____________^
|
||||||
|
@ -35,7 +35,7 @@ LL | | } else {
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
note: same as this
|
note: same as this
|
||||||
--> $DIR/if_same_then_else2.rs:36:12
|
--> $DIR/if_same_then_else2.rs:37:12
|
||||||
|
|
|
|
||||||
LL | } else {
|
LL | } else {
|
||||||
| ____________^
|
| ____________^
|
||||||
|
@ -45,7 +45,7 @@ LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
||||||
error: this `if` has identical blocks
|
error: this `if` has identical blocks
|
||||||
--> $DIR/if_same_then_else2.rs:41:13
|
--> $DIR/if_same_then_else2.rs:42:13
|
||||||
|
|
|
|
||||||
LL | if true {
|
LL | if true {
|
||||||
| _____________^
|
| _____________^
|
||||||
|
@ -54,7 +54,7 @@ LL | | } else {
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
note: same as this
|
note: same as this
|
||||||
--> $DIR/if_same_then_else2.rs:43:12
|
--> $DIR/if_same_then_else2.rs:44:12
|
||||||
|
|
|
|
||||||
LL | } else {
|
LL | } else {
|
||||||
| ____________^
|
| ____________^
|
||||||
|
@ -64,7 +64,7 @@ LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
||||||
error: this `if` has identical blocks
|
error: this `if` has identical blocks
|
||||||
--> $DIR/if_same_then_else2.rs:91:21
|
--> $DIR/if_same_then_else2.rs:92:21
|
||||||
|
|
|
|
||||||
LL | let _ = if true {
|
LL | let _ = if true {
|
||||||
| _____________________^
|
| _____________________^
|
||||||
|
@ -73,7 +73,7 @@ LL | | } else {
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
note: same as this
|
note: same as this
|
||||||
--> $DIR/if_same_then_else2.rs:93:12
|
--> $DIR/if_same_then_else2.rs:94:12
|
||||||
|
|
|
|
||||||
LL | } else {
|
LL | } else {
|
||||||
| ____________^
|
| ____________^
|
||||||
|
@ -83,7 +83,7 @@ LL | | };
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
||||||
error: this `if` has identical blocks
|
error: this `if` has identical blocks
|
||||||
--> $DIR/if_same_then_else2.rs:98:13
|
--> $DIR/if_same_then_else2.rs:99:13
|
||||||
|
|
|
|
||||||
LL | if true {
|
LL | if true {
|
||||||
| _____________^
|
| _____________^
|
||||||
|
@ -92,7 +92,7 @@ LL | | } else {
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
note: same as this
|
note: same as this
|
||||||
--> $DIR/if_same_then_else2.rs:100:12
|
--> $DIR/if_same_then_else2.rs:101:12
|
||||||
|
|
|
|
||||||
LL | } else {
|
LL | } else {
|
||||||
| ____________^
|
| ____________^
|
||||||
|
@ -102,7 +102,7 @@ LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
||||||
error: this `if` has identical blocks
|
error: this `if` has identical blocks
|
||||||
--> $DIR/if_same_then_else2.rs:122:20
|
--> $DIR/if_same_then_else2.rs:123:20
|
||||||
|
|
|
|
||||||
LL | } else if true {
|
LL | } else if true {
|
||||||
| ____________________^
|
| ____________________^
|
||||||
|
@ -112,7 +112,7 @@ LL | | } else {
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
note: same as this
|
note: same as this
|
||||||
--> $DIR/if_same_then_else2.rs:125:12
|
--> $DIR/if_same_then_else2.rs:126:12
|
||||||
|
|
|
|
||||||
LL | } else {
|
LL | } else {
|
||||||
| ____________^
|
| ____________^
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue