mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Merge commit 'ca3b393750ee8d870bf3215dcf6509cafa5c0445' into clippy-subtree-update
This commit is contained in:
parent
876d5f00a0
commit
a5aaf33422
2
.github/workflows/remark.yml
vendored
2
.github/workflows/remark.yml
vendored
@ -24,7 +24,7 @@ jobs:
|
||||
node-version: '18.x'
|
||||
|
||||
- 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
|
||||
run: |
|
||||
|
@ -5894,6 +5894,7 @@ Released 2018-09-13
|
||||
[`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-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-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
|
||||
|
@ -18,17 +18,27 @@ category.
|
||||
| `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::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::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 might have false positives | allow |
|
||||
| `clippy::pedantic` | lints which are rather strict or have occasional 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::cargo` | lints for the cargo manifest | allow | | allow |
|
||||
| `clippy::cargo` | lints for the cargo manifest | allow |
|
||||
|
||||
More to come, please [file an
|
||||
issue](https://github.com/rust-lang/rust-clippy/issues) if you have ideas!
|
||||
More to come, please [file an 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
|
||||
contains "restriction lints", which are for things which are usually not
|
||||
considered "bad", but may be useful to turn on in specific cases. These should
|
||||
be used very selectively, if at all.
|
||||
The `restriction` category should, *emphatically*, not be enabled as a whole. The contained
|
||||
lints may lint against perfectly reasonable code, may not have an alternative suggestion,
|
||||
and may contradict any other lints (including other categories). Lints should be considered
|
||||
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)
|
||||
- [Rustfix tests](#rustfix-tests)
|
||||
- [Testing manually](#testing-manually)
|
||||
- [Running directly](#running-directly)
|
||||
- [Lint declaration](#lint-declaration)
|
||||
- [Lint registration](#lint-registration)
|
||||
- [Lint passes](#lint-passes)
|
||||
@ -176,23 +175,26 @@ the tests.
|
||||
|
||||
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
|
||||
your local modifications, run
|
||||
your local modifications, run the following from the Clippy directory:
|
||||
|
||||
```
|
||||
```bash
|
||||
cargo dev lint input.rs
|
||||
```
|
||||
|
||||
from the working copy root. With tests in place, let's have a look at
|
||||
implementing our lint now.
|
||||
To run Clippy on an existing project rather than a single file you can use
|
||||
|
||||
## 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
|
||||
`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,
|
||||
add the path printed by`rustc --print target-libdir` (ran inside this workspace so that the rustc version matches)
|
||||
to your library search path.
|
||||
On linux, this can be done by setting the `LD_LIBRARY_PATH` environment variable to that path.
|
||||
Or set up a rustup toolchain that points to the local Clippy binaries
|
||||
|
||||
```bash
|
||||
cargo dev setup toolchain
|
||||
|
||||
# Then in `/path/to/project` you can run
|
||||
cargo +clippy clippy
|
||||
```
|
||||
|
||||
## 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)
|
||||
|
||||
|
||||
## `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`
|
||||
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_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
|
||||
#[derive(Default)]
|
||||
@ -589,6 +590,26 @@ define_Conf! {
|
||||
/// 2. Paths with any segment that containing the word 'prelude'
|
||||
/// are already allowed by 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.
|
||||
@ -649,6 +670,7 @@ fn deserialize(file: &SourceFile) -> TryConf {
|
||||
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.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
|
||||
if conf.conf.allowed_idents_below_min_chars.contains("..") {
|
||||
conf.conf
|
||||
|
@ -35,7 +35,6 @@ struct FmtContext {
|
||||
}
|
||||
|
||||
// the "main" function of cargo dev fmt
|
||||
#[allow(clippy::missing_panics_doc)]
|
||||
pub fn run(check: bool, verbose: bool) {
|
||||
fn try_run(context: &FmtContext) -> Result<bool, CliError> {
|
||||
let mut success = true;
|
||||
|
@ -9,6 +9,7 @@
|
||||
unused_lifetimes,
|
||||
unused_qualifications
|
||||
)]
|
||||
#![allow(clippy::missing_panics_doc)]
|
||||
|
||||
// The `rustc_driver` crate seems to be required in order to use the `rust_lexer` crate.
|
||||
#[allow(unused_extern_crates)]
|
||||
|
@ -46,6 +46,13 @@ fn main() {
|
||||
}
|
||||
},
|
||||
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)) => {
|
||||
if matches.get_flag("remove") {
|
||||
setup::intellij::remove_rustc_src();
|
||||
@ -57,12 +64,12 @@ fn main() {
|
||||
);
|
||||
}
|
||||
},
|
||||
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(("toolchain", matches)) => {
|
||||
setup::toolchain::create(
|
||||
matches.get_flag("force"),
|
||||
matches.get_flag("release"),
|
||||
matches.get_one::<String>("name").unwrap(),
|
||||
);
|
||||
},
|
||||
Some(("vscode-tasks", matches)) => {
|
||||
if matches.get_flag("remove") {
|
||||
@ -210,6 +217,19 @@ fn get_clap_config() -> ArgMatches {
|
||||
.about("Support for setting up your personal development environment")
|
||||
.arg_required_else_help(true)
|
||||
.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")
|
||||
.about("Alter dependencies so Intellij Rust can find rustc internals")
|
||||
.args([
|
||||
@ -225,18 +245,23 @@ fn get_clap_config() -> ArgMatches {
|
||||
.conflicts_with("remove")
|
||||
.required(true),
|
||||
]),
|
||||
Command::new("git-hook")
|
||||
.about("Add a pre-commit git hook that formats your code to make it look pretty")
|
||||
Command::new("toolchain")
|
||||
.about("Install a rustup toolchain pointing to the local clippy build")
|
||||
.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")
|
||||
Arg::new("force")
|
||||
.long("force")
|
||||
.short('f')
|
||||
.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")
|
||||
.about("Add several tasks to vscode for formatting, validation and testing")
|
||||
|
@ -36,7 +36,6 @@ impl<T> Context for io::Result<T> {
|
||||
/// # Errors
|
||||
///
|
||||
/// This function errors out if the files couldn't be created or written to.
|
||||
#[allow(clippy::missing_panics_doc)]
|
||||
pub fn create(
|
||||
pass: &String,
|
||||
lint_name: Option<&String>,
|
||||
|
@ -1,5 +1,6 @@
|
||||
pub mod git_hook;
|
||||
pub mod intellij;
|
||||
pub mod toolchain;
|
||||
pub mod vscode;
|
||||
|
||||
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(sync) = cx.tcx.lang_items().sync_trait()
|
||||
&& 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)
|
||||
{
|
||||
span_lint_and_then(
|
||||
@ -66,21 +71,12 @@ impl<'tcx> LateLintPass<'tcx> for ArcWithNonSendSync {
|
||||
"usage of an `Arc` that is not `Send` and `Sync`",
|
||||
|diag| {
|
||||
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!(
|
||||
"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 rustc_ast::{Attribute, MetaItem};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::{sym, Span};
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
fn emit_if_duplicated(
|
||||
cx: &EarlyContext<'_>,
|
||||
cx: &LateContext<'_>,
|
||||
attr: &MetaItem,
|
||||
attr_paths: &mut FxHashMap<String, Span>,
|
||||
complete_path: String,
|
||||
@ -26,7 +26,7 @@ fn emit_if_duplicated(
|
||||
}
|
||||
|
||||
fn check_duplicated_attr(
|
||||
cx: &EarlyContext<'_>,
|
||||
cx: &LateContext<'_>,
|
||||
attr: &MetaItem,
|
||||
attr_paths: &mut FxHashMap<String, Span>,
|
||||
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();
|
||||
|
||||
for attr in attrs {
|
||||
|
@ -17,7 +17,7 @@ mod useless_attribute;
|
||||
mod utils;
|
||||
|
||||
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_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, impl_lint_pass};
|
||||
@ -534,11 +534,13 @@ declare_lint_pass!(Attributes => [
|
||||
BLANKET_CLIPPY_RESTRICTION_LINTS,
|
||||
SHOULD_PANIC_WITHOUT_EXPECT,
|
||||
MIXED_ATTRIBUTES_STYLE,
|
||||
DUPLICATED_ATTRIBUTES,
|
||||
]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for Attributes {
|
||||
fn check_crate(&mut self, cx: &LateContext<'tcx>) {
|
||||
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) {
|
||||
@ -578,6 +580,7 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
|
||||
_ => {},
|
||||
}
|
||||
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<'_>) {
|
||||
@ -606,17 +609,11 @@ impl_lint_pass!(EarlyAttributes => [
|
||||
MAYBE_MISUSED_CFG,
|
||||
DEPRECATED_CLIPPY_CFG_ATTR,
|
||||
UNNECESSARY_CLIPPY_CFG,
|
||||
DUPLICATED_ATTRIBUTES,
|
||||
]);
|
||||
|
||||
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) {
|
||||
empty_line_after::check(cx, item);
|
||||
duplicated_attributes::check(cx, &item.attrs);
|
||||
}
|
||||
|
||||
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||
|
@ -346,11 +346,18 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
|
||||
_ => None,
|
||||
}
|
||||
.and_then(|op| {
|
||||
Some(format!(
|
||||
"{}{op}{}",
|
||||
snippet_opt(cx, lhs.span)?,
|
||||
snippet_opt(cx, rhs.span)?
|
||||
))
|
||||
let lhs_snippet = snippet_opt(cx, lhs.span)?;
|
||||
let rhs_snippet = 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, [], _) => {
|
||||
|
@ -754,11 +754,7 @@ impl_lint_pass!(Casts => [
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for Casts {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if !in_external_macro(cx.sess(), expr.span) {
|
||||
ptr_as_ptr::check(cx, expr, &self.msrv);
|
||||
}
|
||||
|
||||
if expr.span.from_expansion() {
|
||||
if in_external_macro(cx.sess(), expr.span) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -771,7 +767,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
|
||||
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;
|
||||
}
|
||||
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);
|
||||
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);
|
||||
if cast_from.is_numeric() {
|
||||
cast_possible_wrap::check(cx, expr, cast_from, cast_to);
|
||||
|
@ -1016,9 +1016,18 @@ fn report<'tcx>(
|
||||
},
|
||||
_ => (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
|
||||
&& (calls_field || expr.precedence().order() < precedence)
|
||||
&& !has_enclosing_paren(&snip)
|
||||
&& !is_in_tuple
|
||||
{
|
||||
format!("({snip})")
|
||||
} else {
|
||||
|
@ -132,7 +132,7 @@ declare_clippy_lint! {
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Deriving `serde::Deserialize` will create a constructor
|
||||
/// that may violate invariants hold by another constructor.
|
||||
/// that may violate invariants held by another constructor.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust,ignore
|
||||
|
@ -11,7 +11,7 @@ use super::{DocHeaders, MISSING_ERRORS_DOC, MISSING_PANICS_DOC, MISSING_SAFETY_D
|
||||
pub fn check(
|
||||
cx: &LateContext<'_>,
|
||||
owner_id: OwnerId,
|
||||
sig: &FnSig<'_>,
|
||||
sig: FnSig<'_>,
|
||||
headers: DocHeaders,
|
||||
body_id: Option<BodyId>,
|
||||
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::ty::is_type_diagnostic_item;
|
||||
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::{
|
||||
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 rustc_ast::ast::Attribute;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir as hir;
|
||||
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_middle::hir::nested_filter;
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
@ -366,7 +365,6 @@ declare_clippy_lint! {
|
||||
#[derive(Clone)]
|
||||
pub struct Documentation {
|
||||
valid_idents: FxHashSet<String>,
|
||||
in_trait_impl: bool,
|
||||
check_private_items: bool,
|
||||
}
|
||||
|
||||
@ -374,7 +372,6 @@ impl Documentation {
|
||||
pub fn new(valid_idents: &[String], check_private_items: bool) -> Self {
|
||||
Self {
|
||||
valid_idents: valid_idents.iter().cloned().collect(),
|
||||
in_trait_impl: false,
|
||||
check_private_items,
|
||||
}
|
||||
}
|
||||
@ -394,36 +391,72 @@ impl_lint_pass!(Documentation => [
|
||||
]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for Documentation {
|
||||
fn check_crate(&mut self, cx: &LateContext<'tcx>) {
|
||||
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());
|
||||
fn check_attributes(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) {
|
||||
let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else {
|
||||
return;
|
||||
};
|
||||
|
||||
match item.kind {
|
||||
hir::ItemKind::Fn(ref sig, _, 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);
|
||||
match cx.tcx.hir_node(cx.last_node_with_lint_attrs) {
|
||||
Node::Item(item) => match item.kind {
|
||||
ItemKind::Fn(sig, _, 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(
|
||||
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,
|
||||
headers,
|
||||
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_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::HirId;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::HirId;
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::ty;
|
||||
|
@ -5,6 +5,7 @@ use clippy_utils::is_bool;
|
||||
use clippy_utils::macros::span_is_local;
|
||||
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 rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir::{EnumDef, FieldDef, Item, ItemKind, OwnerId, Variant, VariantData};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::impl_lint_pass;
|
||||
@ -147,6 +148,7 @@ pub struct ItemNameRepetitions {
|
||||
struct_threshold: u64,
|
||||
avoid_breaking_exported_api: bool,
|
||||
allow_private_module_inception: bool,
|
||||
allowed_prefixes: FxHashSet<String>,
|
||||
}
|
||||
|
||||
impl ItemNameRepetitions {
|
||||
@ -156,6 +158,7 @@ impl ItemNameRepetitions {
|
||||
struct_threshold: u64,
|
||||
avoid_breaking_exported_api: bool,
|
||||
allow_private_module_inception: bool,
|
||||
allowed_prefixes: &[String],
|
||||
) -> Self {
|
||||
Self {
|
||||
modules: Vec::new(),
|
||||
@ -163,8 +166,13 @@ impl ItemNameRepetitions {
|
||||
struct_threshold,
|
||||
avoid_breaking_exported_api,
|
||||
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 => [
|
||||
@ -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(
|
||||
cx,
|
||||
MODULE_NAME_REPETITIONS,
|
||||
|
@ -17,7 +17,7 @@ declare_clippy_lint! {
|
||||
/// `std::<float>::EPSILON`, etc.
|
||||
///
|
||||
/// ### 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.
|
||||
///
|
||||
/// ### Example
|
||||
|
@ -594,6 +594,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
|
||||
pub_underscore_fields_behavior,
|
||||
ref allowed_duplicate_crates,
|
||||
allow_comparison_to_zero,
|
||||
ref allowed_prefixes,
|
||||
|
||||
blacklisted_names: _,
|
||||
cyclomatic_complexity_threshold: _,
|
||||
@ -864,6 +865,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
|
||||
struct_field_name_threshold,
|
||||
avoid_breaking_exported_api,
|
||||
allow_private_module_inception,
|
||||
allowed_prefixes,
|
||||
))
|
||||
});
|
||||
store.register_early_pass(|| Box::new(tabs_in_doc_comments::TabsInDocComments));
|
||||
|
@ -291,10 +291,7 @@ fn elision_suggestions(
|
||||
}) => {
|
||||
// expand `&'a T` to `&'a T`
|
||||
// ^^ ^^^
|
||||
let span = cx
|
||||
.sess()
|
||||
.source_map()
|
||||
.span_extend_while_whitespace(usage.ident.span);
|
||||
let span = cx.sess().source_map().span_extend_while_whitespace(usage.ident.span);
|
||||
|
||||
(span, String::new())
|
||||
},
|
||||
|
@ -1,13 +1,14 @@
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, MatchSource, Pat, PatKind, QPath};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::ty::GenericArgKind;
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::sym;
|
||||
|
||||
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::{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 {
|
||||
let ExprKind::Match(match_expr, [arm1, arm2], MatchSource::Normal | MatchSource::ForLoopDesugar) = expr.kind else {
|
||||
return false;
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
fn handle<'tcx>(cx: &LateContext<'tcx>, if_let_or_match: IfLetOrMatch<'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||
// 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()
|
||||
&& arm2.guard.is_none()
|
||||
// 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, &[])
|
||||
// We now get the bodies for both the `Some` and `None` arms.
|
||||
&& let Some(((body_some, binding_id), body_none)) = get_some_and_none_bodies(cx, arm1, arm2)
|
||||
|
||||
// We check if the return type of the expression implements Default.
|
||||
let expr_type = cx.typeck_results().expr_ty(expr);
|
||||
if let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default)
|
||||
&& implements_trait(cx, expr_type, default_trait_id, &[])
|
||||
// We check if the initial condition implements Default.
|
||||
&& let Some(condition_ty) = cx.typeck_results().expr_ty(condition).walk().nth(1)
|
||||
&& let GenericArgKind::Type(condition_ty) = condition_ty.unpack()
|
||||
&& 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`.
|
||||
&& let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(body_some).kind
|
||||
&& 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`.
|
||||
&& let body_none = peel_blocks(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) {
|
||||
Applicability::MaybeIncorrect
|
||||
} else {
|
||||
@ -136,48 +158,12 @@ fn handle_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
|
||||
cx,
|
||||
MANUAL_UNWRAP_OR_DEFAULT,
|
||||
expr.span,
|
||||
"match can be simplified with `.unwrap_or_default()`",
|
||||
format!("{expr_name} can be simplified with `.unwrap_or_default()`"),
|
||||
"replace it with",
|
||||
format!("{receiver}.unwrap_or_default()"),
|
||||
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 {
|
||||
@ -185,8 +171,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualUnwrapOrDefault {
|
||||
if expr.span.from_expansion() || in_constant(cx, expr.hir_id) {
|
||||
return;
|
||||
}
|
||||
if !handle_match(cx, expr) {
|
||||
handle_if_let(cx, expr);
|
||||
// Call handle only if the expression is `if let` or `match`
|
||||
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
|
||||
/// `"\r\n"`), for example during the parsing of a specific file format in which precisely one newline type is
|
||||
/// valid.
|
||||
/// ```
|
||||
#[clippy::version = "1.77.0"]
|
||||
pub STR_SPLIT_AT_NEWLINE,
|
||||
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::sugg::deref_closure_args;
|
||||
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_hir as hir;
|
||||
use rustc_hir::PatKind;
|
||||
@ -35,7 +36,7 @@ pub(super) fn check<'tcx>(
|
||||
// suggest `any(|..| *..)` instead of `any(|..| **..)` for `find(|..| **..).is_some()`
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
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 Some(closure_arg) = closure_body.params.first()
|
||||
{
|
||||
@ -72,16 +73,24 @@ pub(super) fn check<'tcx>(
|
||||
);
|
||||
} else {
|
||||
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(
|
||||
cx,
|
||||
SEARCH_IS_SOME,
|
||||
expr.span,
|
||||
msg,
|
||||
"consider using",
|
||||
format!(
|
||||
"!{iter}.any({})",
|
||||
any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
|
||||
),
|
||||
sugg,
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
@ -127,13 +136,18 @@ pub(super) fn check<'tcx>(
|
||||
let string = snippet(cx, search_recv.span, "..");
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
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(
|
||||
cx,
|
||||
SEARCH_IS_SOME,
|
||||
expr.span,
|
||||
msg,
|
||||
"consider using",
|
||||
format!("!{string}.contains({find_arg})"),
|
||||
sugg,
|
||||
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! {
|
||||
/// ### 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.
|
||||
///
|
||||
/// ### 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::{self, Ty, TyCtxt};
|
||||
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;
|
||||
|
||||
// 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 {
|
||||
let args = cx.typeck_results().node_args(hir_id);
|
||||
|
||||
let result = Self::const_eval_resolve(
|
||||
cx.tcx,
|
||||
cx.param_env,
|
||||
ty::UnevaluatedConst::new(def_id, args),
|
||||
DUMMY_SP,
|
||||
);
|
||||
let result = Self::const_eval_resolve(cx.tcx, cx.param_env, ty::UnevaluatedConst::new(def_id, args), DUMMY_SP);
|
||||
self.is_value_unfrozen_raw(cx, result, ty)
|
||||
}
|
||||
|
||||
|
@ -300,11 +300,8 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
|
||||
e.span,
|
||||
"calling `as_bytes()` on `include_str!(..)`",
|
||||
"consider using `include_bytes!(..)` instead",
|
||||
snippet_with_applicability(cx, receiver.span.source_callsite(), r#""foo""#, &mut applicability).replacen(
|
||||
"include_str",
|
||||
"include_bytes",
|
||||
1,
|
||||
),
|
||||
snippet_with_applicability(cx, receiver.span.source_callsite(), r#""foo""#, &mut applicability)
|
||||
.replacen("include_str", "include_bytes", 1),
|
||||
applicability,
|
||||
);
|
||||
} 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.
|
||||
let coercable_types = [
|
||||
let coercible_types = [
|
||||
("NonZeroU8", tcx.types.u8),
|
||||
("NonZeroU16", tcx.types.u16),
|
||||
("NonZeroU32", tcx.types.u32),
|
||||
@ -44,7 +44,7 @@ pub(super) fn check<'tcx>(
|
||||
|
||||
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 {
|
||||
Some(nonzero_alias)
|
||||
} else {
|
||||
|
@ -1,10 +1,10 @@
|
||||
use rustc_hir_typeck::cast::check_cast;
|
||||
use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use rustc_ast::ExprPrecedence;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, Node};
|
||||
use rustc_hir_typeck::cast::check_cast;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::cast::CastKind;
|
||||
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)),
|
||||
(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),
|
||||
(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)),
|
||||
(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)
|
||||
})
|
||||
},
|
||||
(Typeof(l), Typeof(r)) => eq_expr(&l.value, &r.value),
|
||||
(MacCall(l), MacCall(r)) => eq_mac_call(l, r),
|
||||
_ => false,
|
||||
|
@ -3285,7 +3285,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
|
||||
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 path = Vec::new();
|
||||
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_id::DefId;
|
||||
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_lint::LateContext;
|
||||
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) {
|
||||
certainty.with_def_id(def_id)
|
||||
} else {
|
||||
certainty
|
||||
certainty.clear_def_id()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,12 +26,12 @@ use std::env::consts::EXE_SUFFIX;
|
||||
use std::fmt::{self, Write as _};
|
||||
use std::io::{self, ErrorKind};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::process::{Command, ExitStatus};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::time::Duration;
|
||||
use std::{env, fs, thread};
|
||||
|
||||
use cargo_metadata::diagnostic::{Diagnostic, DiagnosticLevel};
|
||||
use cargo_metadata::diagnostic::Diagnostic;
|
||||
use cargo_metadata::Message;
|
||||
use rayon::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -97,16 +97,43 @@ struct Crate {
|
||||
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`
|
||||
#[derive(Debug)]
|
||||
struct ClippyWarning {
|
||||
crate_name: String,
|
||||
file: String,
|
||||
line: usize,
|
||||
column: usize,
|
||||
lint_type: String,
|
||||
message: String,
|
||||
is_ice: bool,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
@ -131,13 +158,11 @@ impl ClippyWarning {
|
||||
};
|
||||
|
||||
Some(Self {
|
||||
crate_name: crate_name.to_owned(),
|
||||
file,
|
||||
line: span.line_start,
|
||||
column: span.column_start,
|
||||
lint_type,
|
||||
message: diag.message,
|
||||
is_ice: diag.level == DiagnosticLevel::Ice,
|
||||
})
|
||||
}
|
||||
|
||||
@ -318,7 +343,7 @@ impl Crate {
|
||||
config: &LintcheckConfig,
|
||||
lint_filter: &[String],
|
||||
server: &Option<LintcheckServer>,
|
||||
) -> Vec<ClippyWarning> {
|
||||
) -> Vec<ClippyCheckOutput> {
|
||||
// advance the atomic index by one
|
||||
let index = target_dir_index.fetch_add(1, Ordering::SeqCst);
|
||||
// "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 mut cargo_clippy_args = if config.fix {
|
||||
vec!["--fix", "--"]
|
||||
vec!["--quiet", "--fix", "--"]
|
||||
} else {
|
||||
vec!["--", "--message-format=json", "--"]
|
||||
vec!["--quiet", "--message-format=json", "--"]
|
||||
};
|
||||
|
||||
let mut clippy_args = Vec::<&str>::new();
|
||||
@ -435,14 +460,21 @@ impl Crate {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
Ok(Message::CompilerMessage(message)) => ClippyWarning::new(message.message, &self.name, &self.version),
|
||||
_ => None,
|
||||
})
|
||||
.map(ClippyCheckOutput::ClippyWarning)
|
||||
.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)
|
||||
});
|
||||
|
||||
let mut clippy_warnings: Vec<ClippyWarning> = crates
|
||||
let mut clippy_entries: Vec<ClippyCheckOutput> = crates
|
||||
.par_iter()
|
||||
.flat_map(|krate| {
|
||||
krate.run_clippy_lints(
|
||||
@ -658,7 +690,9 @@ fn main() {
|
||||
.collect();
|
||||
|
||||
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
|
||||
@ -666,20 +700,21 @@ fn main() {
|
||||
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
|
||||
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 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();
|
||||
let mut all_msgs: Vec<String> = warnings.iter().map(|warn| warn.to_output(config.markdown)).collect();
|
||||
all_msgs.sort();
|
||||
all_msgs.push("\n\n### Stats:\n\n".into());
|
||||
all_msgs.push(stats_formatted);
|
||||
@ -693,11 +728,18 @@ fn main() {
|
||||
}
|
||||
write!(text, "{}", all_msgs.join("")).unwrap();
|
||||
text.push_str("\n\n### ICEs:\n");
|
||||
for (cratename, msg) in &ices {
|
||||
let _: fmt::Result = write!(text, "{cratename}: '{msg}'");
|
||||
for ice in &raw_ices {
|
||||
let _: fmt::Result = write!(
|
||||
text,
|
||||
"{}:\n{}\n========================================\n\n",
|
||||
ice.crate_name, ice.ice_content
|
||||
);
|
||||
}
|
||||
|
||||
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::write(&config.lintcheck_results_path, text).unwrap();
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2024-04-04"
|
||||
channel = "nightly-2024-04-18"
|
||||
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 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: "this compiler `.*` is outdated" -> "this compiler <version> is outdated"
|
||||
|
||||
#![deny(clippy::internal)]
|
||||
#![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.
|
||||
|
||||
note: it seems that this compiler <version> is outdated, a newer nightly should have been released in the meantime
|
||||
|
|
||||
= note: please consider running `rustup update nightly` to update the nightly channel and check if this problem still persists
|
||||
= 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: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml
|
||||
|
||||
note: please make sure that you have updated to the latest nightly
|
||||
|
||||
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-duplicate-crates
|
||||
allowed-idents-below-min-chars
|
||||
allowed-prefixes
|
||||
allowed-scripts
|
||||
allowed-wildcard-imports
|
||||
arithmetic-side-effects-allowed
|
||||
@ -93,6 +94,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
|
||||
allowed-dotfiles
|
||||
allowed-duplicate-crates
|
||||
allowed-idents-below-min-chars
|
||||
allowed-prefixes
|
||||
allowed-scripts
|
||||
allowed-wildcard-imports
|
||||
arithmetic-side-effects-allowed
|
||||
@ -172,6 +174,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni
|
||||
allowed-dotfiles
|
||||
allowed-duplicate-crates
|
||||
allowed-idents-below-min-chars
|
||||
allowed-prefixes
|
||||
allowed-scripts
|
||||
allowed-wildcard-imports
|
||||
arithmetic-side-effects-allowed
|
||||
|
@ -33,16 +33,9 @@ fn main() {
|
||||
let _ = Arc::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 _ = 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);
|
||||
//~^ 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));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `Arc<RefCell<i32>>` is not `Send` and `Sync` as:
|
||||
= note: - the trait `Sync` is not implemented for `RefCell<i32>`
|
||||
= 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 `RefCell<i32>`
|
||||
= note: `Arc<RefCell<i32>>` is not `Send` and `Sync` as `RefCell<i32>` is not `Sync`
|
||||
= help: if the `Arc` will not used be across threads replace it with an `Rc`
|
||||
= help: otherwise make `RefCell<i32>` `Send` and `Sync` or consider a wrapper type such as `Mutex`
|
||||
= 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)]`
|
||||
|
||||
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());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `Arc<MutexGuard<'_, i32>>` is not `Send` and `Sync` as:
|
||||
= note: - the trait `Send` is not implemented for `MutexGuard<'_, i32>`
|
||||
= 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 `MutexGuard<'_, i32>`
|
||||
= note: `Arc<MutexGuard<'_, i32>>` is not `Send` and `Sync` as `MutexGuard<'_, i32>` is not `Send`
|
||||
= help: if the `Arc` will not used be across threads replace it with an `Rc`
|
||||
= help: otherwise make `MutexGuard<'_, i32>` `Send` and `Sync` or consider a wrapper type such as `Mutex`
|
||||
|
||||
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);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `Arc<*const i32>` is not `Send` and `Sync` as:
|
||||
= note: - the trait `Send` is not implemented for `*const i32`
|
||||
= note: - the trait `Sync` is not implemented for `*const i32`
|
||||
= 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`
|
||||
= note: `Arc<*const i32>` is not `Send` and `Sync` as `*const i32` is neither `Send` nor `Sync`
|
||||
= help: if the `Arc` will not used be across threads replace it with an `Rc`
|
||||
= help: otherwise make `*const i32` `Send` and `Sync` or consider a wrapper type such as `Mutex`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -176,3 +176,17 @@ pub fn with_empty_docs(_attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||
}
|
||||
.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 {
|
||||
let bar: Result<Option<i64>, u32> = Ok(Some(10));
|
||||
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
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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
|
||||
--> tests/ui/cast.rs:468:5
|
||||
--> tests/ui/cast.rs:480:5
|
||||
|
|
||||
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
|
||||
--> tests/ui/cast.rs:468:5
|
||||
--> tests/ui/cast.rs:480:5
|
||||
|
|
||||
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`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::ptr_as_ptr)]`
|
||||
|
||||
error: `as` casting between raw pointers without changing its mutability
|
||||
--> 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
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -235,3 +235,8 @@ fn parenthesized_word() {}
|
||||
/// OSes
|
||||
/// UXes
|
||||
fn plural_acronym_test() {}
|
||||
|
||||
extern {
|
||||
/// `foo()`
|
||||
fn in_extern();
|
||||
}
|
||||
|
@ -235,3 +235,8 @@ fn parenthesized_word() {}
|
||||
/// OSes
|
||||
/// UXes
|
||||
fn plural_acronym_test() {}
|
||||
|
||||
extern {
|
||||
/// foo()
|
||||
fn in_extern();
|
||||
}
|
||||
|
@ -352,5 +352,16 @@ help: try
|
||||
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)]
|
||||
#![cfg(any(unix, windows))]
|
||||
#![allow(dead_code)]
|
||||
#![allow(dead_code)] //~ ERROR: duplicated attribute
|
||||
#![cfg(any(unix, windows))] // Should not warn!
|
||||
|
||||
#[macro_use]
|
||||
extern crate proc_macro_attr;
|
||||
|
||||
#[cfg(any(unix, windows, target_os = "linux"))]
|
||||
#[allow(dead_code)]
|
||||
#[allow(dead_code)] //~ ERROR: duplicated attribute
|
||||
@ -12,7 +17,10 @@ fn foo() {}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(windows)]
|
||||
#[cfg(unix)] //~ ERROR: duplicated attribute
|
||||
#[cfg(unix)] // cfgs are not handled
|
||||
fn bar() {}
|
||||
|
||||
#[proc_macro_attr::duplicated_attr()] // Should not warn!
|
||||
fn babar() {}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,16 +1,16 @@
|
||||
error: duplicated attribute
|
||||
--> tests/ui/duplicated_attributes.rs:4:10
|
||||
--> tests/ui/duplicated_attributes.rs:6:10
|
||||
|
|
||||
LL | #![allow(dead_code)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
note: first defined here
|
||||
--> tests/ui/duplicated_attributes.rs:3:10
|
||||
--> tests/ui/duplicated_attributes.rs:5:10
|
||||
|
|
||||
LL | #![allow(dead_code)]
|
||||
| ^^^^^^^^^
|
||||
help: remove this attribute
|
||||
--> tests/ui/duplicated_attributes.rs:4:10
|
||||
--> tests/ui/duplicated_attributes.rs:6:10
|
||||
|
|
||||
LL | #![allow(dead_code)]
|
||||
| ^^^^^^^^^
|
||||
@ -18,38 +18,21 @@ LL | #![allow(dead_code)]
|
||||
= help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]`
|
||||
|
||||
error: duplicated attribute
|
||||
--> tests/ui/duplicated_attributes.rs:9:9
|
||||
--> tests/ui/duplicated_attributes.rs:14:9
|
||||
|
|
||||
LL | #[allow(dead_code)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
note: first defined here
|
||||
--> tests/ui/duplicated_attributes.rs:8:9
|
||||
--> tests/ui/duplicated_attributes.rs:13:9
|
||||
|
|
||||
LL | #[allow(dead_code)]
|
||||
| ^^^^^^^^^
|
||||
help: remove this attribute
|
||||
--> tests/ui/duplicated_attributes.rs:9:9
|
||||
--> tests/ui/duplicated_attributes.rs:14:9
|
||||
|
|
||||
LL | #[allow(dead_code)]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: duplicated attribute
|
||||
--> 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
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -16,6 +16,16 @@ fn main() {
|
||||
|
||||
let x: Option<Vec<String>> = None;
|
||||
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
|
||||
|
@ -37,6 +37,16 @@ fn main() {
|
||||
} else {
|
||||
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
|
||||
|
@ -53,7 +53,7 @@ LL | | };
|
||||
| |_____^ help: replace it with: `x.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 {
|
||||
| ____________________^
|
||||
|
@ -19,6 +19,20 @@ mod foo {
|
||||
|
||||
// Should not warn
|
||||
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() {}
|
||||
|
@ -1,3 +1,4 @@
|
||||
//@needs-asm-support
|
||||
//@aux-build:proc_macros.rs
|
||||
#![allow(unused)]
|
||||
#![allow(deref_nullptr)]
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 | | STATIC += 1;
|
||||
@ -8,12 +8,12 @@ LL | | }
|
||||
| |_____^
|
||||
|
|
||||
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;
|
||||
| ^^^^^^^^^^^
|
||||
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();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
@ -21,7 +21,7 @@ LL | not_very_safe();
|
||||
= help: to override `-D warnings` add `#[allow(clippy::multiple_unsafe_ops_per_block)]`
|
||||
|
||||
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 | | drop(u.u);
|
||||
@ -30,18 +30,18 @@ LL | | }
|
||||
| |_____^
|
||||
|
|
||||
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);
|
||||
| ^^^
|
||||
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();
|
||||
| ^^^^^^^^^^
|
||||
|
||||
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 | | asm!("nop");
|
||||
@ -51,23 +51,23 @@ LL | | }
|
||||
| |_____^
|
||||
|
|
||||
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");
|
||||
| ^^^^^^^^^^^
|
||||
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();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
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;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
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 | | drop(u.u);
|
||||
@ -79,55 +79,55 @@ LL | | }
|
||||
| |_____^
|
||||
|
|
||||
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);
|
||||
| ^^^
|
||||
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);
|
||||
| ^^^^^^
|
||||
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();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
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();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
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();
|
||||
| ^^^^^^^^^^
|
||||
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");
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
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>()) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
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>()) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
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>()) }
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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 | | x();
|
||||
@ -136,18 +136,18 @@ LL | | }
|
||||
| |_____^
|
||||
|
|
||||
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();
|
||||
| ^^^
|
||||
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();
|
||||
| ^^^
|
||||
|
||||
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 | | T::X();
|
||||
@ -156,18 +156,18 @@ LL | | }
|
||||
| |_________^
|
||||
|
|
||||
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();
|
||||
| ^^^^^^
|
||||
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();
|
||||
| ^^^^^^
|
||||
|
||||
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 | | x.0();
|
||||
@ -176,12 +176,12 @@ LL | | }
|
||||
| |_____^
|
||||
|
|
||||
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();
|
||||
| ^^^^^
|
||||
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();
|
||||
| ^^^^^
|
||||
|
@ -251,3 +251,11 @@ mod issue_10253 {
|
||||
(&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::<()>();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
| ^^^^^^^^^^^^^^ 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);
|
||||
}
|
||||
|
||||
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() {}
|
||||
|
@ -109,4 +109,12 @@ fn dont_warn_for_negated_partial_ord_comparison() {
|
||||
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() {}
|
||||
|
@ -79,5 +79,23 @@ error: this boolean expression can be simplified
|
||||
LL | if !res.is_none() {}
|
||||
| ^^^^^^^^^^^^^^ 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
|
||||
//@compile-flags: -Zdeduplicate-diagnostics=yes
|
||||
|
||||
#![warn(clippy::ptr_as_ptr)]
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
//@aux-build:proc_macros.rs
|
||||
//@compile-flags: -Zdeduplicate-diagnostics=yes
|
||||
|
||||
#![warn(clippy::ptr_as_ptr)]
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
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>) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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)]`
|
||||
|
||||
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;
|
||||
| ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
|
||||
|
||||
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;
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
|
||||
|
||||
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;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `(*ptr_ptr).cast::<i32>()`
|
||||
|
||||
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 _;
|
||||
| ^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast()`
|
||||
|
||||
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 _;
|
||||
| ^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast()`
|
||||
|
||||
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);
|
||||
| ^^^^^^^^^^^^^^^^^^ 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)
|
||||
|
||||
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;
|
||||
| ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
|
||||
|
||||
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;
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
|
||||
|
||||
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
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::<u32>()`
|
||||
|
||||
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
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut::<u32>()`
|
||||
|
||||
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
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::<u32>()`
|
||||
|
||||
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
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut::<u32>()`
|
||||
|
||||
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
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::<u32>()`
|
||||
|
||||
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
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null::<u32>()`
|
||||
|
||||
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
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::<u32>()`
|
||||
|
||||
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
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null::<u32>()`
|
||||
|
||||
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 _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
|
||||
|
||||
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 _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()`
|
||||
|
||||
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 _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
|
||||
|
||||
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 _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()`
|
||||
|
||||
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 _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
|
||||
|
||||
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 _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()`
|
||||
|
||||
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 _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
|
||||
|
||||
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 _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()`
|
||||
|
||||
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 _
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
|
||||
|
||||
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 _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()`
|
||||
|
||||
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 _
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
|
||||
|
||||
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 _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()`
|
||||
|
||||
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 _
|
||||
| ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
|
||||
|
||||
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 _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()`
|
||||
|
||||
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 _
|
||||
| ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
|
||||
|
||||
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 _
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()`
|
||||
|
@ -213,3 +213,53 @@ mod issue7392 {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 {
|
||||
fn new() -> Self {
|
||||
// Shoud not warn!
|
||||
// Should not warn!
|
||||
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))]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
|
||||
|
||||
#![allow(unused)]
|
||||
#![allow(unused, clippy::duplicated_attributes)]
|
||||
#![warn(clippy::useless_attribute)]
|
||||
#![warn(unreachable_pub)]
|
||||
#![feature(rustc_private)]
|
||||
|
@ -1,6 +1,6 @@
|
||||
//@aux-build:proc_macro_derive.rs
|
||||
|
||||
#![allow(unused)]
|
||||
#![allow(unused, clippy::duplicated_attributes)]
|
||||
#![warn(clippy::useless_attribute)]
|
||||
#![warn(unreachable_pub)]
|
||||
#![feature(rustc_private)]
|
||||
|
@ -19,7 +19,12 @@ new_pr = true
|
||||
|
||||
[assign]
|
||||
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]
|
||||
"/.github" = ["@flip1995"]
|
||||
|
Loading…
Reference in New Issue
Block a user