mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-10 07:04:18 +00:00
Merge commit 'ca3b393750ee8d870bf3215dcf6509cafa5c0445' into clippy-subtree-update
This commit is contained in:
parent
876d5f00a0
commit
a5aaf33422
84 changed files with 1067 additions and 427 deletions
2
.github/workflows/remark.yml
vendored
2
.github/workflows/remark.yml
vendored
|
@ -24,7 +24,7 @@ jobs:
|
||||||
node-version: '18.x'
|
node-version: '18.x'
|
||||||
|
|
||||||
- name: Install remark
|
- name: Install remark
|
||||||
run: npm install remark-cli remark-lint remark-lint-maximum-line-length remark-preset-lint-recommended remark-gfm
|
run: npm install remark-cli remark-lint remark-lint-maximum-line-length@^3.1.3 remark-preset-lint-recommended remark-gfm
|
||||||
|
|
||||||
- name: Install mdbook
|
- name: Install mdbook
|
||||||
run: |
|
run: |
|
||||||
|
|
|
@ -5894,6 +5894,7 @@ Released 2018-09-13
|
||||||
[`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles
|
[`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles
|
||||||
[`allowed-duplicate-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-duplicate-crates
|
[`allowed-duplicate-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-duplicate-crates
|
||||||
[`allowed-idents-below-min-chars`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-idents-below-min-chars
|
[`allowed-idents-below-min-chars`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-idents-below-min-chars
|
||||||
|
[`allowed-prefixes`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-prefixes
|
||||||
[`allowed-scripts`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-scripts
|
[`allowed-scripts`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-scripts
|
||||||
[`allowed-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-wildcard-imports
|
[`allowed-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-wildcard-imports
|
||||||
[`arithmetic-side-effects-allowed`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed
|
[`arithmetic-side-effects-allowed`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed
|
||||||
|
|
|
@ -18,17 +18,27 @@ category.
|
||||||
| `clippy::all` | all lints that are on by default (correctness, suspicious, style, complexity, perf) | **warn/deny** |
|
| `clippy::all` | all lints that are on by default (correctness, suspicious, style, complexity, perf) | **warn/deny** |
|
||||||
| `clippy::correctness` | code that is outright wrong or useless | **deny** |
|
| `clippy::correctness` | code that is outright wrong or useless | **deny** |
|
||||||
| `clippy::suspicious` | code that is most likely wrong or useless | **warn** |
|
| `clippy::suspicious` | code that is most likely wrong or useless | **warn** |
|
||||||
|
| `clippy::style` | code that should be written in a more idiomatic way | **warn** |
|
||||||
| `clippy::complexity` | code that does something simple but in a complex way | **warn** |
|
| `clippy::complexity` | code that does something simple but in a complex way | **warn** |
|
||||||
| `clippy::perf` | code that can be written to run faster | **warn** |
|
| `clippy::perf` | code that can be written to run faster | **warn** |
|
||||||
| `clippy::style` | code that should be written in a more idiomatic way | **warn** |
|
| `clippy::pedantic` | lints which are rather strict or have occasional false positives | allow |
|
||||||
| `clippy::pedantic` | lints which are rather strict or might have false positives | allow |
|
| `clippy::restriction` | lints which prevent the use of language and library features[^restrict] | allow |
|
||||||
| `clippy::nursery` | new lints that are still under development | allow |
|
| `clippy::nursery` | new lints that are still under development | allow |
|
||||||
| `clippy::cargo` | lints for the cargo manifest | allow | | allow |
|
| `clippy::cargo` | lints for the cargo manifest | allow |
|
||||||
|
|
||||||
More to come, please [file an
|
More to come, please [file an issue](https://github.com/rust-lang/rust-clippy/issues) if you have ideas!
|
||||||
issue](https://github.com/rust-lang/rust-clippy/issues) if you have ideas!
|
|
||||||
|
|
||||||
The [lint list](https://rust-lang.github.io/rust-clippy/master/index.html) also
|
The `restriction` category should, *emphatically*, not be enabled as a whole. The contained
|
||||||
contains "restriction lints", which are for things which are usually not
|
lints may lint against perfectly reasonable code, may not have an alternative suggestion,
|
||||||
considered "bad", but may be useful to turn on in specific cases. These should
|
and may contradict any other lints (including other categories). Lints should be considered
|
||||||
be used very selectively, if at all.
|
on a case-by-case basis before enabling.
|
||||||
|
|
||||||
|
[^restrict]: Some use cases for `restriction` lints include:
|
||||||
|
- Strict coding styles (e.g. [`clippy::else_if_without_else`]).
|
||||||
|
- Additional restrictions on CI (e.g. [`clippy::todo`]).
|
||||||
|
- Preventing panicking in certain functions (e.g. [`clippy::unwrap_used`]).
|
||||||
|
- Running a lint only on a subset of code (e.g. `#[forbid(clippy::float_arithmetic)]` on a module).
|
||||||
|
|
||||||
|
[`clippy::else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else
|
||||||
|
[`clippy::todo`]: https://rust-lang.github.io/rust-clippy/master/index.html#todo
|
||||||
|
[`clippy::unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used
|
||||||
|
|
|
@ -18,7 +18,6 @@ because that's clearly a non-descriptive name.
|
||||||
- [Cargo lints](#cargo-lints)
|
- [Cargo lints](#cargo-lints)
|
||||||
- [Rustfix tests](#rustfix-tests)
|
- [Rustfix tests](#rustfix-tests)
|
||||||
- [Testing manually](#testing-manually)
|
- [Testing manually](#testing-manually)
|
||||||
- [Running directly](#running-directly)
|
|
||||||
- [Lint declaration](#lint-declaration)
|
- [Lint declaration](#lint-declaration)
|
||||||
- [Lint registration](#lint-registration)
|
- [Lint registration](#lint-registration)
|
||||||
- [Lint passes](#lint-passes)
|
- [Lint passes](#lint-passes)
|
||||||
|
@ -176,23 +175,26 @@ the tests.
|
||||||
|
|
||||||
Manually testing against an example file can be useful if you have added some
|
Manually testing against an example file can be useful if you have added some
|
||||||
`println!`s and the test suite output becomes unreadable. To try Clippy with
|
`println!`s and the test suite output becomes unreadable. To try Clippy with
|
||||||
your local modifications, run
|
your local modifications, run the following from the Clippy directory:
|
||||||
|
|
||||||
```
|
```bash
|
||||||
cargo dev lint input.rs
|
cargo dev lint input.rs
|
||||||
```
|
```
|
||||||
|
|
||||||
from the working copy root. With tests in place, let's have a look at
|
To run Clippy on an existing project rather than a single file you can use
|
||||||
implementing our lint now.
|
|
||||||
|
|
||||||
## Running directly
|
```bash
|
||||||
|
cargo dev lint /path/to/project
|
||||||
|
```
|
||||||
|
|
||||||
While it's easier to just use `cargo dev lint`, it might be desirable to get
|
Or set up a rustup toolchain that points to the local Clippy binaries
|
||||||
`target/release/cargo-clippy` and `target/release/clippy-driver` to work as well in some cases.
|
|
||||||
By default, they don't work because clippy dynamically links rustc. To help them find rustc,
|
```bash
|
||||||
add the path printed by`rustc --print target-libdir` (ran inside this workspace so that the rustc version matches)
|
cargo dev setup toolchain
|
||||||
to your library search path.
|
|
||||||
On linux, this can be done by setting the `LD_LIBRARY_PATH` environment variable to that path.
|
# Then in `/path/to/project` you can run
|
||||||
|
cargo +clippy clippy
|
||||||
|
```
|
||||||
|
|
||||||
## Lint declaration
|
## Lint declaration
|
||||||
|
|
||||||
|
|
|
@ -164,6 +164,32 @@ configuration of Clippy. By default, any configuration will replace the default
|
||||||
* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars)
|
* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars)
|
||||||
|
|
||||||
|
|
||||||
|
## `allowed-prefixes`
|
||||||
|
List of prefixes to allow when determining whether an item's name ends with the module's name.
|
||||||
|
If the rest of an item's name is an allowed prefix (e.g. item `ToFoo` or `to_foo` in module `foo`),
|
||||||
|
then don't emit a warning.
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```toml
|
||||||
|
allowed-prefixes = [ "to", "from" ]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Noteworthy
|
||||||
|
|
||||||
|
- By default, the following prefixes are allowed: `to`, `as`, `into`, `from`, `try_into` and `try_from`
|
||||||
|
- PascalCase variant is included automatically for each snake_case variant (e.g. if `try_into` is included,
|
||||||
|
`TryInto` will also be included)
|
||||||
|
- Use `".."` as part of the list to indicate that the configured values should be appended to the
|
||||||
|
default configuration of Clippy. By default, any configuration will replace the default value
|
||||||
|
|
||||||
|
**Default Value:** `["to", "as", "into", "from", "try_into", "try_from"]`
|
||||||
|
|
||||||
|
---
|
||||||
|
**Affected lints:**
|
||||||
|
* [`module_name_repetitions`](https://rust-lang.github.io/rust-clippy/master/index.html#module_name_repetitions)
|
||||||
|
|
||||||
|
|
||||||
## `allowed-scripts`
|
## `allowed-scripts`
|
||||||
The list of unicode scripts allowed to be used in the scope.
|
The list of unicode scripts allowed to be used in the scope.
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[
|
||||||
];
|
];
|
||||||
const DEFAULT_DISALLOWED_NAMES: &[&str] = &["foo", "baz", "quux"];
|
const DEFAULT_DISALLOWED_NAMES: &[&str] = &["foo", "baz", "quux"];
|
||||||
const DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS: &[&str] = &["i", "j", "x", "y", "z", "w", "n"];
|
const DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS: &[&str] = &["i", "j", "x", "y", "z", "w", "n"];
|
||||||
|
const DEFAULT_ALLOWED_PREFIXES: &[&str] = &["to", "as", "into", "from", "try_into", "try_from"];
|
||||||
|
|
||||||
/// Conf with parse errors
|
/// Conf with parse errors
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -589,6 +590,26 @@ define_Conf! {
|
||||||
/// 2. Paths with any segment that containing the word 'prelude'
|
/// 2. Paths with any segment that containing the word 'prelude'
|
||||||
/// are already allowed by default.
|
/// are already allowed by default.
|
||||||
(allowed_wildcard_imports: FxHashSet<String> = FxHashSet::default()),
|
(allowed_wildcard_imports: FxHashSet<String> = FxHashSet::default()),
|
||||||
|
/// Lint: MODULE_NAME_REPETITIONS.
|
||||||
|
///
|
||||||
|
/// List of prefixes to allow when determining whether an item's name ends with the module's name.
|
||||||
|
/// If the rest of an item's name is an allowed prefix (e.g. item `ToFoo` or `to_foo` in module `foo`),
|
||||||
|
/// then don't emit a warning.
|
||||||
|
///
|
||||||
|
/// #### Example
|
||||||
|
///
|
||||||
|
/// ```toml
|
||||||
|
/// allowed-prefixes = [ "to", "from" ]
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// #### Noteworthy
|
||||||
|
///
|
||||||
|
/// - By default, the following prefixes are allowed: `to`, `as`, `into`, `from`, `try_into` and `try_from`
|
||||||
|
/// - PascalCase variant is included automatically for each snake_case variant (e.g. if `try_into` is included,
|
||||||
|
/// `TryInto` will also be included)
|
||||||
|
/// - Use `".."` as part of the list to indicate that the configured values should be appended to the
|
||||||
|
/// default configuration of Clippy. By default, any configuration will replace the default value
|
||||||
|
(allowed_prefixes: Vec<String> = DEFAULT_ALLOWED_PREFIXES.iter().map(ToString::to_string).collect()),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Search for the configuration file.
|
/// Search for the configuration file.
|
||||||
|
@ -649,6 +670,7 @@ fn deserialize(file: &SourceFile) -> TryConf {
|
||||||
Ok(mut conf) => {
|
Ok(mut conf) => {
|
||||||
extend_vec_if_indicator_present(&mut conf.conf.doc_valid_idents, DEFAULT_DOC_VALID_IDENTS);
|
extend_vec_if_indicator_present(&mut conf.conf.doc_valid_idents, DEFAULT_DOC_VALID_IDENTS);
|
||||||
extend_vec_if_indicator_present(&mut conf.conf.disallowed_names, DEFAULT_DISALLOWED_NAMES);
|
extend_vec_if_indicator_present(&mut conf.conf.disallowed_names, DEFAULT_DISALLOWED_NAMES);
|
||||||
|
extend_vec_if_indicator_present(&mut conf.conf.allowed_prefixes, DEFAULT_ALLOWED_PREFIXES);
|
||||||
// TODO: THIS SHOULD BE TESTED, this comment will be gone soon
|
// TODO: THIS SHOULD BE TESTED, this comment will be gone soon
|
||||||
if conf.conf.allowed_idents_below_min_chars.contains("..") {
|
if conf.conf.allowed_idents_below_min_chars.contains("..") {
|
||||||
conf.conf
|
conf.conf
|
||||||
|
|
|
@ -35,7 +35,6 @@ struct FmtContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
// the "main" function of cargo dev fmt
|
// the "main" function of cargo dev fmt
|
||||||
#[allow(clippy::missing_panics_doc)]
|
|
||||||
pub fn run(check: bool, verbose: bool) {
|
pub fn run(check: bool, verbose: bool) {
|
||||||
fn try_run(context: &FmtContext) -> Result<bool, CliError> {
|
fn try_run(context: &FmtContext) -> Result<bool, CliError> {
|
||||||
let mut success = true;
|
let mut success = true;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
unused_lifetimes,
|
unused_lifetimes,
|
||||||
unused_qualifications
|
unused_qualifications
|
||||||
)]
|
)]
|
||||||
|
#![allow(clippy::missing_panics_doc)]
|
||||||
|
|
||||||
// The `rustc_driver` crate seems to be required in order to use the `rust_lexer` crate.
|
// The `rustc_driver` crate seems to be required in order to use the `rust_lexer` crate.
|
||||||
#[allow(unused_extern_crates)]
|
#[allow(unused_extern_crates)]
|
||||||
|
|
|
@ -46,6 +46,13 @@ fn main() {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(("setup", sub_command)) => match sub_command.subcommand() {
|
Some(("setup", sub_command)) => match sub_command.subcommand() {
|
||||||
|
Some(("git-hook", matches)) => {
|
||||||
|
if matches.get_flag("remove") {
|
||||||
|
setup::git_hook::remove_hook();
|
||||||
|
} else {
|
||||||
|
setup::git_hook::install_hook(matches.get_flag("force-override"));
|
||||||
|
}
|
||||||
|
},
|
||||||
Some(("intellij", matches)) => {
|
Some(("intellij", matches)) => {
|
||||||
if matches.get_flag("remove") {
|
if matches.get_flag("remove") {
|
||||||
setup::intellij::remove_rustc_src();
|
setup::intellij::remove_rustc_src();
|
||||||
|
@ -57,12 +64,12 @@ fn main() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(("git-hook", matches)) => {
|
Some(("toolchain", matches)) => {
|
||||||
if matches.get_flag("remove") {
|
setup::toolchain::create(
|
||||||
setup::git_hook::remove_hook();
|
matches.get_flag("force"),
|
||||||
} else {
|
matches.get_flag("release"),
|
||||||
setup::git_hook::install_hook(matches.get_flag("force-override"));
|
matches.get_one::<String>("name").unwrap(),
|
||||||
}
|
);
|
||||||
},
|
},
|
||||||
Some(("vscode-tasks", matches)) => {
|
Some(("vscode-tasks", matches)) => {
|
||||||
if matches.get_flag("remove") {
|
if matches.get_flag("remove") {
|
||||||
|
@ -210,6 +217,19 @@ fn get_clap_config() -> ArgMatches {
|
||||||
.about("Support for setting up your personal development environment")
|
.about("Support for setting up your personal development environment")
|
||||||
.arg_required_else_help(true)
|
.arg_required_else_help(true)
|
||||||
.subcommands([
|
.subcommands([
|
||||||
|
Command::new("git-hook")
|
||||||
|
.about("Add a pre-commit git hook that formats your code to make it look pretty")
|
||||||
|
.args([
|
||||||
|
Arg::new("remove")
|
||||||
|
.long("remove")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("Remove the pre-commit hook added with 'cargo dev setup git-hook'"),
|
||||||
|
Arg::new("force-override")
|
||||||
|
.long("force-override")
|
||||||
|
.short('f')
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("Forces the override of an existing git pre-commit hook"),
|
||||||
|
]),
|
||||||
Command::new("intellij")
|
Command::new("intellij")
|
||||||
.about("Alter dependencies so Intellij Rust can find rustc internals")
|
.about("Alter dependencies so Intellij Rust can find rustc internals")
|
||||||
.args([
|
.args([
|
||||||
|
@ -225,18 +245,23 @@ fn get_clap_config() -> ArgMatches {
|
||||||
.conflicts_with("remove")
|
.conflicts_with("remove")
|
||||||
.required(true),
|
.required(true),
|
||||||
]),
|
]),
|
||||||
Command::new("git-hook")
|
Command::new("toolchain")
|
||||||
.about("Add a pre-commit git hook that formats your code to make it look pretty")
|
.about("Install a rustup toolchain pointing to the local clippy build")
|
||||||
.args([
|
.args([
|
||||||
Arg::new("remove")
|
Arg::new("force")
|
||||||
.long("remove")
|
.long("force")
|
||||||
.action(ArgAction::SetTrue)
|
|
||||||
.help("Remove the pre-commit hook added with 'cargo dev setup git-hook'"),
|
|
||||||
Arg::new("force-override")
|
|
||||||
.long("force-override")
|
|
||||||
.short('f')
|
.short('f')
|
||||||
.action(ArgAction::SetTrue)
|
.action(ArgAction::SetTrue)
|
||||||
.help("Forces the override of an existing git pre-commit hook"),
|
.help("Override an existing toolchain"),
|
||||||
|
Arg::new("release")
|
||||||
|
.long("release")
|
||||||
|
.short('r')
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("Point to --release clippy binaries"),
|
||||||
|
Arg::new("name")
|
||||||
|
.long("name")
|
||||||
|
.default_value("clippy")
|
||||||
|
.help("The name of the created toolchain"),
|
||||||
]),
|
]),
|
||||||
Command::new("vscode-tasks")
|
Command::new("vscode-tasks")
|
||||||
.about("Add several tasks to vscode for formatting, validation and testing")
|
.about("Add several tasks to vscode for formatting, validation and testing")
|
||||||
|
|
|
@ -36,7 +36,6 @@ impl<T> Context for io::Result<T> {
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// This function errors out if the files couldn't be created or written to.
|
/// This function errors out if the files couldn't be created or written to.
|
||||||
#[allow(clippy::missing_panics_doc)]
|
|
||||||
pub fn create(
|
pub fn create(
|
||||||
pass: &String,
|
pass: &String,
|
||||||
lint_name: Option<&String>,
|
lint_name: Option<&String>,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
pub mod git_hook;
|
pub mod git_hook;
|
||||||
pub mod intellij;
|
pub mod intellij;
|
||||||
|
pub mod toolchain;
|
||||||
pub mod vscode;
|
pub mod vscode;
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
75
clippy_dev/src/setup/toolchain.rs
Normal file
75
clippy_dev/src/setup/toolchain.rs
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
use std::env::consts::EXE_SUFFIX;
|
||||||
|
use std::env::current_dir;
|
||||||
|
use std::ffi::OsStr;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
|
use super::verify_inside_clippy_dir;
|
||||||
|
|
||||||
|
pub fn create(force: bool, release: bool, name: &str) {
|
||||||
|
if !verify_inside_clippy_dir() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let rustup_home = std::env::var("RUSTUP_HOME").unwrap();
|
||||||
|
let toolchain = std::env::var("RUSTUP_TOOLCHAIN").unwrap();
|
||||||
|
|
||||||
|
let src = PathBuf::from_iter([&rustup_home, "toolchains", &toolchain]);
|
||||||
|
let dest = PathBuf::from_iter([&rustup_home, "toolchains", name]);
|
||||||
|
|
||||||
|
if dest.exists() {
|
||||||
|
if force {
|
||||||
|
fs::remove_dir_all(&dest).unwrap();
|
||||||
|
} else {
|
||||||
|
println!("{} already exists, pass `--force` to override it", dest.display());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for entry in WalkDir::new(&src) {
|
||||||
|
let entry = entry.unwrap();
|
||||||
|
let relative = entry.path().strip_prefix(&src).unwrap();
|
||||||
|
|
||||||
|
if relative.starts_with("bin")
|
||||||
|
&& matches!(
|
||||||
|
relative.file_stem().and_then(OsStr::to_str),
|
||||||
|
Some("cargo-clippy" | "clippy-driver")
|
||||||
|
)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let target = dest.join(relative);
|
||||||
|
if entry.file_type().is_dir() {
|
||||||
|
fs::create_dir(&target).unwrap();
|
||||||
|
} else {
|
||||||
|
fs::hard_link(entry.path(), target).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
symlink_bin("cargo-clippy", &dest, release);
|
||||||
|
symlink_bin("clippy-driver", &dest, release);
|
||||||
|
|
||||||
|
println!("Created toolchain {name}, use it in other projects with e.g. `cargo +{name} clippy`");
|
||||||
|
println!("Note: This will need to be re-run whenever the Clippy `rust-toolchain` changes");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn symlink_bin(bin: &str, dest: &Path, release: bool) {
|
||||||
|
#[cfg(windows)]
|
||||||
|
use std::os::windows::fs::symlink_file as symlink;
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
use std::os::unix::fs::symlink;
|
||||||
|
|
||||||
|
let profile = if release { "release" } else { "debug" };
|
||||||
|
let file_name = format!("{bin}{EXE_SUFFIX}");
|
||||||
|
|
||||||
|
let mut src = current_dir().unwrap();
|
||||||
|
src.extend(["target", profile, &file_name]);
|
||||||
|
|
||||||
|
let mut dest = dest.to_path_buf();
|
||||||
|
dest.extend(["bin", &file_name]);
|
||||||
|
|
||||||
|
symlink(src, dest).unwrap();
|
||||||
|
}
|
|
@ -56,7 +56,12 @@ impl<'tcx> LateLintPass<'tcx> for ArcWithNonSendSync {
|
||||||
&& let Some(send) = cx.tcx.get_diagnostic_item(sym::Send)
|
&& let Some(send) = cx.tcx.get_diagnostic_item(sym::Send)
|
||||||
&& let Some(sync) = cx.tcx.lang_items().sync_trait()
|
&& let Some(sync) = cx.tcx.lang_items().sync_trait()
|
||||||
&& let [is_send, is_sync] = [send, sync].map(|id| implements_trait(cx, arg_ty, id, &[]))
|
&& let [is_send, is_sync] = [send, sync].map(|id| implements_trait(cx, arg_ty, id, &[]))
|
||||||
&& !(is_send && is_sync)
|
&& let reason = match (is_send, is_sync) {
|
||||||
|
(false, false) => "neither `Send` nor `Sync`",
|
||||||
|
(false, true) => "not `Send`",
|
||||||
|
(true, false) => "not `Sync`",
|
||||||
|
_ => return,
|
||||||
|
}
|
||||||
&& !is_from_proc_macro(cx, expr)
|
&& !is_from_proc_macro(cx, expr)
|
||||||
{
|
{
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
|
@ -66,21 +71,12 @@ impl<'tcx> LateLintPass<'tcx> for ArcWithNonSendSync {
|
||||||
"usage of an `Arc` that is not `Send` and `Sync`",
|
"usage of an `Arc` that is not `Send` and `Sync`",
|
||||||
|diag| {
|
|diag| {
|
||||||
with_forced_trimmed_paths!({
|
with_forced_trimmed_paths!({
|
||||||
diag.note(format!("`Arc<{arg_ty}>` is not `Send` and `Sync` as:"));
|
|
||||||
|
|
||||||
if !is_send {
|
|
||||||
diag.note(format!("- the trait `Send` is not implemented for `{arg_ty}`"));
|
|
||||||
}
|
|
||||||
if !is_sync {
|
|
||||||
diag.note(format!("- the trait `Sync` is not implemented for `{arg_ty}`"));
|
|
||||||
}
|
|
||||||
|
|
||||||
diag.help("consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types");
|
|
||||||
|
|
||||||
diag.note("if you intend to use `Arc` with `Send` and `Sync` traits");
|
|
||||||
|
|
||||||
diag.note(format!(
|
diag.note(format!(
|
||||||
"wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `{arg_ty}`"
|
"`Arc<{arg_ty}>` is not `Send` and `Sync` as `{arg_ty}` is {reason}"
|
||||||
|
));
|
||||||
|
diag.help("if the `Arc` will not used be across threads replace it with an `Rc`");
|
||||||
|
diag.help(format!(
|
||||||
|
"otherwise make `{arg_ty}` `Send` and `Sync` or consider a wrapper type such as `Mutex`"
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,12 +2,12 @@ use super::DUPLICATED_ATTRIBUTES;
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use rustc_ast::{Attribute, MetaItem};
|
use rustc_ast::{Attribute, MetaItem};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_lint::EarlyContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_span::{sym, Span};
|
use rustc_span::{sym, Span};
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
|
|
||||||
fn emit_if_duplicated(
|
fn emit_if_duplicated(
|
||||||
cx: &EarlyContext<'_>,
|
cx: &LateContext<'_>,
|
||||||
attr: &MetaItem,
|
attr: &MetaItem,
|
||||||
attr_paths: &mut FxHashMap<String, Span>,
|
attr_paths: &mut FxHashMap<String, Span>,
|
||||||
complete_path: String,
|
complete_path: String,
|
||||||
|
@ -26,7 +26,7 @@ fn emit_if_duplicated(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_duplicated_attr(
|
fn check_duplicated_attr(
|
||||||
cx: &EarlyContext<'_>,
|
cx: &LateContext<'_>,
|
||||||
attr: &MetaItem,
|
attr: &MetaItem,
|
||||||
attr_paths: &mut FxHashMap<String, Span>,
|
attr_paths: &mut FxHashMap<String, Span>,
|
||||||
parent: &mut Vec<String>,
|
parent: &mut Vec<String>,
|
||||||
|
@ -64,7 +64,7 @@ fn check_duplicated_attr(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check(cx: &EarlyContext<'_>, attrs: &[Attribute]) {
|
pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
|
||||||
let mut attr_paths = FxHashMap::default();
|
let mut attr_paths = FxHashMap::default();
|
||||||
|
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
|
|
|
@ -17,7 +17,7 @@ mod useless_attribute;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use clippy_config::msrvs::Msrv;
|
use clippy_config::msrvs::Msrv;
|
||||||
use rustc_ast::{Attribute, Crate, MetaItemKind, NestedMetaItem};
|
use rustc_ast::{Attribute, MetaItemKind, NestedMetaItem};
|
||||||
use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
|
use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
|
||||||
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
|
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
|
||||||
use rustc_session::{declare_lint_pass, impl_lint_pass};
|
use rustc_session::{declare_lint_pass, impl_lint_pass};
|
||||||
|
@ -534,11 +534,13 @@ declare_lint_pass!(Attributes => [
|
||||||
BLANKET_CLIPPY_RESTRICTION_LINTS,
|
BLANKET_CLIPPY_RESTRICTION_LINTS,
|
||||||
SHOULD_PANIC_WITHOUT_EXPECT,
|
SHOULD_PANIC_WITHOUT_EXPECT,
|
||||||
MIXED_ATTRIBUTES_STYLE,
|
MIXED_ATTRIBUTES_STYLE,
|
||||||
|
DUPLICATED_ATTRIBUTES,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for Attributes {
|
impl<'tcx> LateLintPass<'tcx> for Attributes {
|
||||||
fn check_crate(&mut self, cx: &LateContext<'tcx>) {
|
fn check_crate(&mut self, cx: &LateContext<'tcx>) {
|
||||||
blanket_clippy_restriction_lints::check_command_line(cx);
|
blanket_clippy_restriction_lints::check_command_line(cx);
|
||||||
|
duplicated_attributes::check(cx, cx.tcx.hir().krate_attrs());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_attribute(&mut self, cx: &LateContext<'tcx>, attr: &'tcx Attribute) {
|
fn check_attribute(&mut self, cx: &LateContext<'tcx>, attr: &'tcx Attribute) {
|
||||||
|
@ -578,6 +580,7 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
mixed_attributes_style::check(cx, item.span, attrs);
|
mixed_attributes_style::check(cx, item.span, attrs);
|
||||||
|
duplicated_attributes::check(cx, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
|
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
|
||||||
|
@ -606,17 +609,11 @@ impl_lint_pass!(EarlyAttributes => [
|
||||||
MAYBE_MISUSED_CFG,
|
MAYBE_MISUSED_CFG,
|
||||||
DEPRECATED_CLIPPY_CFG_ATTR,
|
DEPRECATED_CLIPPY_CFG_ATTR,
|
||||||
UNNECESSARY_CLIPPY_CFG,
|
UNNECESSARY_CLIPPY_CFG,
|
||||||
DUPLICATED_ATTRIBUTES,
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
impl EarlyLintPass for EarlyAttributes {
|
impl EarlyLintPass for EarlyAttributes {
|
||||||
fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) {
|
|
||||||
duplicated_attributes::check(cx, &krate.attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
|
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
|
||||||
empty_line_after::check(cx, item);
|
empty_line_after::check(cx, item);
|
||||||
duplicated_attributes::check(cx, &item.attrs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
|
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||||
|
|
|
@ -346,11 +346,18 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
.and_then(|op| {
|
.and_then(|op| {
|
||||||
Some(format!(
|
let lhs_snippet = snippet_opt(cx, lhs.span)?;
|
||||||
"{}{op}{}",
|
let rhs_snippet = snippet_opt(cx, rhs.span)?;
|
||||||
snippet_opt(cx, lhs.span)?,
|
|
||||||
snippet_opt(cx, rhs.span)?
|
if !(lhs_snippet.starts_with('(') && lhs_snippet.ends_with(')')) {
|
||||||
))
|
if let (ExprKind::Cast(..), BinOpKind::Ge) = (&lhs.kind, binop.node) {
|
||||||
|
// e.g. `(a as u64) < b`. Without the parens the `<` is
|
||||||
|
// interpreted as a start of generic arguments for `u64`
|
||||||
|
return Some(format!("({lhs_snippet}){op}{rhs_snippet}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(format!("{lhs_snippet}{op}{rhs_snippet}"))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
ExprKind::MethodCall(path, receiver, [], _) => {
|
ExprKind::MethodCall(path, receiver, [], _) => {
|
||||||
|
|
|
@ -754,11 +754,7 @@ impl_lint_pass!(Casts => [
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for Casts {
|
impl<'tcx> LateLintPass<'tcx> for Casts {
|
||||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||||
if !in_external_macro(cx.sess(), expr.span) {
|
if in_external_macro(cx.sess(), expr.span) {
|
||||||
ptr_as_ptr::check(cx, expr, &self.msrv);
|
|
||||||
}
|
|
||||||
|
|
||||||
if expr.span.from_expansion() {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -771,7 +767,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
|
||||||
cx.typeck_results().expr_ty(expr),
|
cx.typeck_results().expr_ty(expr),
|
||||||
);
|
);
|
||||||
|
|
||||||
if unnecessary_cast::check(cx, expr, cast_expr, cast_from, cast_to) {
|
if !expr.span.from_expansion() && unnecessary_cast::check(cx, expr, cast_expr, cast_from, cast_to) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cast_slice_from_raw_parts::check(cx, expr, cast_expr, cast_to, &self.msrv);
|
cast_slice_from_raw_parts::check(cx, expr, cast_expr, cast_to, &self.msrv);
|
||||||
|
@ -782,7 +778,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
|
||||||
fn_to_numeric_cast_with_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
|
fn_to_numeric_cast_with_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
|
||||||
zero_ptr::check(cx, expr, cast_expr, cast_to_hir);
|
zero_ptr::check(cx, expr, cast_expr, cast_to_hir);
|
||||||
|
|
||||||
if cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) {
|
if cast_to.is_numeric() {
|
||||||
cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to, cast_to_hir.span);
|
cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to, cast_to_hir.span);
|
||||||
if cast_from.is_numeric() {
|
if cast_from.is_numeric() {
|
||||||
cast_possible_wrap::check(cx, expr, cast_from, cast_to);
|
cast_possible_wrap::check(cx, expr, cast_from, cast_to);
|
||||||
|
|
|
@ -1016,9 +1016,18 @@ fn report<'tcx>(
|
||||||
},
|
},
|
||||||
_ => (0, false),
|
_ => (0, false),
|
||||||
};
|
};
|
||||||
|
let is_in_tuple = matches!(
|
||||||
|
get_parent_expr(cx, data.first_expr),
|
||||||
|
Some(Expr {
|
||||||
|
kind: ExprKind::Tup(..),
|
||||||
|
..
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
let sugg = if !snip_is_macro
|
let sugg = if !snip_is_macro
|
||||||
&& (calls_field || expr.precedence().order() < precedence)
|
&& (calls_field || expr.precedence().order() < precedence)
|
||||||
&& !has_enclosing_paren(&snip)
|
&& !has_enclosing_paren(&snip)
|
||||||
|
&& !is_in_tuple
|
||||||
{
|
{
|
||||||
format!("({snip})")
|
format!("({snip})")
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -132,7 +132,7 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// ### Why is this bad?
|
/// ### Why is this bad?
|
||||||
/// Deriving `serde::Deserialize` will create a constructor
|
/// Deriving `serde::Deserialize` will create a constructor
|
||||||
/// that may violate invariants hold by another constructor.
|
/// that may violate invariants held by another constructor.
|
||||||
///
|
///
|
||||||
/// ### Example
|
/// ### Example
|
||||||
/// ```rust,ignore
|
/// ```rust,ignore
|
||||||
|
|
|
@ -11,7 +11,7 @@ use super::{DocHeaders, MISSING_ERRORS_DOC, MISSING_PANICS_DOC, MISSING_SAFETY_D
|
||||||
pub fn check(
|
pub fn check(
|
||||||
cx: &LateContext<'_>,
|
cx: &LateContext<'_>,
|
||||||
owner_id: OwnerId,
|
owner_id: OwnerId,
|
||||||
sig: &FnSig<'_>,
|
sig: FnSig<'_>,
|
||||||
headers: DocHeaders,
|
headers: DocHeaders,
|
||||||
body_id: Option<BodyId>,
|
body_id: Option<BodyId>,
|
||||||
panic_span: Option<Span>,
|
panic_span: Option<Span>,
|
||||||
|
|
|
@ -3,7 +3,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
|
||||||
use clippy_utils::macros::{is_panic, root_macro_call_first_node};
|
use clippy_utils::macros::{is_panic, root_macro_call_first_node};
|
||||||
use clippy_utils::ty::is_type_diagnostic_item;
|
use clippy_utils::ty::is_type_diagnostic_item;
|
||||||
use clippy_utils::visitors::Visitable;
|
use clippy_utils::visitors::Visitable;
|
||||||
use clippy_utils::{is_entrypoint_fn, method_chain_args};
|
use clippy_utils::{is_entrypoint_fn, is_trait_impl_item, method_chain_args};
|
||||||
use pulldown_cmark::Event::{
|
use pulldown_cmark::Event::{
|
||||||
Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text,
|
Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text,
|
||||||
};
|
};
|
||||||
|
@ -11,9 +11,8 @@ use pulldown_cmark::Tag::{BlockQuote, CodeBlock, Heading, Item, Link, Paragraph}
|
||||||
use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options};
|
use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options};
|
||||||
use rustc_ast::ast::Attribute;
|
use rustc_ast::ast::Attribute;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_hir as hir;
|
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
use rustc_hir::{AnonConst, Expr};
|
use rustc_hir::{AnonConst, Expr, ImplItemKind, ItemKind, Node, TraitItemKind, Unsafety};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_middle::lint::in_external_macro;
|
||||||
|
@ -366,7 +365,6 @@ declare_clippy_lint! {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Documentation {
|
pub struct Documentation {
|
||||||
valid_idents: FxHashSet<String>,
|
valid_idents: FxHashSet<String>,
|
||||||
in_trait_impl: bool,
|
|
||||||
check_private_items: bool,
|
check_private_items: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,7 +372,6 @@ impl Documentation {
|
||||||
pub fn new(valid_idents: &[String], check_private_items: bool) -> Self {
|
pub fn new(valid_idents: &[String], check_private_items: bool) -> Self {
|
||||||
Self {
|
Self {
|
||||||
valid_idents: valid_idents.iter().cloned().collect(),
|
valid_idents: valid_idents.iter().cloned().collect(),
|
||||||
in_trait_impl: false,
|
|
||||||
check_private_items,
|
check_private_items,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -394,36 +391,72 @@ impl_lint_pass!(Documentation => [
|
||||||
]);
|
]);
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for Documentation {
|
impl<'tcx> LateLintPass<'tcx> for Documentation {
|
||||||
fn check_crate(&mut self, cx: &LateContext<'tcx>) {
|
fn check_attributes(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) {
|
||||||
let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID);
|
|
||||||
check_attrs(cx, &self.valid_idents, attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_variant(&mut self, cx: &LateContext<'tcx>, variant: &'tcx hir::Variant<'tcx>) {
|
|
||||||
let attrs = cx.tcx.hir().attrs(variant.hir_id);
|
|
||||||
check_attrs(cx, &self.valid_idents, attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_field_def(&mut self, cx: &LateContext<'tcx>, variant: &'tcx hir::FieldDef<'tcx>) {
|
|
||||||
let attrs = cx.tcx.hir().attrs(variant.hir_id);
|
|
||||||
check_attrs(cx, &self.valid_idents, attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
|
|
||||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
|
||||||
let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else {
|
let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
match item.kind {
|
match cx.tcx.hir_node(cx.last_node_with_lint_attrs) {
|
||||||
hir::ItemKind::Fn(ref sig, _, body_id) => {
|
Node::Item(item) => match item.kind {
|
||||||
if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) {
|
ItemKind::Fn(sig, _, body_id) => {
|
||||||
let body = cx.tcx.hir().body(body_id);
|
if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) {
|
||||||
|
let body = cx.tcx.hir().body(body_id);
|
||||||
|
|
||||||
let panic_span = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value);
|
let panic_span = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value);
|
||||||
|
missing_headers::check(
|
||||||
|
cx,
|
||||||
|
item.owner_id,
|
||||||
|
sig,
|
||||||
|
headers,
|
||||||
|
Some(body_id),
|
||||||
|
panic_span,
|
||||||
|
self.check_private_items,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ItemKind::Trait(_, unsafety, ..) => match (headers.safety, unsafety) {
|
||||||
|
(false, Unsafety::Unsafe) => span_lint(
|
||||||
|
cx,
|
||||||
|
MISSING_SAFETY_DOC,
|
||||||
|
cx.tcx.def_span(item.owner_id),
|
||||||
|
"docs for unsafe trait missing `# Safety` section",
|
||||||
|
),
|
||||||
|
(true, Unsafety::Normal) => span_lint(
|
||||||
|
cx,
|
||||||
|
UNNECESSARY_SAFETY_DOC,
|
||||||
|
cx.tcx.def_span(item.owner_id),
|
||||||
|
"docs for safe trait have unnecessary `# Safety` section",
|
||||||
|
),
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
|
Node::TraitItem(trait_item) => {
|
||||||
|
if let TraitItemKind::Fn(sig, ..) = trait_item.kind
|
||||||
|
&& !in_external_macro(cx.tcx.sess, trait_item.span)
|
||||||
|
{
|
||||||
missing_headers::check(
|
missing_headers::check(
|
||||||
cx,
|
cx,
|
||||||
item.owner_id,
|
trait_item.owner_id,
|
||||||
|
sig,
|
||||||
|
headers,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
self.check_private_items,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Node::ImplItem(impl_item) => {
|
||||||
|
if let ImplItemKind::Fn(sig, body_id) = impl_item.kind
|
||||||
|
&& !in_external_macro(cx.tcx.sess, impl_item.span)
|
||||||
|
&& !is_trait_impl_item(cx, impl_item.hir_id())
|
||||||
|
{
|
||||||
|
let body = cx.tcx.hir().body(body_id);
|
||||||
|
|
||||||
|
let panic_span = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(impl_item.owner_id), body.value);
|
||||||
|
missing_headers::check(
|
||||||
|
cx,
|
||||||
|
impl_item.owner_id,
|
||||||
sig,
|
sig,
|
||||||
headers,
|
headers,
|
||||||
Some(body_id),
|
Some(body_id),
|
||||||
|
@ -432,67 +465,7 @@ impl<'tcx> LateLintPass<'tcx> for Documentation {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hir::ItemKind::Impl(impl_) => {
|
_ => {},
|
||||||
self.in_trait_impl = impl_.of_trait.is_some();
|
|
||||||
},
|
|
||||||
hir::ItemKind::Trait(_, unsafety, ..) => match (headers.safety, unsafety) {
|
|
||||||
(false, hir::Unsafety::Unsafe) => span_lint(
|
|
||||||
cx,
|
|
||||||
MISSING_SAFETY_DOC,
|
|
||||||
cx.tcx.def_span(item.owner_id),
|
|
||||||
"docs for unsafe trait missing `# Safety` section",
|
|
||||||
),
|
|
||||||
(true, hir::Unsafety::Normal) => span_lint(
|
|
||||||
cx,
|
|
||||||
UNNECESSARY_SAFETY_DOC,
|
|
||||||
cx.tcx.def_span(item.owner_id),
|
|
||||||
"docs for safe trait have unnecessary `# Safety` section",
|
|
||||||
),
|
|
||||||
_ => (),
|
|
||||||
},
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_item_post(&mut self, _cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
|
|
||||||
if let hir::ItemKind::Impl { .. } = item.kind {
|
|
||||||
self.in_trait_impl = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
|
|
||||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
|
||||||
let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind {
|
|
||||||
if !in_external_macro(cx.tcx.sess, item.span) {
|
|
||||||
missing_headers::check(cx, item.owner_id, sig, headers, None, None, self.check_private_items);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) {
|
|
||||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
|
||||||
let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if self.in_trait_impl || in_external_macro(cx.tcx.sess, item.span) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if let hir::ImplItemKind::Fn(ref sig, body_id) = item.kind {
|
|
||||||
let body = cx.tcx.hir().body(body_id);
|
|
||||||
|
|
||||||
let panic_span = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value);
|
|
||||||
missing_headers::check(
|
|
||||||
cx,
|
|
||||||
item.owner_id,
|
|
||||||
sig,
|
|
||||||
headers,
|
|
||||||
Some(body_id),
|
|
||||||
panic_span,
|
|
||||||
self.check_private_items,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@ use clippy_utils::{is_expn_of, is_lint_allowed, path_to_local};
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::HirId;
|
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
|
use rustc_hir::HirId;
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
|
|
|
@ -5,6 +5,7 @@ use clippy_utils::is_bool;
|
||||||
use clippy_utils::macros::span_is_local;
|
use clippy_utils::macros::span_is_local;
|
||||||
use clippy_utils::source::is_present_in_source;
|
use clippy_utils::source::is_present_in_source;
|
||||||
use clippy_utils::str_utils::{camel_case_split, count_match_end, count_match_start, to_camel_case, to_snake_case};
|
use clippy_utils::str_utils::{camel_case_split, count_match_end, count_match_start, to_camel_case, to_snake_case};
|
||||||
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_hir::{EnumDef, FieldDef, Item, ItemKind, OwnerId, Variant, VariantData};
|
use rustc_hir::{EnumDef, FieldDef, Item, ItemKind, OwnerId, Variant, VariantData};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_session::impl_lint_pass;
|
use rustc_session::impl_lint_pass;
|
||||||
|
@ -147,6 +148,7 @@ pub struct ItemNameRepetitions {
|
||||||
struct_threshold: u64,
|
struct_threshold: u64,
|
||||||
avoid_breaking_exported_api: bool,
|
avoid_breaking_exported_api: bool,
|
||||||
allow_private_module_inception: bool,
|
allow_private_module_inception: bool,
|
||||||
|
allowed_prefixes: FxHashSet<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ItemNameRepetitions {
|
impl ItemNameRepetitions {
|
||||||
|
@ -156,6 +158,7 @@ impl ItemNameRepetitions {
|
||||||
struct_threshold: u64,
|
struct_threshold: u64,
|
||||||
avoid_breaking_exported_api: bool,
|
avoid_breaking_exported_api: bool,
|
||||||
allow_private_module_inception: bool,
|
allow_private_module_inception: bool,
|
||||||
|
allowed_prefixes: &[String],
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
modules: Vec::new(),
|
modules: Vec::new(),
|
||||||
|
@ -163,8 +166,13 @@ impl ItemNameRepetitions {
|
||||||
struct_threshold,
|
struct_threshold,
|
||||||
avoid_breaking_exported_api,
|
avoid_breaking_exported_api,
|
||||||
allow_private_module_inception,
|
allow_private_module_inception,
|
||||||
|
allowed_prefixes: allowed_prefixes.iter().map(|s| to_camel_case(s)).collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_allowed_prefix(&self, prefix: &str) -> bool {
|
||||||
|
self.allowed_prefixes.contains(prefix)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_lint_pass!(ItemNameRepetitions => [
|
impl_lint_pass!(ItemNameRepetitions => [
|
||||||
|
@ -423,7 +431,9 @@ impl LateLintPass<'_> for ItemNameRepetitions {
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if rmatching.char_count == nchars {
|
if rmatching.char_count == nchars
|
||||||
|
&& !self.is_allowed_prefix(&item_camel[..item_camel.len() - rmatching.byte_count])
|
||||||
|
{
|
||||||
span_lint(
|
span_lint(
|
||||||
cx,
|
cx,
|
||||||
MODULE_NAME_REPETITIONS,
|
MODULE_NAME_REPETITIONS,
|
||||||
|
|
|
@ -17,7 +17,7 @@ declare_clippy_lint! {
|
||||||
/// `std::<float>::EPSILON`, etc.
|
/// `std::<float>::EPSILON`, etc.
|
||||||
///
|
///
|
||||||
/// ### Why is this bad?
|
/// ### Why is this bad?
|
||||||
/// All of these have been superceded by the associated constants on their respective types,
|
/// All of these have been superseded by the associated constants on their respective types,
|
||||||
/// such as `i128::MAX`. These legacy items may be deprecated in a future version of rust.
|
/// such as `i128::MAX`. These legacy items may be deprecated in a future version of rust.
|
||||||
///
|
///
|
||||||
/// ### Example
|
/// ### Example
|
||||||
|
|
|
@ -594,6 +594,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
|
||||||
pub_underscore_fields_behavior,
|
pub_underscore_fields_behavior,
|
||||||
ref allowed_duplicate_crates,
|
ref allowed_duplicate_crates,
|
||||||
allow_comparison_to_zero,
|
allow_comparison_to_zero,
|
||||||
|
ref allowed_prefixes,
|
||||||
|
|
||||||
blacklisted_names: _,
|
blacklisted_names: _,
|
||||||
cyclomatic_complexity_threshold: _,
|
cyclomatic_complexity_threshold: _,
|
||||||
|
@ -864,6 +865,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
|
||||||
struct_field_name_threshold,
|
struct_field_name_threshold,
|
||||||
avoid_breaking_exported_api,
|
avoid_breaking_exported_api,
|
||||||
allow_private_module_inception,
|
allow_private_module_inception,
|
||||||
|
allowed_prefixes,
|
||||||
))
|
))
|
||||||
});
|
});
|
||||||
store.register_early_pass(|| Box::new(tabs_in_doc_comments::TabsInDocComments));
|
store.register_early_pass(|| Box::new(tabs_in_doc_comments::TabsInDocComments));
|
||||||
|
|
|
@ -291,10 +291,7 @@ fn elision_suggestions(
|
||||||
}) => {
|
}) => {
|
||||||
// expand `&'a T` to `&'a T`
|
// expand `&'a T` to `&'a T`
|
||||||
// ^^ ^^^
|
// ^^ ^^^
|
||||||
let span = cx
|
let span = cx.sess().source_map().span_extend_while_whitespace(usage.ident.span);
|
||||||
.sess()
|
|
||||||
.source_map()
|
|
||||||
.span_extend_while_whitespace(usage.ident.span);
|
|
||||||
|
|
||||||
(span, String::new())
|
(span, String::new())
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
use clippy_utils::sugg::Sugg;
|
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::def::Res;
|
use rustc_hir::def::Res;
|
||||||
use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, MatchSource, Pat, PatKind, QPath};
|
use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, MatchSource, Pat, PatKind, QPath};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
|
use rustc_middle::ty::GenericArgKind;
|
||||||
use rustc_session::declare_lint_pass;
|
use rustc_session::declare_lint_pass;
|
||||||
use rustc_span::sym;
|
use rustc_span::sym;
|
||||||
|
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::higher::IfLetOrMatch;
|
||||||
|
use clippy_utils::sugg::Sugg;
|
||||||
use clippy_utils::ty::implements_trait;
|
use clippy_utils::ty::implements_trait;
|
||||||
use clippy_utils::{in_constant, is_default_equivalent, peel_blocks, span_contains_comment};
|
use clippy_utils::{in_constant, is_default_equivalent, peel_blocks, span_contains_comment};
|
||||||
|
|
||||||
|
@ -105,19 +106,39 @@ fn get_some_and_none_bodies<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
let ExprKind::Match(match_expr, [arm1, arm2], MatchSource::Normal | MatchSource::ForLoopDesugar) = expr.kind else {
|
fn handle<'tcx>(cx: &LateContext<'tcx>, if_let_or_match: IfLetOrMatch<'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||||
return false;
|
// Get expr_name ("if let" or "match" depending on kind of expression), the condition, the body for
|
||||||
|
// the some arm, the body for the none arm and the binding id of the some arm
|
||||||
|
let (expr_name, condition, body_some, body_none, binding_id) = match if_let_or_match {
|
||||||
|
IfLetOrMatch::Match(condition, [arm1, arm2], MatchSource::Normal | MatchSource::ForLoopDesugar)
|
||||||
|
// Make sure there are no guards to keep things simple
|
||||||
|
if arm1.guard.is_none()
|
||||||
|
&& arm2.guard.is_none()
|
||||||
|
// Get the some and none bodies and the binding id of the some arm
|
||||||
|
&& let Some(((body_some, binding_id), body_none)) = get_some_and_none_bodies(cx, arm1, arm2) =>
|
||||||
|
{
|
||||||
|
("match", condition, body_some, body_none, binding_id)
|
||||||
|
},
|
||||||
|
IfLetOrMatch::IfLet(condition, pat, if_expr, Some(else_expr), _)
|
||||||
|
if let Some(binding_id) = get_some(cx, pat) =>
|
||||||
|
{
|
||||||
|
("if let", condition, if_expr, else_expr, binding_id)
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
// All other cases (match with number of arms != 2, if let without else, etc.)
|
||||||
|
return;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
// We don't want conditions on the arms to simplify things.
|
|
||||||
if arm1.guard.is_none()
|
// We check if the return type of the expression implements Default.
|
||||||
&& arm2.guard.is_none()
|
let expr_type = cx.typeck_results().expr_ty(expr);
|
||||||
// We check that the returned type implements the `Default` trait.
|
if let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default)
|
||||||
&& let match_ty = cx.typeck_results().expr_ty(expr)
|
&& implements_trait(cx, expr_type, default_trait_id, &[])
|
||||||
&& let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default)
|
// We check if the initial condition implements Default.
|
||||||
&& implements_trait(cx, match_ty, default_trait_id, &[])
|
&& let Some(condition_ty) = cx.typeck_results().expr_ty(condition).walk().nth(1)
|
||||||
// We now get the bodies for both the `Some` and `None` arms.
|
&& let GenericArgKind::Type(condition_ty) = condition_ty.unpack()
|
||||||
&& let Some(((body_some, binding_id), body_none)) = get_some_and_none_bodies(cx, arm1, arm2)
|
&& implements_trait(cx, condition_ty, default_trait_id, &[])
|
||||||
// We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`.
|
// We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`.
|
||||||
&& let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(body_some).kind
|
&& let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(body_some).kind
|
||||||
&& let Res::Local(local_id) = path.res
|
&& let Res::Local(local_id) = path.res
|
||||||
|
@ -125,8 +146,9 @@ fn handle_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
|
||||||
// We now check the `None` arm is calling a method equivalent to `Default::default`.
|
// We now check the `None` arm is calling a method equivalent to `Default::default`.
|
||||||
&& let body_none = peel_blocks(body_none)
|
&& let body_none = peel_blocks(body_none)
|
||||||
&& is_default_equivalent(cx, body_none)
|
&& is_default_equivalent(cx, body_none)
|
||||||
&& let Some(receiver) = Sugg::hir_opt(cx, match_expr).map(Sugg::maybe_par)
|
&& let Some(receiver) = Sugg::hir_opt(cx, condition).map(Sugg::maybe_par)
|
||||||
{
|
{
|
||||||
|
// Machine applicable only if there are no comments present
|
||||||
let applicability = if span_contains_comment(cx.sess().source_map(), expr.span) {
|
let applicability = if span_contains_comment(cx.sess().source_map(), expr.span) {
|
||||||
Applicability::MaybeIncorrect
|
Applicability::MaybeIncorrect
|
||||||
} else {
|
} else {
|
||||||
|
@ -136,48 +158,12 @@ fn handle_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
|
||||||
cx,
|
cx,
|
||||||
MANUAL_UNWRAP_OR_DEFAULT,
|
MANUAL_UNWRAP_OR_DEFAULT,
|
||||||
expr.span,
|
expr.span,
|
||||||
"match can be simplified with `.unwrap_or_default()`",
|
format!("{expr_name} can be simplified with `.unwrap_or_default()`"),
|
||||||
"replace it with",
|
"replace it with",
|
||||||
format!("{receiver}.unwrap_or_default()"),
|
format!("{receiver}.unwrap_or_default()"),
|
||||||
applicability,
|
applicability,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_if_let<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
|
|
||||||
if let ExprKind::If(cond, if_block, Some(else_expr)) = expr.kind
|
|
||||||
&& let ExprKind::Let(let_) = cond.kind
|
|
||||||
&& let ExprKind::Block(_, _) = else_expr.kind
|
|
||||||
// We check that the returned type implements the `Default` trait.
|
|
||||||
&& let match_ty = cx.typeck_results().expr_ty(expr)
|
|
||||||
&& let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default)
|
|
||||||
&& implements_trait(cx, match_ty, default_trait_id, &[])
|
|
||||||
&& let Some(binding_id) = get_some(cx, let_.pat)
|
|
||||||
// We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`.
|
|
||||||
&& let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(if_block).kind
|
|
||||||
&& let Res::Local(local_id) = path.res
|
|
||||||
&& local_id == binding_id
|
|
||||||
// We now check the `None` arm is calling a method equivalent to `Default::default`.
|
|
||||||
&& let body_else = peel_blocks(else_expr)
|
|
||||||
&& is_default_equivalent(cx, body_else)
|
|
||||||
&& let Some(if_let_expr_snippet) = snippet_opt(cx, let_.init.span)
|
|
||||||
{
|
|
||||||
let applicability = if span_contains_comment(cx.sess().source_map(), expr.span) {
|
|
||||||
Applicability::MaybeIncorrect
|
|
||||||
} else {
|
|
||||||
Applicability::MachineApplicable
|
|
||||||
};
|
|
||||||
span_lint_and_sugg(
|
|
||||||
cx,
|
|
||||||
MANUAL_UNWRAP_OR_DEFAULT,
|
|
||||||
expr.span,
|
|
||||||
"if let can be simplified with `.unwrap_or_default()`",
|
|
||||||
"replace it with",
|
|
||||||
format!("{if_let_expr_snippet}.unwrap_or_default()"),
|
|
||||||
applicability,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for ManualUnwrapOrDefault {
|
impl<'tcx> LateLintPass<'tcx> for ManualUnwrapOrDefault {
|
||||||
|
@ -185,8 +171,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualUnwrapOrDefault {
|
||||||
if expr.span.from_expansion() || in_constant(cx, expr.hir_id) {
|
if expr.span.from_expansion() || in_constant(cx, expr.hir_id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if !handle_match(cx, expr) {
|
// Call handle only if the expression is `if let` or `match`
|
||||||
handle_if_let(cx, expr);
|
if let Some(if_let_or_match) = IfLetOrMatch::parse(cx, expr) {
|
||||||
|
handle(cx, if_let_or_match, expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3938,7 +3938,6 @@ declare_clippy_lint! {
|
||||||
/// This lint cannot detect if the split is intentionally restricted to a single type of newline (`"\n"` or
|
/// This lint cannot detect if the split is intentionally restricted to a single type of newline (`"\n"` or
|
||||||
/// `"\r\n"`), for example during the parsing of a specific file format in which precisely one newline type is
|
/// `"\r\n"`), for example during the parsing of a specific file format in which precisely one newline type is
|
||||||
/// valid.
|
/// valid.
|
||||||
/// ```
|
|
||||||
#[clippy::version = "1.77.0"]
|
#[clippy::version = "1.77.0"]
|
||||||
pub STR_SPLIT_AT_NEWLINE,
|
pub STR_SPLIT_AT_NEWLINE,
|
||||||
pedantic,
|
pedantic,
|
||||||
|
|
|
@ -2,7 +2,8 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
|
||||||
use clippy_utils::source::{snippet, snippet_with_applicability};
|
use clippy_utils::source::{snippet, snippet_with_applicability};
|
||||||
use clippy_utils::sugg::deref_closure_args;
|
use clippy_utils::sugg::deref_closure_args;
|
||||||
use clippy_utils::ty::is_type_lang_item;
|
use clippy_utils::ty::is_type_lang_item;
|
||||||
use clippy_utils::{is_trait_method, strip_pat_refs};
|
use clippy_utils::{get_parent_expr, is_trait_method, strip_pat_refs};
|
||||||
|
use hir::ExprKind;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::PatKind;
|
use rustc_hir::PatKind;
|
||||||
|
@ -35,7 +36,7 @@ pub(super) fn check<'tcx>(
|
||||||
// suggest `any(|..| *..)` instead of `any(|..| **..)` for `find(|..| **..).is_some()`
|
// suggest `any(|..| *..)` instead of `any(|..| **..)` for `find(|..| **..).is_some()`
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
let any_search_snippet = if search_method == "find"
|
let any_search_snippet = if search_method == "find"
|
||||||
&& let hir::ExprKind::Closure(&hir::Closure { body, .. }) = search_arg.kind
|
&& let ExprKind::Closure(&hir::Closure { body, .. }) = search_arg.kind
|
||||||
&& let closure_body = cx.tcx.hir().body(body)
|
&& let closure_body = cx.tcx.hir().body(body)
|
||||||
&& let Some(closure_arg) = closure_body.params.first()
|
&& let Some(closure_arg) = closure_body.params.first()
|
||||||
{
|
{
|
||||||
|
@ -72,16 +73,24 @@ pub(super) fn check<'tcx>(
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let iter = snippet(cx, search_recv.span, "..");
|
let iter = snippet(cx, search_recv.span, "..");
|
||||||
|
let sugg = if is_receiver_of_method_call(cx, expr) {
|
||||||
|
format!(
|
||||||
|
"(!{iter}.any({}))",
|
||||||
|
any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
"!{iter}.any({})",
|
||||||
|
any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
|
||||||
|
)
|
||||||
|
};
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
SEARCH_IS_SOME,
|
SEARCH_IS_SOME,
|
||||||
expr.span,
|
expr.span,
|
||||||
msg,
|
msg,
|
||||||
"consider using",
|
"consider using",
|
||||||
format!(
|
sugg,
|
||||||
"!{iter}.any({})",
|
|
||||||
any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
|
|
||||||
),
|
|
||||||
applicability,
|
applicability,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -127,13 +136,18 @@ pub(super) fn check<'tcx>(
|
||||||
let string = snippet(cx, search_recv.span, "..");
|
let string = snippet(cx, search_recv.span, "..");
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
let find_arg = snippet_with_applicability(cx, search_arg.span, "..", &mut applicability);
|
let find_arg = snippet_with_applicability(cx, search_arg.span, "..", &mut applicability);
|
||||||
|
let sugg = if is_receiver_of_method_call(cx, expr) {
|
||||||
|
format!("(!{string}.contains({find_arg}))")
|
||||||
|
} else {
|
||||||
|
format!("!{string}.contains({find_arg})")
|
||||||
|
};
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
SEARCH_IS_SOME,
|
SEARCH_IS_SOME,
|
||||||
expr.span,
|
expr.span,
|
||||||
msg,
|
msg,
|
||||||
"consider using",
|
"consider using",
|
||||||
format!("!{string}.contains({find_arg})"),
|
sugg,
|
||||||
applicability,
|
applicability,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -142,3 +156,13 @@ pub(super) fn check<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_receiver_of_method_call(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
|
||||||
|
if let Some(parent_expr) = get_parent_expr(cx, expr)
|
||||||
|
&& let ExprKind::MethodCall(_, receiver, ..) = parent_expr.kind
|
||||||
|
&& receiver.hir_id == expr.hir_id
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ use std::collections::VecDeque;
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
/// Checks for borrow operations (`&`) that used as a generic argument to a
|
/// Checks for borrow operations (`&`) that are used as a generic argument to a
|
||||||
/// function when the borrowed value could be used.
|
/// function when the borrowed value could be used.
|
||||||
///
|
///
|
||||||
/// ### Why is this bad?
|
/// ### Why is this bad?
|
||||||
|
|
|
@ -18,7 +18,7 @@ use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult, GlobalId};
|
||||||
use rustc_middle::ty::adjustment::Adjust;
|
use rustc_middle::ty::adjustment::Adjust;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_session::impl_lint_pass;
|
use rustc_session::impl_lint_pass;
|
||||||
use rustc_span::{sym, DUMMY_SP, InnerSpan, Span};
|
use rustc_span::{sym, InnerSpan, Span, DUMMY_SP};
|
||||||
use rustc_target::abi::VariantIdx;
|
use rustc_target::abi::VariantIdx;
|
||||||
|
|
||||||
// FIXME: this is a correctness problem but there's no suitable
|
// FIXME: this is a correctness problem but there's no suitable
|
||||||
|
@ -297,12 +297,7 @@ impl NonCopyConst {
|
||||||
fn is_value_unfrozen_expr<'tcx>(&self, cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool {
|
fn is_value_unfrozen_expr<'tcx>(&self, cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool {
|
||||||
let args = cx.typeck_results().node_args(hir_id);
|
let args = cx.typeck_results().node_args(hir_id);
|
||||||
|
|
||||||
let result = Self::const_eval_resolve(
|
let result = Self::const_eval_resolve(cx.tcx, cx.param_env, ty::UnevaluatedConst::new(def_id, args), DUMMY_SP);
|
||||||
cx.tcx,
|
|
||||||
cx.param_env,
|
|
||||||
ty::UnevaluatedConst::new(def_id, args),
|
|
||||||
DUMMY_SP,
|
|
||||||
);
|
|
||||||
self.is_value_unfrozen_raw(cx, result, ty)
|
self.is_value_unfrozen_raw(cx, result, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -300,11 +300,8 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
|
||||||
e.span,
|
e.span,
|
||||||
"calling `as_bytes()` on `include_str!(..)`",
|
"calling `as_bytes()` on `include_str!(..)`",
|
||||||
"consider using `include_bytes!(..)` instead",
|
"consider using `include_bytes!(..)` instead",
|
||||||
snippet_with_applicability(cx, receiver.span.source_callsite(), r#""foo""#, &mut applicability).replacen(
|
snippet_with_applicability(cx, receiver.span.source_callsite(), r#""foo""#, &mut applicability)
|
||||||
"include_str",
|
.replacen("include_str", "include_bytes", 1),
|
||||||
"include_bytes",
|
|
||||||
1,
|
|
||||||
),
|
|
||||||
applicability,
|
applicability,
|
||||||
);
|
);
|
||||||
} else if lit_content.as_str().is_ascii()
|
} else if lit_content.as_str().is_ascii()
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub(super) fn check<'tcx>(
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: This can be simplified once `NonZero<T>` is stable.
|
// FIXME: This can be simplified once `NonZero<T>` is stable.
|
||||||
let coercable_types = [
|
let coercible_types = [
|
||||||
("NonZeroU8", tcx.types.u8),
|
("NonZeroU8", tcx.types.u8),
|
||||||
("NonZeroU16", tcx.types.u16),
|
("NonZeroU16", tcx.types.u16),
|
||||||
("NonZeroU32", tcx.types.u32),
|
("NonZeroU32", tcx.types.u32),
|
||||||
|
@ -44,7 +44,7 @@ pub(super) fn check<'tcx>(
|
||||||
|
|
||||||
let int_type = substs.type_at(0);
|
let int_type = substs.type_at(0);
|
||||||
|
|
||||||
let Some(nonzero_alias) = coercable_types.iter().find_map(|(nonzero_alias, t)| {
|
let Some(nonzero_alias) = coercible_types.iter().find_map(|(nonzero_alias, t)| {
|
||||||
if *t == int_type && *t == from_ty {
|
if *t == int_type && *t == from_ty {
|
||||||
Some(nonzero_alias)
|
Some(nonzero_alias)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use rustc_hir_typeck::cast::check_cast;
|
|
||||||
use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
|
use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::sugg::Sugg;
|
use clippy_utils::sugg::Sugg;
|
||||||
use rustc_ast::ExprPrecedence;
|
use rustc_ast::ExprPrecedence;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{Expr, Node};
|
use rustc_hir::{Expr, Node};
|
||||||
|
use rustc_hir_typeck::cast::check_cast;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::ty::cast::CastKind;
|
use rustc_middle::ty::cast::CastKind;
|
||||||
use rustc_middle::ty::Ty;
|
use rustc_middle::ty::Ty;
|
||||||
|
|
|
@ -709,8 +709,12 @@ pub fn eq_ty(l: &Ty, r: &Ty) -> bool {
|
||||||
(Tup(l), Tup(r)) => over(l, r, |l, r| eq_ty(l, r)),
|
(Tup(l), Tup(r)) => over(l, r, |l, r| eq_ty(l, r)),
|
||||||
(Path(lq, lp), Path(rq, rp)) => both(lq, rq, eq_qself) && eq_path(lp, rp),
|
(Path(lq, lp), Path(rq, rp)) => both(lq, rq, eq_qself) && eq_path(lp, rp),
|
||||||
(TraitObject(lg, ls), TraitObject(rg, rs)) => ls == rs && over(lg, rg, eq_generic_bound),
|
(TraitObject(lg, ls), TraitObject(rg, rs)) => ls == rs && over(lg, rg, eq_generic_bound),
|
||||||
(ImplTrait(_, lg, lc), ImplTrait(_, rg, rc)) =>
|
(ImplTrait(_, lg, lc), ImplTrait(_, rg, rc)) => {
|
||||||
over(lg, rg, eq_generic_bound) && both(lc, rc, |lc, rc| over(lc.0.as_slice(), rc.0.as_slice(), eq_precise_capture)),
|
over(lg, rg, eq_generic_bound)
|
||||||
|
&& both(lc, rc, |lc, rc| {
|
||||||
|
over(lc.0.as_slice(), rc.0.as_slice(), eq_precise_capture)
|
||||||
|
})
|
||||||
|
},
|
||||||
(Typeof(l), Typeof(r)) => eq_expr(&l.value, &r.value),
|
(Typeof(l), Typeof(r)) => eq_expr(&l.value, &r.value),
|
||||||
(MacCall(l), MacCall(r)) => eq_mac_call(l, r),
|
(MacCall(l), MacCall(r)) => eq_mac_call(l, r),
|
||||||
_ => false,
|
_ => false,
|
||||||
|
|
|
@ -3285,7 +3285,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
|
||||||
Right(r) => Right(r.data),
|
Right(r) => Right(r.data),
|
||||||
});
|
});
|
||||||
|
|
||||||
// 2. for the remaning segments, construct relative path using only mod names and `super`
|
// 2. for the remaining segments, construct relative path using only mod names and `super`
|
||||||
let mut go_up_by = 0;
|
let mut go_up_by = 0;
|
||||||
let mut path = Vec::new();
|
let mut path = Vec::new();
|
||||||
for el in unique_parts {
|
for el in unique_parts {
|
||||||
|
|
|
@ -10,7 +10,7 @@ use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
|
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety};
|
use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety};
|
||||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin};
|
use rustc_infer::infer::type_variable::TypeVariableOrigin;
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::mir::interpret::Scalar;
|
use rustc_middle::mir::interpret::Scalar;
|
||||||
|
|
|
@ -90,7 +90,7 @@ fn expr_type_certainty(cx: &LateContext<'_>, expr: &Expr<'_>) -> Certainty {
|
||||||
if let Some(def_id) = adt_def_id(expr_ty) {
|
if let Some(def_id) = adt_def_id(expr_ty) {
|
||||||
certainty.with_def_id(def_id)
|
certainty.with_def_id(def_id)
|
||||||
} else {
|
} else {
|
||||||
certainty
|
certainty.clear_def_id()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,12 +26,12 @@ use std::env::consts::EXE_SUFFIX;
|
||||||
use std::fmt::{self, Write as _};
|
use std::fmt::{self, Write as _};
|
||||||
use std::io::{self, ErrorKind};
|
use std::io::{self, ErrorKind};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::Command;
|
use std::process::{Command, ExitStatus};
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::{env, fs, thread};
|
use std::{env, fs, thread};
|
||||||
|
|
||||||
use cargo_metadata::diagnostic::{Diagnostic, DiagnosticLevel};
|
use cargo_metadata::diagnostic::Diagnostic;
|
||||||
use cargo_metadata::Message;
|
use cargo_metadata::Message;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -97,16 +97,43 @@ struct Crate {
|
||||||
options: Option<Vec<String>>,
|
options: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A single emitted output from clippy being executed on a crate. It may either be a
|
||||||
|
/// `ClippyWarning`, or a `RustcIce` caused by a panic within clippy. A crate may have many
|
||||||
|
/// `ClippyWarning`s but a maximum of one `RustcIce` (at which point clippy halts execution).
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum ClippyCheckOutput {
|
||||||
|
ClippyWarning(ClippyWarning),
|
||||||
|
RustcIce(RustcIce),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct RustcIce {
|
||||||
|
pub crate_name: String,
|
||||||
|
pub ice_content: String,
|
||||||
|
}
|
||||||
|
impl RustcIce {
|
||||||
|
pub fn from_stderr_and_status(crate_name: &str, status: ExitStatus, stderr: &str) -> Option<Self> {
|
||||||
|
if status.code().unwrap_or(0) == 101
|
||||||
|
/* ice exit status */
|
||||||
|
{
|
||||||
|
Some(Self {
|
||||||
|
crate_name: crate_name.to_owned(),
|
||||||
|
ice_content: stderr.to_owned(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A single warning that clippy issued while checking a `Crate`
|
/// A single warning that clippy issued while checking a `Crate`
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct ClippyWarning {
|
struct ClippyWarning {
|
||||||
crate_name: String,
|
|
||||||
file: String,
|
file: String,
|
||||||
line: usize,
|
line: usize,
|
||||||
column: usize,
|
column: usize,
|
||||||
lint_type: String,
|
lint_type: String,
|
||||||
message: String,
|
message: String,
|
||||||
is_ice: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
@ -131,13 +158,11 @@ impl ClippyWarning {
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(Self {
|
Some(Self {
|
||||||
crate_name: crate_name.to_owned(),
|
|
||||||
file,
|
file,
|
||||||
line: span.line_start,
|
line: span.line_start,
|
||||||
column: span.column_start,
|
column: span.column_start,
|
||||||
lint_type,
|
lint_type,
|
||||||
message: diag.message,
|
message: diag.message,
|
||||||
is_ice: diag.level == DiagnosticLevel::Ice,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,7 +343,7 @@ impl Crate {
|
||||||
config: &LintcheckConfig,
|
config: &LintcheckConfig,
|
||||||
lint_filter: &[String],
|
lint_filter: &[String],
|
||||||
server: &Option<LintcheckServer>,
|
server: &Option<LintcheckServer>,
|
||||||
) -> Vec<ClippyWarning> {
|
) -> Vec<ClippyCheckOutput> {
|
||||||
// advance the atomic index by one
|
// advance the atomic index by one
|
||||||
let index = target_dir_index.fetch_add(1, Ordering::SeqCst);
|
let index = target_dir_index.fetch_add(1, Ordering::SeqCst);
|
||||||
// "loop" the index within 0..thread_limit
|
// "loop" the index within 0..thread_limit
|
||||||
|
@ -342,9 +367,9 @@ impl Crate {
|
||||||
let shared_target_dir = clippy_project_root().join("target/lintcheck/shared_target_dir");
|
let shared_target_dir = clippy_project_root().join("target/lintcheck/shared_target_dir");
|
||||||
|
|
||||||
let mut cargo_clippy_args = if config.fix {
|
let mut cargo_clippy_args = if config.fix {
|
||||||
vec!["--fix", "--"]
|
vec!["--quiet", "--fix", "--"]
|
||||||
} else {
|
} else {
|
||||||
vec!["--", "--message-format=json", "--"]
|
vec!["--quiet", "--message-format=json", "--"]
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut clippy_args = Vec::<&str>::new();
|
let mut clippy_args = Vec::<&str>::new();
|
||||||
|
@ -435,14 +460,21 @@ impl Crate {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get all clippy warnings and ICEs
|
// get all clippy warnings and ICEs
|
||||||
let warnings: Vec<ClippyWarning> = Message::parse_stream(stdout.as_bytes())
|
let mut entries: Vec<ClippyCheckOutput> = Message::parse_stream(stdout.as_bytes())
|
||||||
.filter_map(|msg| match msg {
|
.filter_map(|msg| match msg {
|
||||||
Ok(Message::CompilerMessage(message)) => ClippyWarning::new(message.message, &self.name, &self.version),
|
Ok(Message::CompilerMessage(message)) => ClippyWarning::new(message.message, &self.name, &self.version),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
|
.map(ClippyCheckOutput::ClippyWarning)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
warnings
|
if let Some(ice) = RustcIce::from_stderr_and_status(&self.name, *status, &stderr) {
|
||||||
|
entries.push(ClippyCheckOutput::RustcIce(ice));
|
||||||
|
} else if !status.success() {
|
||||||
|
println!("non-ICE bad exit status for {} {}: {}", self.name, self.version, stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
entries
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,7 +674,7 @@ fn main() {
|
||||||
LintcheckServer::spawn(recursive_options)
|
LintcheckServer::spawn(recursive_options)
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut clippy_warnings: Vec<ClippyWarning> = crates
|
let mut clippy_entries: Vec<ClippyCheckOutput> = crates
|
||||||
.par_iter()
|
.par_iter()
|
||||||
.flat_map(|krate| {
|
.flat_map(|krate| {
|
||||||
krate.run_clippy_lints(
|
krate.run_clippy_lints(
|
||||||
|
@ -658,7 +690,9 @@ fn main() {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if let Some(server) = server {
|
if let Some(server) = server {
|
||||||
clippy_warnings.extend(server.warnings());
|
let server_clippy_entries = server.warnings().map(ClippyCheckOutput::ClippyWarning);
|
||||||
|
|
||||||
|
clippy_entries.extend(server_clippy_entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we are in --fix mode, don't change the log files, terminate here
|
// if we are in --fix mode, don't change the log files, terminate here
|
||||||
|
@ -666,20 +700,21 @@ fn main() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// split up warnings and ices
|
||||||
|
let mut warnings: Vec<ClippyWarning> = vec![];
|
||||||
|
let mut raw_ices: Vec<RustcIce> = vec![];
|
||||||
|
for entry in clippy_entries {
|
||||||
|
if let ClippyCheckOutput::ClippyWarning(x) = entry {
|
||||||
|
warnings.push(x);
|
||||||
|
} else if let ClippyCheckOutput::RustcIce(x) = entry {
|
||||||
|
raw_ices.push(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// generate some stats
|
// generate some stats
|
||||||
let (stats_formatted, new_stats) = gather_stats(&clippy_warnings);
|
let (stats_formatted, new_stats) = gather_stats(&warnings);
|
||||||
|
|
||||||
// grab crashes/ICEs, save the crate name and the ice message
|
let mut all_msgs: Vec<String> = warnings.iter().map(|warn| warn.to_output(config.markdown)).collect();
|
||||||
let ices: Vec<(&String, &String)> = clippy_warnings
|
|
||||||
.iter()
|
|
||||||
.filter(|warning| warning.is_ice)
|
|
||||||
.map(|w| (&w.crate_name, &w.message))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut all_msgs: Vec<String> = clippy_warnings
|
|
||||||
.iter()
|
|
||||||
.map(|warn| warn.to_output(config.markdown))
|
|
||||||
.collect();
|
|
||||||
all_msgs.sort();
|
all_msgs.sort();
|
||||||
all_msgs.push("\n\n### Stats:\n\n".into());
|
all_msgs.push("\n\n### Stats:\n\n".into());
|
||||||
all_msgs.push(stats_formatted);
|
all_msgs.push(stats_formatted);
|
||||||
|
@ -693,11 +728,18 @@ fn main() {
|
||||||
}
|
}
|
||||||
write!(text, "{}", all_msgs.join("")).unwrap();
|
write!(text, "{}", all_msgs.join("")).unwrap();
|
||||||
text.push_str("\n\n### ICEs:\n");
|
text.push_str("\n\n### ICEs:\n");
|
||||||
for (cratename, msg) in &ices {
|
for ice in &raw_ices {
|
||||||
let _: fmt::Result = write!(text, "{cratename}: '{msg}'");
|
let _: fmt::Result = write!(
|
||||||
|
text,
|
||||||
|
"{}:\n{}\n========================================\n\n",
|
||||||
|
ice.crate_name, ice.ice_content
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Writing logs to {}", config.lintcheck_results_path.display());
|
println!("Writing logs to {}", config.lintcheck_results_path.display());
|
||||||
|
if !raw_ices.is_empty() {
|
||||||
|
println!("WARNING: at least one ICE reported, check log file");
|
||||||
|
}
|
||||||
fs::create_dir_all(config.lintcheck_results_path.parent().unwrap()).unwrap();
|
fs::create_dir_all(config.lintcheck_results_path.parent().unwrap()).unwrap();
|
||||||
fs::write(&config.lintcheck_results_path, text).unwrap();
|
fs::write(&config.lintcheck_results_path, text).unwrap();
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly-2024-04-04"
|
channel = "nightly-2024-04-18"
|
||||||
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
//@normalize-stderr-test: "'rustc'" -> "'<unnamed>'"
|
//@normalize-stderr-test: "'rustc'" -> "'<unnamed>'"
|
||||||
//@normalize-stderr-test: "rustc 1\.\d+.* running on .*" -> "rustc <version> running on <target>"
|
//@normalize-stderr-test: "rustc 1\.\d+.* running on .*" -> "rustc <version> running on <target>"
|
||||||
//@normalize-stderr-test: "(?ms)query stack during panic:\n.*end of query stack\n" -> ""
|
//@normalize-stderr-test: "(?ms)query stack during panic:\n.*end of query stack\n" -> ""
|
||||||
//@normalize-stderr-test: "this compiler `.*` is outdated" -> "this compiler <version> is outdated"
|
|
||||||
|
|
||||||
#![deny(clippy::internal)]
|
#![deny(clippy::internal)]
|
||||||
#![allow(clippy::missing_clippy_version_attribute)]
|
#![allow(clippy::missing_clippy_version_attribute)]
|
||||||
|
|
|
@ -4,10 +4,9 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||||
|
|
||||||
error: the compiler unexpectedly panicked. this is a bug.
|
error: the compiler unexpectedly panicked. this is a bug.
|
||||||
|
|
||||||
note: it seems that this compiler <version> is outdated, a newer nightly should have been released in the meantime
|
note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml
|
||||||
|
|
|
||||||
= note: please consider running `rustup update nightly` to update the nightly channel and check if this problem still persists
|
note: please make sure that you have updated to the latest nightly
|
||||||
= note: if the problem still persists, we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml
|
|
||||||
|
|
||||||
note: rustc <version> running on <target>
|
note: rustc <version> running on <target>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
allowed-prefixes = ["bar"]
|
|
@ -0,0 +1,15 @@
|
||||||
|
#![warn(clippy::module_name_repetitions)]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
mod foo {
|
||||||
|
// #12544 - shouldn't warn if item name consists only of an allowed prefix and a module name.
|
||||||
|
// In this test, allowed prefixes are configured to be ["bar"].
|
||||||
|
|
||||||
|
// this line should produce a warning:
|
||||||
|
pub fn to_foo() {}
|
||||||
|
|
||||||
|
// but this line shouldn't
|
||||||
|
pub fn bar_foo() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,11 @@
|
||||||
|
error: item name ends with its containing module's name
|
||||||
|
--> tests/ui-toml/item_name_repetitions/allowed_prefixes/item_name_repetitions.rs:9:12
|
||||||
|
|
|
||||||
|
LL | pub fn to_foo() {}
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= note: `-D clippy::module-name-repetitions` implied by `-D warnings`
|
||||||
|
= help: to override `-D warnings` add `#[allow(clippy::module_name_repetitions)]`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
allowed-prefixes = ["..", "bar"]
|
|
@ -0,0 +1,21 @@
|
||||||
|
#![warn(clippy::module_name_repetitions)]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
mod foo {
|
||||||
|
// #12544 - shouldn't warn if item name consists only of an allowed prefix and a module name.
|
||||||
|
// In this test, allowed prefixes are configured to be all of the default prefixes and ["bar"].
|
||||||
|
|
||||||
|
// this line should produce a warning:
|
||||||
|
pub fn something_foo() {}
|
||||||
|
|
||||||
|
// but none of the following should:
|
||||||
|
pub fn bar_foo() {}
|
||||||
|
pub fn to_foo() {}
|
||||||
|
pub fn as_foo() {}
|
||||||
|
pub fn into_foo() {}
|
||||||
|
pub fn from_foo() {}
|
||||||
|
pub fn try_into_foo() {}
|
||||||
|
pub fn try_from_foo() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,11 @@
|
||||||
|
error: item name ends with its containing module's name
|
||||||
|
--> tests/ui-toml/item_name_repetitions/allowed_prefixes_extend/item_name_repetitions.rs:9:12
|
||||||
|
|
|
||||||
|
LL | pub fn something_foo() {}
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `-D clippy::module-name-repetitions` implied by `-D warnings`
|
||||||
|
= help: to override `-D warnings` add `#[allow(clippy::module_name_repetitions)]`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
|
@ -14,6 +14,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
|
||||||
allowed-dotfiles
|
allowed-dotfiles
|
||||||
allowed-duplicate-crates
|
allowed-duplicate-crates
|
||||||
allowed-idents-below-min-chars
|
allowed-idents-below-min-chars
|
||||||
|
allowed-prefixes
|
||||||
allowed-scripts
|
allowed-scripts
|
||||||
allowed-wildcard-imports
|
allowed-wildcard-imports
|
||||||
arithmetic-side-effects-allowed
|
arithmetic-side-effects-allowed
|
||||||
|
@ -93,6 +94,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
|
||||||
allowed-dotfiles
|
allowed-dotfiles
|
||||||
allowed-duplicate-crates
|
allowed-duplicate-crates
|
||||||
allowed-idents-below-min-chars
|
allowed-idents-below-min-chars
|
||||||
|
allowed-prefixes
|
||||||
allowed-scripts
|
allowed-scripts
|
||||||
allowed-wildcard-imports
|
allowed-wildcard-imports
|
||||||
arithmetic-side-effects-allowed
|
arithmetic-side-effects-allowed
|
||||||
|
@ -172,6 +174,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni
|
||||||
allowed-dotfiles
|
allowed-dotfiles
|
||||||
allowed-duplicate-crates
|
allowed-duplicate-crates
|
||||||
allowed-idents-below-min-chars
|
allowed-idents-below-min-chars
|
||||||
|
allowed-prefixes
|
||||||
allowed-scripts
|
allowed-scripts
|
||||||
allowed-wildcard-imports
|
allowed-wildcard-imports
|
||||||
arithmetic-side-effects-allowed
|
arithmetic-side-effects-allowed
|
||||||
|
|
|
@ -33,16 +33,9 @@ fn main() {
|
||||||
let _ = Arc::new(42);
|
let _ = Arc::new(42);
|
||||||
|
|
||||||
let _ = Arc::new(RefCell::new(42));
|
let _ = Arc::new(RefCell::new(42));
|
||||||
//~^ ERROR: usage of an `Arc` that is not `Send` and `Sync`
|
|
||||||
//~| NOTE: the trait `Sync` is not implemented for `RefCell<i32>`
|
|
||||||
|
|
||||||
let mutex = Mutex::new(1);
|
let mutex = Mutex::new(1);
|
||||||
let _ = Arc::new(mutex.lock().unwrap());
|
let _ = Arc::new(mutex.lock().unwrap());
|
||||||
//~^ ERROR: usage of an `Arc` that is not `Send` and `Sync`
|
|
||||||
//~| NOTE: the trait `Send` is not implemented for `MutexGuard<'_, i32>`
|
|
||||||
|
|
||||||
let _ = Arc::new(&42 as *const i32);
|
let _ = Arc::new(&42 as *const i32);
|
||||||
//~^ ERROR: usage of an `Arc` that is not `Send` and `Sync`
|
|
||||||
//~| NOTE: the trait `Send` is not implemented for `*const i32`
|
|
||||||
//~| NOTE: the trait `Sync` is not implemented for `*const i32`
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,38 +4,31 @@ error: usage of an `Arc` that is not `Send` and `Sync`
|
||||||
LL | let _ = Arc::new(RefCell::new(42));
|
LL | let _ = Arc::new(RefCell::new(42));
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: `Arc<RefCell<i32>>` is not `Send` and `Sync` as:
|
= note: `Arc<RefCell<i32>>` is not `Send` and `Sync` as `RefCell<i32>` is not `Sync`
|
||||||
= note: - the trait `Sync` is not implemented for `RefCell<i32>`
|
= help: if the `Arc` will not used be across threads replace it with an `Rc`
|
||||||
= help: consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types
|
= help: otherwise make `RefCell<i32>` `Send` and `Sync` or consider a wrapper type such as `Mutex`
|
||||||
= note: if you intend to use `Arc` with `Send` and `Sync` traits
|
|
||||||
= note: wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `RefCell<i32>`
|
|
||||||
= note: `-D clippy::arc-with-non-send-sync` implied by `-D warnings`
|
= note: `-D clippy::arc-with-non-send-sync` implied by `-D warnings`
|
||||||
= help: to override `-D warnings` add `#[allow(clippy::arc_with_non_send_sync)]`
|
= help: to override `-D warnings` add `#[allow(clippy::arc_with_non_send_sync)]`
|
||||||
|
|
||||||
error: usage of an `Arc` that is not `Send` and `Sync`
|
error: usage of an `Arc` that is not `Send` and `Sync`
|
||||||
--> tests/ui/arc_with_non_send_sync.rs:40:13
|
--> tests/ui/arc_with_non_send_sync.rs:38:13
|
||||||
|
|
|
|
||||||
LL | let _ = Arc::new(mutex.lock().unwrap());
|
LL | let _ = Arc::new(mutex.lock().unwrap());
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: `Arc<MutexGuard<'_, i32>>` is not `Send` and `Sync` as:
|
= note: `Arc<MutexGuard<'_, i32>>` is not `Send` and `Sync` as `MutexGuard<'_, i32>` is not `Send`
|
||||||
= note: - the trait `Send` is not implemented for `MutexGuard<'_, i32>`
|
= help: if the `Arc` will not used be across threads replace it with an `Rc`
|
||||||
= help: consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types
|
= help: otherwise make `MutexGuard<'_, i32>` `Send` and `Sync` or consider a wrapper type such as `Mutex`
|
||||||
= note: if you intend to use `Arc` with `Send` and `Sync` traits
|
|
||||||
= note: wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `MutexGuard<'_, i32>`
|
|
||||||
|
|
||||||
error: usage of an `Arc` that is not `Send` and `Sync`
|
error: usage of an `Arc` that is not `Send` and `Sync`
|
||||||
--> tests/ui/arc_with_non_send_sync.rs:44:13
|
--> tests/ui/arc_with_non_send_sync.rs:40:13
|
||||||
|
|
|
|
||||||
LL | let _ = Arc::new(&42 as *const i32);
|
LL | let _ = Arc::new(&42 as *const i32);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: `Arc<*const i32>` is not `Send` and `Sync` as:
|
= note: `Arc<*const i32>` is not `Send` and `Sync` as `*const i32` is neither `Send` nor `Sync`
|
||||||
= note: - the trait `Send` is not implemented for `*const i32`
|
= help: if the `Arc` will not used be across threads replace it with an `Rc`
|
||||||
= note: - the trait `Sync` is not implemented for `*const i32`
|
= help: otherwise make `*const i32` `Send` and `Sync` or consider a wrapper type such as `Mutex`
|
||||||
= help: consider using an `Rc` instead. `Arc` does not provide benefits for non `Send` and `Sync` types
|
|
||||||
= note: if you intend to use `Arc` with `Send` and `Sync` traits
|
|
||||||
= note: wrap the inner type with a `Mutex` or implement `Send` and `Sync` for `*const i32`
|
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
|
|
@ -176,3 +176,17 @@ pub fn with_empty_docs(_attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn duplicated_attr(_attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
|
let item = parse_macro_input!(input as syn::Item);
|
||||||
|
let attrs: Vec<syn::Attribute> = vec![];
|
||||||
|
quote! {
|
||||||
|
#(#attrs)*
|
||||||
|
#[allow(unused)]
|
||||||
|
#[allow(unused)]
|
||||||
|
#[allow(unused)]
|
||||||
|
#item
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
|
@ -463,6 +463,18 @@ fn issue11642() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn issue11738() {
|
||||||
|
macro_rules! m {
|
||||||
|
() => {
|
||||||
|
let _ = i32::MIN as u32; // cast_sign_loss
|
||||||
|
let _ = u32::MAX as u8; // cast_possible_truncation
|
||||||
|
let _ = std::f64::consts::PI as f32; // cast_possible_truncation
|
||||||
|
let _ = 0i8 as i32; // cast_lossless
|
||||||
|
};
|
||||||
|
}
|
||||||
|
m!();
|
||||||
|
}
|
||||||
|
|
||||||
fn issue12506() -> usize {
|
fn issue12506() -> usize {
|
||||||
let bar: Result<Option<i64>, u32> = Ok(Some(10));
|
let bar: Result<Option<i64>, u32> = Ok(Some(10));
|
||||||
bar.unwrap().unwrap() as usize
|
bar.unwrap().unwrap() as usize
|
||||||
|
|
|
@ -650,8 +650,47 @@ error: casting `i32` to `u32` may lose the sign of the value
|
||||||
LL | (a.abs() * b.pow(2) / c.abs()) as u32
|
LL | (a.abs() * b.pow(2) / c.abs()) as u32
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: casting `i32` to `u32` may lose the sign of the value
|
||||||
|
--> tests/ui/cast.rs:469:21
|
||||||
|
|
|
||||||
|
LL | let _ = i32::MIN as u32; // cast_sign_loss
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
...
|
||||||
|
LL | m!();
|
||||||
|
| ---- in this macro invocation
|
||||||
|
|
|
||||||
|
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: casting `u32` to `u8` may truncate the value
|
||||||
|
--> tests/ui/cast.rs:470:21
|
||||||
|
|
|
||||||
|
LL | let _ = u32::MAX as u8; // cast_possible_truncation
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
...
|
||||||
|
LL | m!();
|
||||||
|
| ---- in this macro invocation
|
||||||
|
|
|
||||||
|
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||||
|
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
help: ... or use `try_from` and handle the error accordingly
|
||||||
|
|
|
||||||
|
LL | let _ = u8::try_from(u32::MAX); // cast_possible_truncation
|
||||||
|
| ~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
error: casting `f64` to `f32` may truncate the value
|
||||||
|
--> tests/ui/cast.rs:471:21
|
||||||
|
|
|
||||||
|
LL | let _ = std::f64::consts::PI as f32; // cast_possible_truncation
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
...
|
||||||
|
LL | m!();
|
||||||
|
| ---- in this macro invocation
|
||||||
|
|
|
||||||
|
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||||
|
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers
|
error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers
|
||||||
--> tests/ui/cast.rs:468:5
|
--> tests/ui/cast.rs:480:5
|
||||||
|
|
|
|
||||||
LL | bar.unwrap().unwrap() as usize
|
LL | bar.unwrap().unwrap() as usize
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -663,10 +702,10 @@ LL | usize::try_from(bar.unwrap().unwrap())
|
||||||
|
|
|
|
||||||
|
|
||||||
error: casting `i64` to `usize` may lose the sign of the value
|
error: casting `i64` to `usize` may lose the sign of the value
|
||||||
--> tests/ui/cast.rs:468:5
|
--> tests/ui/cast.rs:480:5
|
||||||
|
|
|
|
||||||
LL | bar.unwrap().unwrap() as usize
|
LL | bar.unwrap().unwrap() as usize
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 87 previous errors
|
error: aborting due to 90 previous errors
|
||||||
|
|
||||||
|
|
26
tests/ui/crashes/ice-12585.rs
Normal file
26
tests/ui/crashes/ice-12585.rs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#![allow(clippy::unit_arg)]
|
||||||
|
|
||||||
|
struct One {
|
||||||
|
x: i32,
|
||||||
|
}
|
||||||
|
struct Two {
|
||||||
|
x: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Product {}
|
||||||
|
|
||||||
|
impl Product {
|
||||||
|
pub fn a_method(self, _: ()) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_array(_: [i32; 2]) -> Product {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let one = One { x: 1 };
|
||||||
|
let two = Two { x: 2 };
|
||||||
|
|
||||||
|
let product = from_array([one.x, two.x]);
|
||||||
|
product.a_method(<()>::default());
|
||||||
|
}
|
|
@ -7,13 +7,5 @@ LL | s() as *const ();
|
||||||
= note: `-D clippy::ptr-as-ptr` implied by `-D warnings`
|
= note: `-D clippy::ptr-as-ptr` implied by `-D warnings`
|
||||||
= help: to override `-D warnings` add `#[allow(clippy::ptr_as_ptr)]`
|
= help: to override `-D warnings` add `#[allow(clippy::ptr_as_ptr)]`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: aborting due to 1 previous error
|
||||||
--> tests/ui/crashes/ice-12616.rs:6:5
|
|
||||||
|
|
|
||||||
LL | s() as *const ();
|
|
||||||
| ^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `s().cast::<()>()`
|
|
||||||
|
|
|
||||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
|
|
|
@ -235,3 +235,8 @@ fn parenthesized_word() {}
|
||||||
/// OSes
|
/// OSes
|
||||||
/// UXes
|
/// UXes
|
||||||
fn plural_acronym_test() {}
|
fn plural_acronym_test() {}
|
||||||
|
|
||||||
|
extern {
|
||||||
|
/// `foo()`
|
||||||
|
fn in_extern();
|
||||||
|
}
|
||||||
|
|
|
@ -235,3 +235,8 @@ fn parenthesized_word() {}
|
||||||
/// OSes
|
/// OSes
|
||||||
/// UXes
|
/// UXes
|
||||||
fn plural_acronym_test() {}
|
fn plural_acronym_test() {}
|
||||||
|
|
||||||
|
extern {
|
||||||
|
/// foo()
|
||||||
|
fn in_extern();
|
||||||
|
}
|
||||||
|
|
|
@ -352,5 +352,16 @@ help: try
|
||||||
LL | /// `ABes`
|
LL | /// `ABes`
|
||||||
| ~~~~~~
|
| ~~~~~~
|
||||||
|
|
||||||
error: aborting due to 32 previous errors
|
error: item in documentation is missing backticks
|
||||||
|
--> tests/ui/doc/doc-fixable.rs:240:9
|
||||||
|
|
|
||||||
|
LL | /// foo()
|
||||||
|
| ^^^^^
|
||||||
|
|
|
||||||
|
help: try
|
||||||
|
|
|
||||||
|
LL | /// `foo()`
|
||||||
|
| ~~~~~~~
|
||||||
|
|
||||||
|
error: aborting due to 33 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
|
//@aux-build:proc_macro_attr.rs
|
||||||
|
|
||||||
#![warn(clippy::duplicated_attributes)]
|
#![warn(clippy::duplicated_attributes)]
|
||||||
#![cfg(any(unix, windows))]
|
#![cfg(any(unix, windows))]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![allow(dead_code)] //~ ERROR: duplicated attribute
|
#![allow(dead_code)] //~ ERROR: duplicated attribute
|
||||||
#![cfg(any(unix, windows))] // Should not warn!
|
#![cfg(any(unix, windows))] // Should not warn!
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate proc_macro_attr;
|
||||||
|
|
||||||
#[cfg(any(unix, windows, target_os = "linux"))]
|
#[cfg(any(unix, windows, target_os = "linux"))]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(dead_code)] //~ ERROR: duplicated attribute
|
#[allow(dead_code)] //~ ERROR: duplicated attribute
|
||||||
|
@ -12,7 +17,10 @@ fn foo() {}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
#[cfg(unix)] //~ ERROR: duplicated attribute
|
#[cfg(unix)] // cfgs are not handled
|
||||||
fn bar() {}
|
fn bar() {}
|
||||||
|
|
||||||
|
#[proc_macro_attr::duplicated_attr()] // Should not warn!
|
||||||
|
fn babar() {}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
error: duplicated attribute
|
error: duplicated attribute
|
||||||
--> tests/ui/duplicated_attributes.rs:4:10
|
--> tests/ui/duplicated_attributes.rs:6:10
|
||||||
|
|
|
|
||||||
LL | #![allow(dead_code)]
|
LL | #![allow(dead_code)]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: first defined here
|
note: first defined here
|
||||||
--> tests/ui/duplicated_attributes.rs:3:10
|
--> tests/ui/duplicated_attributes.rs:5:10
|
||||||
|
|
|
|
||||||
LL | #![allow(dead_code)]
|
LL | #![allow(dead_code)]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
help: remove this attribute
|
help: remove this attribute
|
||||||
--> tests/ui/duplicated_attributes.rs:4:10
|
--> tests/ui/duplicated_attributes.rs:6:10
|
||||||
|
|
|
|
||||||
LL | #![allow(dead_code)]
|
LL | #![allow(dead_code)]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -18,38 +18,21 @@ LL | #![allow(dead_code)]
|
||||||
= help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]`
|
= help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]`
|
||||||
|
|
||||||
error: duplicated attribute
|
error: duplicated attribute
|
||||||
--> tests/ui/duplicated_attributes.rs:9:9
|
--> tests/ui/duplicated_attributes.rs:14:9
|
||||||
|
|
|
|
||||||
LL | #[allow(dead_code)]
|
LL | #[allow(dead_code)]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: first defined here
|
note: first defined here
|
||||||
--> tests/ui/duplicated_attributes.rs:8:9
|
--> tests/ui/duplicated_attributes.rs:13:9
|
||||||
|
|
|
|
||||||
LL | #[allow(dead_code)]
|
LL | #[allow(dead_code)]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
help: remove this attribute
|
help: remove this attribute
|
||||||
--> tests/ui/duplicated_attributes.rs:9:9
|
--> tests/ui/duplicated_attributes.rs:14:9
|
||||||
|
|
|
|
||||||
LL | #[allow(dead_code)]
|
LL | #[allow(dead_code)]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: duplicated attribute
|
error: aborting due to 2 previous errors
|
||||||
--> tests/ui/duplicated_attributes.rs:15:7
|
|
||||||
|
|
|
||||||
LL | #[cfg(unix)]
|
|
||||||
| ^^^^
|
|
||||||
|
|
|
||||||
note: first defined here
|
|
||||||
--> tests/ui/duplicated_attributes.rs:13:7
|
|
||||||
|
|
|
||||||
LL | #[cfg(unix)]
|
|
||||||
| ^^^^
|
|
||||||
help: remove this attribute
|
|
||||||
--> tests/ui/duplicated_attributes.rs:15:7
|
|
||||||
|
|
|
||||||
LL | #[cfg(unix)]
|
|
||||||
| ^^^^
|
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,16 @@ fn main() {
|
||||||
|
|
||||||
let x: Option<Vec<String>> = None;
|
let x: Option<Vec<String>> = None;
|
||||||
x.unwrap_or_default();
|
x.unwrap_or_default();
|
||||||
|
|
||||||
|
// Issue #12564
|
||||||
|
// No error as &Vec<_> doesn't implement std::default::Default
|
||||||
|
let mut map = std::collections::HashMap::from([(0, vec![0; 3]), (1, vec![1; 3]), (2, vec![2])]);
|
||||||
|
let x: &[_] = if let Some(x) = map.get(&0) { x } else { &[] };
|
||||||
|
// Same code as above written using match.
|
||||||
|
let x: &[_] = match map.get(&0) {
|
||||||
|
Some(x) => x,
|
||||||
|
None => &[],
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue #12531
|
// Issue #12531
|
||||||
|
|
|
@ -37,6 +37,16 @@ fn main() {
|
||||||
} else {
|
} else {
|
||||||
Vec::default()
|
Vec::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Issue #12564
|
||||||
|
// No error as &Vec<_> doesn't implement std::default::Default
|
||||||
|
let mut map = std::collections::HashMap::from([(0, vec![0; 3]), (1, vec![1; 3]), (2, vec![2])]);
|
||||||
|
let x: &[_] = if let Some(x) = map.get(&0) { x } else { &[] };
|
||||||
|
// Same code as above written using match.
|
||||||
|
let x: &[_] = match map.get(&0) {
|
||||||
|
Some(x) => x,
|
||||||
|
None => &[],
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue #12531
|
// Issue #12531
|
||||||
|
|
|
@ -53,7 +53,7 @@ LL | | };
|
||||||
| |_____^ help: replace it with: `x.unwrap_or_default()`
|
| |_____^ help: replace it with: `x.unwrap_or_default()`
|
||||||
|
|
||||||
error: match can be simplified with `.unwrap_or_default()`
|
error: match can be simplified with `.unwrap_or_default()`
|
||||||
--> tests/ui/manual_unwrap_or_default.rs:46:20
|
--> tests/ui/manual_unwrap_or_default.rs:56:20
|
||||||
|
|
|
|
||||||
LL | Some(_) => match *b {
|
LL | Some(_) => match *b {
|
||||||
| ____________________^
|
| ____________________^
|
||||||
|
|
|
@ -19,6 +19,20 @@ mod foo {
|
||||||
|
|
||||||
// Should not warn
|
// Should not warn
|
||||||
pub struct Foobar;
|
pub struct Foobar;
|
||||||
|
|
||||||
|
// #12544 - shouldn't warn if item name consists only of an allowed prefix and a module name.
|
||||||
|
pub fn to_foo() {}
|
||||||
|
pub fn into_foo() {}
|
||||||
|
pub fn as_foo() {}
|
||||||
|
pub fn from_foo() {}
|
||||||
|
pub fn try_into_foo() {}
|
||||||
|
pub fn try_from_foo() {}
|
||||||
|
pub trait IntoFoo {}
|
||||||
|
pub trait ToFoo {}
|
||||||
|
pub trait AsFoo {}
|
||||||
|
pub trait FromFoo {}
|
||||||
|
pub trait TryIntoFoo {}
|
||||||
|
pub trait TryFromFoo {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//@needs-asm-support
|
||||||
//@aux-build:proc_macros.rs
|
//@aux-build:proc_macros.rs
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
#![allow(deref_nullptr)]
|
#![allow(deref_nullptr)]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:36:5
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:37:5
|
||||||
|
|
|
|
||||||
LL | / unsafe {
|
LL | / unsafe {
|
||||||
LL | | STATIC += 1;
|
LL | | STATIC += 1;
|
||||||
|
@ -8,12 +8,12 @@ LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
note: modification of a mutable static occurs here
|
note: modification of a mutable static occurs here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:37:9
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:38:9
|
||||||
|
|
|
|
||||||
LL | STATIC += 1;
|
LL | STATIC += 1;
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
note: unsafe function call occurs here
|
note: unsafe function call occurs here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:38:9
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:39:9
|
||||||
|
|
|
|
||||||
LL | not_very_safe();
|
LL | not_very_safe();
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
@ -21,7 +21,7 @@ LL | not_very_safe();
|
||||||
= help: to override `-D warnings` add `#[allow(clippy::multiple_unsafe_ops_per_block)]`
|
= help: to override `-D warnings` add `#[allow(clippy::multiple_unsafe_ops_per_block)]`
|
||||||
|
|
||||||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:45:5
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:46:5
|
||||||
|
|
|
|
||||||
LL | / unsafe {
|
LL | / unsafe {
|
||||||
LL | | drop(u.u);
|
LL | | drop(u.u);
|
||||||
|
@ -30,18 +30,18 @@ LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
note: union field access occurs here
|
note: union field access occurs here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:46:14
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:47:14
|
||||||
|
|
|
|
||||||
LL | drop(u.u);
|
LL | drop(u.u);
|
||||||
| ^^^
|
| ^^^
|
||||||
note: raw pointer dereference occurs here
|
note: raw pointer dereference occurs here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:47:9
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:48:9
|
||||||
|
|
|
|
||||||
LL | *raw_ptr();
|
LL | *raw_ptr();
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: this `unsafe` block contains 3 unsafe operations, expected only one
|
error: this `unsafe` block contains 3 unsafe operations, expected only one
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:52:5
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:53:5
|
||||||
|
|
|
|
||||||
LL | / unsafe {
|
LL | / unsafe {
|
||||||
LL | | asm!("nop");
|
LL | | asm!("nop");
|
||||||
|
@ -51,23 +51,23 @@ LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
note: inline assembly used here
|
note: inline assembly used here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:53:9
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:54:9
|
||||||
|
|
|
|
||||||
LL | asm!("nop");
|
LL | asm!("nop");
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
note: unsafe method call occurs here
|
note: unsafe method call occurs here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:54:9
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:55:9
|
||||||
|
|
|
|
||||||
LL | sample.not_very_safe();
|
LL | sample.not_very_safe();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: modification of a mutable static occurs here
|
note: modification of a mutable static occurs here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:55:9
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:56:9
|
||||||
|
|
|
|
||||||
LL | STATIC = 0;
|
LL | STATIC = 0;
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: this `unsafe` block contains 6 unsafe operations, expected only one
|
error: this `unsafe` block contains 6 unsafe operations, expected only one
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:61:5
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:62:5
|
||||||
|
|
|
|
||||||
LL | / unsafe {
|
LL | / unsafe {
|
||||||
LL | | drop(u.u);
|
LL | | drop(u.u);
|
||||||
|
@ -79,55 +79,55 @@ LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
note: union field access occurs here
|
note: union field access occurs here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:62:14
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:63:14
|
||||||
|
|
|
|
||||||
LL | drop(u.u);
|
LL | drop(u.u);
|
||||||
| ^^^
|
| ^^^
|
||||||
note: access of a mutable static occurs here
|
note: access of a mutable static occurs here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:63:14
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:64:14
|
||||||
|
|
|
|
||||||
LL | drop(STATIC);
|
LL | drop(STATIC);
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
note: unsafe method call occurs here
|
note: unsafe method call occurs here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:64:9
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:65:9
|
||||||
|
|
|
|
||||||
LL | sample.not_very_safe();
|
LL | sample.not_very_safe();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: unsafe function call occurs here
|
note: unsafe function call occurs here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:65:9
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:66:9
|
||||||
|
|
|
|
||||||
LL | not_very_safe();
|
LL | not_very_safe();
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
note: raw pointer dereference occurs here
|
note: raw pointer dereference occurs here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:66:9
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:67:9
|
||||||
|
|
|
|
||||||
LL | *raw_ptr();
|
LL | *raw_ptr();
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
note: inline assembly used here
|
note: inline assembly used here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:67:9
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:68:9
|
||||||
|
|
|
|
||||||
LL | asm!("nop");
|
LL | asm!("nop");
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:105:5
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:106:5
|
||||||
|
|
|
|
||||||
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: unsafe function call occurs here
|
note: unsafe function call occurs here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:105:14
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:106:14
|
||||||
|
|
|
|
||||||
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: raw pointer dereference occurs here
|
note: raw pointer dereference occurs here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:105:39
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:106:39
|
||||||
|
|
|
|
||||||
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:123:5
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:124:5
|
||||||
|
|
|
|
||||||
LL | / unsafe {
|
LL | / unsafe {
|
||||||
LL | | x();
|
LL | | x();
|
||||||
|
@ -136,18 +136,18 @@ LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
note: unsafe function call occurs here
|
note: unsafe function call occurs here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:124:9
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:125:9
|
||||||
|
|
|
|
||||||
LL | x();
|
LL | x();
|
||||||
| ^^^
|
| ^^^
|
||||||
note: unsafe function call occurs here
|
note: unsafe function call occurs here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:125:9
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:126:9
|
||||||
|
|
|
|
||||||
LL | x();
|
LL | x();
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:134:9
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:135:9
|
||||||
|
|
|
|
||||||
LL | / unsafe {
|
LL | / unsafe {
|
||||||
LL | | T::X();
|
LL | | T::X();
|
||||||
|
@ -156,18 +156,18 @@ LL | | }
|
||||||
| |_________^
|
| |_________^
|
||||||
|
|
|
|
||||||
note: unsafe function call occurs here
|
note: unsafe function call occurs here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:135:13
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:136:13
|
||||||
|
|
|
|
||||||
LL | T::X();
|
LL | T::X();
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
note: unsafe function call occurs here
|
note: unsafe function call occurs here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:136:13
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:137:13
|
||||||
|
|
|
|
||||||
LL | T::X();
|
LL | T::X();
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
||||||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:144:5
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:145:5
|
||||||
|
|
|
|
||||||
LL | / unsafe {
|
LL | / unsafe {
|
||||||
LL | | x.0();
|
LL | | x.0();
|
||||||
|
@ -176,12 +176,12 @@ LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
note: unsafe function call occurs here
|
note: unsafe function call occurs here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:145:9
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:146:9
|
||||||
|
|
|
|
||||||
LL | x.0();
|
LL | x.0();
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
note: unsafe function call occurs here
|
note: unsafe function call occurs here
|
||||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:146:9
|
--> tests/ui/multiple_unsafe_ops_per_block.rs:147:9
|
||||||
|
|
|
|
||||||
LL | x.0();
|
LL | x.0();
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
@ -251,3 +251,11 @@ mod issue_10253 {
|
||||||
(&S).f::<()>();
|
(&S).f::<()>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn issue_12268() {
|
||||||
|
let option = Some((&1,));
|
||||||
|
let x = (&1,);
|
||||||
|
option.unwrap_or((x.0,));
|
||||||
|
//~^ ERROR: this expression creates a reference which is immediately dereferenced by the
|
||||||
|
// compiler
|
||||||
|
}
|
||||||
|
|
|
@ -251,3 +251,11 @@ mod issue_10253 {
|
||||||
(&S).f::<()>();
|
(&S).f::<()>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn issue_12268() {
|
||||||
|
let option = Some((&1,));
|
||||||
|
let x = (&1,);
|
||||||
|
option.unwrap_or((&x.0,));
|
||||||
|
//~^ ERROR: this expression creates a reference which is immediately dereferenced by the
|
||||||
|
// compiler
|
||||||
|
}
|
||||||
|
|
|
@ -163,5 +163,11 @@ error: this expression borrows a value the compiler would automatically borrow
|
||||||
LL | let _ = &mut (&mut { x.u }).x;
|
LL | let _ = &mut (&mut { x.u }).x;
|
||||||
| ^^^^^^^^^^^^^^ help: change this to: `{ x.u }`
|
| ^^^^^^^^^^^^^^ help: change this to: `{ x.u }`
|
||||||
|
|
||||||
error: aborting due to 27 previous errors
|
error: this expression creates a reference which is immediately dereferenced by the compiler
|
||||||
|
--> tests/ui/needless_borrow.rs:258:23
|
||||||
|
|
|
||||||
|
LL | option.unwrap_or((&x.0,));
|
||||||
|
| ^^^^ help: change this to: `x.0`
|
||||||
|
|
||||||
|
error: aborting due to 28 previous errors
|
||||||
|
|
||||||
|
|
|
@ -109,4 +109,12 @@ fn dont_warn_for_negated_partial_ord_comparison() {
|
||||||
let _ = !(a >= b);
|
let _ = !(a >= b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn issue_12625() {
|
||||||
|
let a = 0;
|
||||||
|
let b = 0;
|
||||||
|
if (a as u64) < b {} //~ ERROR: this boolean expression can be simplified
|
||||||
|
if (a as u64) < b {} //~ ERROR: this boolean expression can be simplified
|
||||||
|
if a as u64 > b {} //~ ERROR: this boolean expression can be simplified
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -109,4 +109,12 @@ fn dont_warn_for_negated_partial_ord_comparison() {
|
||||||
let _ = !(a >= b);
|
let _ = !(a >= b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn issue_12625() {
|
||||||
|
let a = 0;
|
||||||
|
let b = 0;
|
||||||
|
if !(a as u64 >= b) {} //~ ERROR: this boolean expression can be simplified
|
||||||
|
if !((a as u64) >= b) {} //~ ERROR: this boolean expression can be simplified
|
||||||
|
if !(a as u64 <= b) {} //~ ERROR: this boolean expression can be simplified
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -79,5 +79,23 @@ error: this boolean expression can be simplified
|
||||||
LL | if !res.is_none() {}
|
LL | if !res.is_none() {}
|
||||||
| ^^^^^^^^^^^^^^ help: try: `res.is_some()`
|
| ^^^^^^^^^^^^^^ help: try: `res.is_some()`
|
||||||
|
|
||||||
error: aborting due to 13 previous errors
|
error: this boolean expression can be simplified
|
||||||
|
--> tests/ui/nonminimal_bool_methods.rs:115:8
|
||||||
|
|
|
||||||
|
LL | if !(a as u64 >= b) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^ help: try: `(a as u64) < b`
|
||||||
|
|
||||||
|
error: this boolean expression can be simplified
|
||||||
|
--> tests/ui/nonminimal_bool_methods.rs:116:8
|
||||||
|
|
|
||||||
|
LL | if !((a as u64) >= b) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ help: try: `(a as u64) < b`
|
||||||
|
|
||||||
|
error: this boolean expression can be simplified
|
||||||
|
--> tests/ui/nonminimal_bool_methods.rs:117:8
|
||||||
|
|
|
||||||
|
LL | if !(a as u64 <= b) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^ help: try: `a as u64 > b`
|
||||||
|
|
||||||
|
error: aborting due to 16 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
//@aux-build:proc_macros.rs
|
//@aux-build:proc_macros.rs
|
||||||
//@compile-flags: -Zdeduplicate-diagnostics=yes
|
|
||||||
|
|
||||||
#![warn(clippy::ptr_as_ptr)]
|
#![warn(clippy::ptr_as_ptr)]
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
//@aux-build:proc_macros.rs
|
//@aux-build:proc_macros.rs
|
||||||
//@compile-flags: -Zdeduplicate-diagnostics=yes
|
|
||||||
|
|
||||||
#![warn(clippy::ptr_as_ptr)]
|
#![warn(clippy::ptr_as_ptr)]
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:19:33
|
--> tests/ui/ptr_as_ptr.rs:18:33
|
||||||
|
|
|
|
||||||
LL | *unsafe { Box::from_raw(Box::into_raw(Box::new(o)) as *mut super::issue_11278_a::T<String>) }
|
LL | *unsafe { Box::from_raw(Box::into_raw(Box::new(o)) as *mut super::issue_11278_a::T<String>) }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `Box::into_raw(Box::new(o)).cast::<super::issue_11278_a::T<String>>()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `Box::into_raw(Box::new(o)).cast::<super::issue_11278_a::T<String>>()`
|
||||||
|
@ -8,37 +8,37 @@ LL | *unsafe { Box::from_raw(Box::into_raw(Box::new(o)) as *mut super::i
|
||||||
= help: to override `-D warnings` add `#[allow(clippy::ptr_as_ptr)]`
|
= help: to override `-D warnings` add `#[allow(clippy::ptr_as_ptr)]`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:28:13
|
--> tests/ui/ptr_as_ptr.rs:27:13
|
||||||
|
|
|
|
||||||
LL | let _ = ptr as *const i32;
|
LL | let _ = ptr as *const i32;
|
||||||
| ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
|
| ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:29:13
|
--> tests/ui/ptr_as_ptr.rs:28:13
|
||||||
|
|
|
|
||||||
LL | let _ = mut_ptr as *mut i32;
|
LL | let _ = mut_ptr as *mut i32;
|
||||||
| ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
|
| ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:34:17
|
--> tests/ui/ptr_as_ptr.rs:33:17
|
||||||
|
|
|
|
||||||
LL | let _ = *ptr_ptr as *const i32;
|
LL | let _ = *ptr_ptr as *const i32;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `(*ptr_ptr).cast::<i32>()`
|
| ^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `(*ptr_ptr).cast::<i32>()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:47:25
|
--> tests/ui/ptr_as_ptr.rs:46:25
|
||||||
|
|
|
|
||||||
LL | let _: *const i32 = ptr as *const _;
|
LL | let _: *const i32 = ptr as *const _;
|
||||||
| ^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast()`
|
| ^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:48:23
|
--> tests/ui/ptr_as_ptr.rs:47:23
|
||||||
|
|
|
|
||||||
LL | let _: *mut i32 = mut_ptr as _;
|
LL | let _: *mut i32 = mut_ptr as _;
|
||||||
| ^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast()`
|
| ^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:51:21
|
--> tests/ui/ptr_as_ptr.rs:50:21
|
||||||
|
|
|
|
||||||
LL | let _ = inline!($ptr as *const i32);
|
LL | let _ = inline!($ptr as *const i32);
|
||||||
| ^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `$ptr.cast::<i32>()`
|
| ^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `$ptr.cast::<i32>()`
|
||||||
|
@ -46,157 +46,157 @@ LL | let _ = inline!($ptr as *const i32);
|
||||||
= note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:72:13
|
--> tests/ui/ptr_as_ptr.rs:71:13
|
||||||
|
|
|
|
||||||
LL | let _ = ptr as *const i32;
|
LL | let _ = ptr as *const i32;
|
||||||
| ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
|
| ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:73:13
|
--> tests/ui/ptr_as_ptr.rs:72:13
|
||||||
|
|
|
|
||||||
LL | let _ = mut_ptr as *mut i32;
|
LL | let _ = mut_ptr as *mut i32;
|
||||||
| ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
|
| ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:80:9
|
--> tests/ui/ptr_as_ptr.rs:79:9
|
||||||
|
|
|
|
||||||
LL | ptr::null_mut() as *mut u32
|
LL | ptr::null_mut() as *mut u32
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::<u32>()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::<u32>()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:84:9
|
--> tests/ui/ptr_as_ptr.rs:83:9
|
||||||
|
|
|
|
||||||
LL | std::ptr::null_mut() as *mut u32
|
LL | std::ptr::null_mut() as *mut u32
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut::<u32>()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut::<u32>()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:89:9
|
--> tests/ui/ptr_as_ptr.rs:88:9
|
||||||
|
|
|
|
||||||
LL | ptr::null_mut() as *mut u32
|
LL | ptr::null_mut() as *mut u32
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::<u32>()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::<u32>()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:93:9
|
--> tests/ui/ptr_as_ptr.rs:92:9
|
||||||
|
|
|
|
||||||
LL | core::ptr::null_mut() as *mut u32
|
LL | core::ptr::null_mut() as *mut u32
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut::<u32>()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut::<u32>()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:98:9
|
--> tests/ui/ptr_as_ptr.rs:97:9
|
||||||
|
|
|
|
||||||
LL | ptr::null() as *const u32
|
LL | ptr::null() as *const u32
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::<u32>()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::<u32>()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:102:9
|
--> tests/ui/ptr_as_ptr.rs:101:9
|
||||||
|
|
|
|
||||||
LL | std::ptr::null() as *const u32
|
LL | std::ptr::null() as *const u32
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null::<u32>()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null::<u32>()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:107:9
|
--> tests/ui/ptr_as_ptr.rs:106:9
|
||||||
|
|
|
|
||||||
LL | ptr::null() as *const u32
|
LL | ptr::null() as *const u32
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::<u32>()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::<u32>()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:111:9
|
--> tests/ui/ptr_as_ptr.rs:110:9
|
||||||
|
|
|
|
||||||
LL | core::ptr::null() as *const u32
|
LL | core::ptr::null() as *const u32
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null::<u32>()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null::<u32>()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:118:9
|
--> tests/ui/ptr_as_ptr.rs:117:9
|
||||||
|
|
|
|
||||||
LL | ptr::null_mut() as *mut _
|
LL | ptr::null_mut() as *mut _
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:122:9
|
--> tests/ui/ptr_as_ptr.rs:121:9
|
||||||
|
|
|
|
||||||
LL | std::ptr::null_mut() as *mut _
|
LL | std::ptr::null_mut() as *mut _
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:127:9
|
--> tests/ui/ptr_as_ptr.rs:126:9
|
||||||
|
|
|
|
||||||
LL | ptr::null_mut() as *mut _
|
LL | ptr::null_mut() as *mut _
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:131:9
|
--> tests/ui/ptr_as_ptr.rs:130:9
|
||||||
|
|
|
|
||||||
LL | core::ptr::null_mut() as *mut _
|
LL | core::ptr::null_mut() as *mut _
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:136:9
|
--> tests/ui/ptr_as_ptr.rs:135:9
|
||||||
|
|
|
|
||||||
LL | ptr::null() as *const _
|
LL | ptr::null() as *const _
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:140:9
|
--> tests/ui/ptr_as_ptr.rs:139:9
|
||||||
|
|
|
|
||||||
LL | std::ptr::null() as *const _
|
LL | std::ptr::null() as *const _
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:145:9
|
--> tests/ui/ptr_as_ptr.rs:144:9
|
||||||
|
|
|
|
||||||
LL | ptr::null() as *const _
|
LL | ptr::null() as *const _
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:149:9
|
--> tests/ui/ptr_as_ptr.rs:148:9
|
||||||
|
|
|
|
||||||
LL | core::ptr::null() as *const _
|
LL | core::ptr::null() as *const _
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:156:9
|
--> tests/ui/ptr_as_ptr.rs:155:9
|
||||||
|
|
|
|
||||||
LL | ptr::null_mut() as _
|
LL | ptr::null_mut() as _
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
|
| ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:160:9
|
--> tests/ui/ptr_as_ptr.rs:159:9
|
||||||
|
|
|
|
||||||
LL | std::ptr::null_mut() as _
|
LL | std::ptr::null_mut() as _
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:165:9
|
--> tests/ui/ptr_as_ptr.rs:164:9
|
||||||
|
|
|
|
||||||
LL | ptr::null_mut() as _
|
LL | ptr::null_mut() as _
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
|
| ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:169:9
|
--> tests/ui/ptr_as_ptr.rs:168:9
|
||||||
|
|
|
|
||||||
LL | core::ptr::null_mut() as _
|
LL | core::ptr::null_mut() as _
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:174:9
|
--> tests/ui/ptr_as_ptr.rs:173:9
|
||||||
|
|
|
|
||||||
LL | ptr::null() as _
|
LL | ptr::null() as _
|
||||||
| ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
|
| ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:178:9
|
--> tests/ui/ptr_as_ptr.rs:177:9
|
||||||
|
|
|
|
||||||
LL | std::ptr::null() as _
|
LL | std::ptr::null() as _
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()`
|
| ^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:183:9
|
--> tests/ui/ptr_as_ptr.rs:182:9
|
||||||
|
|
|
|
||||||
LL | ptr::null() as _
|
LL | ptr::null() as _
|
||||||
| ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
|
| ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
|
||||||
|
|
||||||
error: `as` casting between raw pointers without changing its mutability
|
error: `as` casting between raw pointers without changing its mutability
|
||||||
--> tests/ui/ptr_as_ptr.rs:187:9
|
--> tests/ui/ptr_as_ptr.rs:186:9
|
||||||
|
|
|
|
||||||
LL | core::ptr::null() as _
|
LL | core::ptr::null() as _
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()`
|
| ^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()`
|
||||||
|
|
|
@ -213,3 +213,53 @@ mod issue7392 {
|
||||||
let _ = !v.iter().any(|fp| test_u32_2(*fp.field));
|
let _ = !v.iter().any(|fp| test_u32_2(*fp.field));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod issue_11910 {
|
||||||
|
fn computations() -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
impl Foo {
|
||||||
|
fn bar(&self, _: bool) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_normal_for_iter() {
|
||||||
|
let v = vec![3, 2, 1, 0, -1, -2, -3];
|
||||||
|
let _ = !v.iter().any(|x| *x == 42);
|
||||||
|
Foo.bar(!v.iter().any(|x| *x == 42));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_then_for_iter() {
|
||||||
|
let v = vec![3, 2, 1, 0, -1, -2, -3];
|
||||||
|
(!v.iter().any(|x| *x == 42)).then(computations);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_then_some_for_iter() {
|
||||||
|
let v = vec![3, 2, 1, 0, -1, -2, -3];
|
||||||
|
(!v.iter().any(|x| *x == 42)).then_some(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_normal_for_str() {
|
||||||
|
let s = "hello";
|
||||||
|
let _ = !s.contains("world");
|
||||||
|
Foo.bar(!s.contains("world"));
|
||||||
|
let s = String::from("hello");
|
||||||
|
let _ = !s.contains("world");
|
||||||
|
Foo.bar(!s.contains("world"));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_then_for_str() {
|
||||||
|
let s = "hello";
|
||||||
|
let _ = (!s.contains("world")).then(computations);
|
||||||
|
let s = String::from("hello");
|
||||||
|
let _ = (!s.contains("world")).then(computations);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_then_some_for_str() {
|
||||||
|
let s = "hello";
|
||||||
|
let _ = (!s.contains("world")).then_some(0);
|
||||||
|
let s = String::from("hello");
|
||||||
|
let _ = (!s.contains("world")).then_some(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -219,3 +219,53 @@ mod issue7392 {
|
||||||
let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none();
|
let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod issue_11910 {
|
||||||
|
fn computations() -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
impl Foo {
|
||||||
|
fn bar(&self, _: bool) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_normal_for_iter() {
|
||||||
|
let v = vec![3, 2, 1, 0, -1, -2, -3];
|
||||||
|
let _ = v.iter().find(|x| **x == 42).is_none();
|
||||||
|
Foo.bar(v.iter().find(|x| **x == 42).is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_then_for_iter() {
|
||||||
|
let v = vec![3, 2, 1, 0, -1, -2, -3];
|
||||||
|
v.iter().find(|x| **x == 42).is_none().then(computations);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_then_some_for_iter() {
|
||||||
|
let v = vec![3, 2, 1, 0, -1, -2, -3];
|
||||||
|
v.iter().find(|x| **x == 42).is_none().then_some(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_normal_for_str() {
|
||||||
|
let s = "hello";
|
||||||
|
let _ = s.find("world").is_none();
|
||||||
|
Foo.bar(s.find("world").is_none());
|
||||||
|
let s = String::from("hello");
|
||||||
|
let _ = s.find("world").is_none();
|
||||||
|
Foo.bar(s.find("world").is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_then_for_str() {
|
||||||
|
let s = "hello";
|
||||||
|
let _ = s.find("world").is_none().then(computations);
|
||||||
|
let s = String::from("hello");
|
||||||
|
let _ = s.find("world").is_none().then(computations);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_then_some_for_str() {
|
||||||
|
let s = "hello";
|
||||||
|
let _ = s.find("world").is_none().then_some(0);
|
||||||
|
let s = String::from("hello");
|
||||||
|
let _ = s.find("world").is_none().then_some(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -282,5 +282,77 @@ error: called `is_none()` after searching an `Iterator` with `find`
|
||||||
LL | let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none();
|
LL | let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|fp| test_u32_2(*fp.field))`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|fp| test_u32_2(*fp.field))`
|
||||||
|
|
||||||
error: aborting due to 43 previous errors
|
error: called `is_none()` after searching an `Iterator` with `find`
|
||||||
|
--> tests/ui/search_is_some_fixable_none.rs:235:17
|
||||||
|
|
|
||||||
|
LL | let _ = v.iter().find(|x| **x == 42).is_none();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x| *x == 42)`
|
||||||
|
|
||||||
|
error: called `is_none()` after searching an `Iterator` with `find`
|
||||||
|
--> tests/ui/search_is_some_fixable_none.rs:236:17
|
||||||
|
|
|
||||||
|
LL | Foo.bar(v.iter().find(|x| **x == 42).is_none());
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x| *x == 42)`
|
||||||
|
|
||||||
|
error: called `is_none()` after searching an `Iterator` with `find`
|
||||||
|
--> tests/ui/search_is_some_fixable_none.rs:241:9
|
||||||
|
|
|
||||||
|
LL | v.iter().find(|x| **x == 42).is_none().then(computations);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!v.iter().any(|x| *x == 42))`
|
||||||
|
|
||||||
|
error: called `is_none()` after searching an `Iterator` with `find`
|
||||||
|
--> tests/ui/search_is_some_fixable_none.rs:246:9
|
||||||
|
|
|
||||||
|
LL | v.iter().find(|x| **x == 42).is_none().then_some(0);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!v.iter().any(|x| *x == 42))`
|
||||||
|
|
||||||
|
error: called `is_none()` after calling `find()` on a string
|
||||||
|
--> tests/ui/search_is_some_fixable_none.rs:251:17
|
||||||
|
|
|
||||||
|
LL | let _ = s.find("world").is_none();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")`
|
||||||
|
|
||||||
|
error: called `is_none()` after calling `find()` on a string
|
||||||
|
--> tests/ui/search_is_some_fixable_none.rs:252:17
|
||||||
|
|
|
||||||
|
LL | Foo.bar(s.find("world").is_none());
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")`
|
||||||
|
|
||||||
|
error: called `is_none()` after calling `find()` on a string
|
||||||
|
--> tests/ui/search_is_some_fixable_none.rs:254:17
|
||||||
|
|
|
||||||
|
LL | let _ = s.find("world").is_none();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")`
|
||||||
|
|
||||||
|
error: called `is_none()` after calling `find()` on a string
|
||||||
|
--> tests/ui/search_is_some_fixable_none.rs:255:17
|
||||||
|
|
|
||||||
|
LL | Foo.bar(s.find("world").is_none());
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s.contains("world")`
|
||||||
|
|
||||||
|
error: called `is_none()` after calling `find()` on a string
|
||||||
|
--> tests/ui/search_is_some_fixable_none.rs:260:17
|
||||||
|
|
|
||||||
|
LL | let _ = s.find("world").is_none().then(computations);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))`
|
||||||
|
|
||||||
|
error: called `is_none()` after calling `find()` on a string
|
||||||
|
--> tests/ui/search_is_some_fixable_none.rs:262:17
|
||||||
|
|
|
||||||
|
LL | let _ = s.find("world").is_none().then(computations);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))`
|
||||||
|
|
||||||
|
error: called `is_none()` after calling `find()` on a string
|
||||||
|
--> tests/ui/search_is_some_fixable_none.rs:267:17
|
||||||
|
|
|
||||||
|
LL | let _ = s.find("world").is_none().then_some(0);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))`
|
||||||
|
|
||||||
|
error: called `is_none()` after calling `find()` on a string
|
||||||
|
--> tests/ui/search_is_some_fixable_none.rs:269:17
|
||||||
|
|
|
||||||
|
LL | let _ = s.find("world").is_none().then_some(0);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(!s.contains("world"))`
|
||||||
|
|
||||||
|
error: aborting due to 55 previous errors
|
||||||
|
|
||||||
|
|
|
@ -266,7 +266,7 @@ struct S13 {
|
||||||
|
|
||||||
impl S13 {
|
impl S13 {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
// Shoud not warn!
|
// Should not warn!
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,5 +57,41 @@ error: no need to put clippy lints behind a `clippy` cfg
|
||||||
LL | #![cfg_attr(clippy, deny(clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
|
LL | #![cfg_attr(clippy, deny(clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#![deny(clippy::non_minimal_cfg, clippy::maybe_misused_cfg)]`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#![deny(clippy::non_minimal_cfg, clippy::maybe_misused_cfg)]`
|
||||||
|
|
||||||
error: aborting due to 8 previous errors
|
error: duplicated attribute
|
||||||
|
--> tests/ui/unnecessary_clippy_cfg.rs:8:26
|
||||||
|
|
|
||||||
|
LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: first defined here
|
||||||
|
--> tests/ui/unnecessary_clippy_cfg.rs:6:26
|
||||||
|
|
|
||||||
|
LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
|
||||||
|
| ^^^^^^^^^
|
||||||
|
help: remove this attribute
|
||||||
|
--> tests/ui/unnecessary_clippy_cfg.rs:8:26
|
||||||
|
|
|
||||||
|
LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
|
||||||
|
| ^^^^^^^^^
|
||||||
|
= note: `-D clippy::duplicated-attributes` implied by `-D warnings`
|
||||||
|
= help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]`
|
||||||
|
|
||||||
|
error: duplicated attribute
|
||||||
|
--> tests/ui/unnecessary_clippy_cfg.rs:17:25
|
||||||
|
|
|
||||||
|
LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: first defined here
|
||||||
|
--> tests/ui/unnecessary_clippy_cfg.rs:15:25
|
||||||
|
|
|
||||||
|
LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
|
||||||
|
| ^^^^^^^^^
|
||||||
|
help: remove this attribute
|
||||||
|
--> tests/ui/unnecessary_clippy_cfg.rs:17:25
|
||||||
|
|
|
||||||
|
LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 10 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//@aux-build:proc_macro_derive.rs
|
//@aux-build:proc_macro_derive.rs
|
||||||
|
|
||||||
#![allow(unused)]
|
#![allow(unused, clippy::duplicated_attributes)]
|
||||||
#![warn(clippy::useless_attribute)]
|
#![warn(clippy::useless_attribute)]
|
||||||
#![warn(unreachable_pub)]
|
#![warn(unreachable_pub)]
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//@aux-build:proc_macro_derive.rs
|
//@aux-build:proc_macro_derive.rs
|
||||||
|
|
||||||
#![allow(unused)]
|
#![allow(unused, clippy::duplicated_attributes)]
|
||||||
#![warn(clippy::useless_attribute)]
|
#![warn(clippy::useless_attribute)]
|
||||||
#![warn(unreachable_pub)]
|
#![warn(unreachable_pub)]
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
|
|
|
@ -19,7 +19,12 @@ new_pr = true
|
||||||
|
|
||||||
[assign]
|
[assign]
|
||||||
contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md"
|
contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md"
|
||||||
users_on_vacation = ["y21"]
|
users_on_vacation = [
|
||||||
|
"y21",
|
||||||
|
"matthiaskrgr",
|
||||||
|
"giraffate",
|
||||||
|
"Centri3",
|
||||||
|
]
|
||||||
|
|
||||||
[assign.owners]
|
[assign.owners]
|
||||||
"/.github" = ["@flip1995"]
|
"/.github" = ["@flip1995"]
|
||||||
|
|
Loading…
Reference in a new issue