mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-25 14:10:32 +00:00
Merge commit '0f7558148c22e53cd4608773b56cdfa50dcdeac3' into clippyup
This commit is contained in:
parent
821199c885
commit
e7fe1f9c14
76 changed files with 2207 additions and 575 deletions
|
@ -4383,6 +4383,7 @@ Released 2018-09-13
|
||||||
[`extend_from_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_from_slice
|
[`extend_from_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_from_slice
|
||||||
[`extend_with_drain`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_with_drain
|
[`extend_with_drain`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_with_drain
|
||||||
[`extra_unused_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_lifetimes
|
[`extra_unused_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_lifetimes
|
||||||
|
[`extra_unused_type_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_type_parameters
|
||||||
[`fallible_impl_from`]: https://rust-lang.github.io/rust-clippy/master/index.html#fallible_impl_from
|
[`fallible_impl_from`]: https://rust-lang.github.io/rust-clippy/master/index.html#fallible_impl_from
|
||||||
[`field_reassign_with_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#field_reassign_with_default
|
[`field_reassign_with_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#field_reassign_with_default
|
||||||
[`filetype_is_file`]: https://rust-lang.github.io/rust-clippy/master/index.html#filetype_is_file
|
[`filetype_is_file`]: https://rust-lang.github.io/rust-clippy/master/index.html#filetype_is_file
|
||||||
|
|
|
@ -42,6 +42,7 @@ filetime = "0.2"
|
||||||
rustc-workspace-hack = "1.0"
|
rustc-workspace-hack = "1.0"
|
||||||
|
|
||||||
# UI test dependencies
|
# UI test dependencies
|
||||||
|
clap = { version = "4.1.4", features = ["derive"] }
|
||||||
clippy_utils = { path = "clippy_utils" }
|
clippy_utils = { path = "clippy_utils" }
|
||||||
derive-new = "0.5"
|
derive-new = "0.5"
|
||||||
if_chain = "1.0"
|
if_chain = "1.0"
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
|
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
|
||||||
|
|
||||||
[There are over 550 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
|
[There are over 600 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
|
||||||
|
|
||||||
Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html).
|
Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html).
|
||||||
You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category.
|
You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category.
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
A collection of lints to catch common mistakes and improve your
|
A collection of lints to catch common mistakes and improve your
|
||||||
[Rust](https://github.com/rust-lang/rust) code.
|
[Rust](https://github.com/rust-lang/rust) code.
|
||||||
|
|
||||||
[There are over 550 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
|
[There are over 600 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
|
||||||
|
|
||||||
Lints are divided into categories, each with a default [lint
|
Lints are divided into categories, each with a default [lint
|
||||||
level](https://doc.rust-lang.org/rustc/lints/levels.html). You can choose how
|
level](https://doc.rust-lang.org/rustc/lints/levels.html). You can choose how
|
||||||
|
|
|
@ -43,6 +43,7 @@ Please use that command to update the file and do not edit it by hand.
|
||||||
| [allowed-scripts](#allowed-scripts) | `["Latin"]` |
|
| [allowed-scripts](#allowed-scripts) | `["Latin"]` |
|
||||||
| [enable-raw-pointer-heuristic-for-send](#enable-raw-pointer-heuristic-for-send) | `true` |
|
| [enable-raw-pointer-heuristic-for-send](#enable-raw-pointer-heuristic-for-send) | `true` |
|
||||||
| [max-suggested-slice-pattern-length](#max-suggested-slice-pattern-length) | `3` |
|
| [max-suggested-slice-pattern-length](#max-suggested-slice-pattern-length) | `3` |
|
||||||
|
| [await-holding-invalid-types](#await-holding-invalid-types) | `[]` |
|
||||||
| [max-include-file-size](#max-include-file-size) | `1000000` |
|
| [max-include-file-size](#max-include-file-size) | `1000000` |
|
||||||
| [allow-expect-in-tests](#allow-expect-in-tests) | `false` |
|
| [allow-expect-in-tests](#allow-expect-in-tests) | `false` |
|
||||||
| [allow-unwrap-in-tests](#allow-unwrap-in-tests) | `false` |
|
| [allow-unwrap-in-tests](#allow-unwrap-in-tests) | `false` |
|
||||||
|
@ -167,6 +168,17 @@ The minimum rust version that the project supports
|
||||||
* [manual_clamp](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp)
|
* [manual_clamp](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp)
|
||||||
* [manual_let_else](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else)
|
* [manual_let_else](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else)
|
||||||
* [unchecked_duration_subtraction](https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction)
|
* [unchecked_duration_subtraction](https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction)
|
||||||
|
* [collapsible_str_replace](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_str_replace)
|
||||||
|
* [seek_from_current](https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current)
|
||||||
|
* [seek_rewind](https://rust-lang.github.io/rust-clippy/master/index.html#seek_rewind)
|
||||||
|
* [unnecessary_lazy_evaluations](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations)
|
||||||
|
* [transmute_ptr_to_ref](https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref)
|
||||||
|
* [almost_complete_range](https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range)
|
||||||
|
* [needless_borrow](https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow)
|
||||||
|
* [derivable_impls](https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls)
|
||||||
|
* [manual_is_ascii_check](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check)
|
||||||
|
* [manual_rem_euclid](https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid)
|
||||||
|
* [manual_retain](https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain)
|
||||||
|
|
||||||
|
|
||||||
### cognitive-complexity-threshold
|
### cognitive-complexity-threshold
|
||||||
|
@ -279,7 +291,7 @@ The minimum size (in bytes) to consider a type for passing by reference instead
|
||||||
|
|
||||||
**Default Value:** `256` (`u64`)
|
**Default Value:** `256` (`u64`)
|
||||||
|
|
||||||
* [large_type_pass_by_move](https://rust-lang.github.io/rust-clippy/master/index.html#large_type_pass_by_move)
|
* [large_types_passed_by_value](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value)
|
||||||
|
|
||||||
|
|
||||||
### too-many-lines-threshold
|
### too-many-lines-threshold
|
||||||
|
@ -442,6 +454,14 @@ For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
|
||||||
* [index_refutable_slice](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice)
|
* [index_refutable_slice](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice)
|
||||||
|
|
||||||
|
|
||||||
|
### await-holding-invalid-types
|
||||||
|
|
||||||
|
|
||||||
|
**Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`)
|
||||||
|
|
||||||
|
* [await_holding_invalid_type](https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type)
|
||||||
|
|
||||||
|
|
||||||
### max-include-file-size
|
### max-include-file-size
|
||||||
The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes
|
The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes
|
||||||
|
|
||||||
|
@ -497,7 +517,7 @@ for the generic parameters for determining interior mutability
|
||||||
|
|
||||||
**Default Value:** `["bytes::Bytes"]` (`Vec<String>`)
|
**Default Value:** `["bytes::Bytes"]` (`Vec<String>`)
|
||||||
|
|
||||||
* [mutable_key](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key)
|
* [mutable_key_type](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type)
|
||||||
|
|
||||||
|
|
||||||
### allow-mixed-uninlined-format-args
|
### allow-mixed-uninlined-format-args
|
||||||
|
@ -509,7 +529,7 @@ Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)
|
||||||
|
|
||||||
|
|
||||||
### suppress-restriction-lint-in-const
|
### suppress-restriction-lint-in-const
|
||||||
In same
|
Whether to suppress a restriction lint in constant code. In same
|
||||||
cases the restructured operation might not be unavoidable, as the
|
cases the restructured operation might not be unavoidable, as the
|
||||||
suggested counterparts are unavailable in constant code. This
|
suggested counterparts are unavailable in constant code. This
|
||||||
configuration will cause restriction lints to trigger even
|
configuration will cause restriction lints to trigger even
|
||||||
|
|
|
@ -5,7 +5,7 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
aho-corasick = "0.7"
|
aho-corasick = "0.7"
|
||||||
clap = "3.2"
|
clap = "4.1.4"
|
||||||
indoc = "1.0"
|
indoc = "1.0"
|
||||||
itertools = "0.10.1"
|
itertools = "0.10.1"
|
||||||
opener = "0.5"
|
opener = "0.5"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// warn on lints, that are included in `rust-lang/rust`s bootstrap
|
// warn on lints, that are included in `rust-lang/rust`s bootstrap
|
||||||
#![warn(rust_2018_idioms, unused_lifetimes)]
|
#![warn(rust_2018_idioms, unused_lifetimes)]
|
||||||
|
|
||||||
use clap::{Arg, ArgAction, ArgMatches, Command, PossibleValue};
|
use clap::{Arg, ArgAction, ArgMatches, Command};
|
||||||
use clippy_dev::{bless, dogfood, fmt, lint, new_lint, serve, setup, update_lints};
|
use clippy_dev::{bless, dogfood, fmt, lint, new_lint, serve, setup, update_lints};
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
|
|
||||||
|
@ -11,22 +11,22 @@ fn main() {
|
||||||
|
|
||||||
match matches.subcommand() {
|
match matches.subcommand() {
|
||||||
Some(("bless", matches)) => {
|
Some(("bless", matches)) => {
|
||||||
bless::bless(matches.contains_id("ignore-timestamp"));
|
bless::bless(matches.get_flag("ignore-timestamp"));
|
||||||
},
|
},
|
||||||
Some(("dogfood", matches)) => {
|
Some(("dogfood", matches)) => {
|
||||||
dogfood::dogfood(
|
dogfood::dogfood(
|
||||||
matches.contains_id("fix"),
|
matches.get_flag("fix"),
|
||||||
matches.contains_id("allow-dirty"),
|
matches.get_flag("allow-dirty"),
|
||||||
matches.contains_id("allow-staged"),
|
matches.get_flag("allow-staged"),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
Some(("fmt", matches)) => {
|
Some(("fmt", matches)) => {
|
||||||
fmt::run(matches.contains_id("check"), matches.contains_id("verbose"));
|
fmt::run(matches.get_flag("check"), matches.get_flag("verbose"));
|
||||||
},
|
},
|
||||||
Some(("update_lints", matches)) => {
|
Some(("update_lints", matches)) => {
|
||||||
if matches.contains_id("print-only") {
|
if matches.get_flag("print-only") {
|
||||||
update_lints::print_lints();
|
update_lints::print_lints();
|
||||||
} else if matches.contains_id("check") {
|
} else if matches.get_flag("check") {
|
||||||
update_lints::update(update_lints::UpdateMode::Check);
|
update_lints::update(update_lints::UpdateMode::Check);
|
||||||
} else {
|
} else {
|
||||||
update_lints::update(update_lints::UpdateMode::Change);
|
update_lints::update(update_lints::UpdateMode::Change);
|
||||||
|
@ -38,7 +38,7 @@ fn main() {
|
||||||
matches.get_one::<String>("name"),
|
matches.get_one::<String>("name"),
|
||||||
matches.get_one::<String>("category").map(String::as_str),
|
matches.get_one::<String>("category").map(String::as_str),
|
||||||
matches.get_one::<String>("type").map(String::as_str),
|
matches.get_one::<String>("type").map(String::as_str),
|
||||||
matches.contains_id("msrv"),
|
matches.get_flag("msrv"),
|
||||||
) {
|
) {
|
||||||
Ok(_) => update_lints::update(update_lints::UpdateMode::Change),
|
Ok(_) => update_lints::update(update_lints::UpdateMode::Change),
|
||||||
Err(e) => eprintln!("Unable to create lint: {e}"),
|
Err(e) => eprintln!("Unable to create lint: {e}"),
|
||||||
|
@ -46,7 +46,7 @@ fn main() {
|
||||||
},
|
},
|
||||||
Some(("setup", sub_command)) => match sub_command.subcommand() {
|
Some(("setup", sub_command)) => match sub_command.subcommand() {
|
||||||
Some(("intellij", matches)) => {
|
Some(("intellij", matches)) => {
|
||||||
if matches.contains_id("remove") {
|
if matches.get_flag("remove") {
|
||||||
setup::intellij::remove_rustc_src();
|
setup::intellij::remove_rustc_src();
|
||||||
} else {
|
} else {
|
||||||
setup::intellij::setup_rustc_src(
|
setup::intellij::setup_rustc_src(
|
||||||
|
@ -57,17 +57,17 @@ fn main() {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(("git-hook", matches)) => {
|
Some(("git-hook", matches)) => {
|
||||||
if matches.contains_id("remove") {
|
if matches.get_flag("remove") {
|
||||||
setup::git_hook::remove_hook();
|
setup::git_hook::remove_hook();
|
||||||
} else {
|
} else {
|
||||||
setup::git_hook::install_hook(matches.contains_id("force-override"));
|
setup::git_hook::install_hook(matches.get_flag("force-override"));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(("vscode-tasks", matches)) => {
|
Some(("vscode-tasks", matches)) => {
|
||||||
if matches.contains_id("remove") {
|
if matches.get_flag("remove") {
|
||||||
setup::vscode::remove_tasks();
|
setup::vscode::remove_tasks();
|
||||||
} else {
|
} else {
|
||||||
setup::vscode::install_tasks(matches.contains_id("force-override"));
|
setup::vscode::install_tasks(matches.get_flag("force-override"));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
|
@ -91,7 +91,7 @@ fn main() {
|
||||||
Some(("rename_lint", matches)) => {
|
Some(("rename_lint", matches)) => {
|
||||||
let old_name = matches.get_one::<String>("old_name").unwrap();
|
let old_name = matches.get_one::<String>("old_name").unwrap();
|
||||||
let new_name = matches.get_one::<String>("new_name").unwrap_or(old_name);
|
let new_name = matches.get_one::<String>("new_name").unwrap_or(old_name);
|
||||||
let uplift = matches.contains_id("uplift");
|
let uplift = matches.get_flag("uplift");
|
||||||
update_lints::rename(old_name, new_name, uplift);
|
update_lints::rename(old_name, new_name, uplift);
|
||||||
},
|
},
|
||||||
Some(("deprecate", matches)) => {
|
Some(("deprecate", matches)) => {
|
||||||
|
@ -110,24 +110,37 @@ fn get_clap_config() -> ArgMatches {
|
||||||
Command::new("bless").about("bless the test output changes").arg(
|
Command::new("bless").about("bless the test output changes").arg(
|
||||||
Arg::new("ignore-timestamp")
|
Arg::new("ignore-timestamp")
|
||||||
.long("ignore-timestamp")
|
.long("ignore-timestamp")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
.help("Include files updated before clippy was built"),
|
.help("Include files updated before clippy was built"),
|
||||||
),
|
),
|
||||||
Command::new("dogfood").about("Runs the dogfood test").args([
|
Command::new("dogfood").about("Runs the dogfood test").args([
|
||||||
Arg::new("fix").long("fix").help("Apply the suggestions when possible"),
|
Arg::new("fix")
|
||||||
|
.long("fix")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("Apply the suggestions when possible"),
|
||||||
Arg::new("allow-dirty")
|
Arg::new("allow-dirty")
|
||||||
.long("allow-dirty")
|
.long("allow-dirty")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
.help("Fix code even if the working directory has changes")
|
.help("Fix code even if the working directory has changes")
|
||||||
.requires("fix"),
|
.requires("fix"),
|
||||||
Arg::new("allow-staged")
|
Arg::new("allow-staged")
|
||||||
.long("allow-staged")
|
.long("allow-staged")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
.help("Fix code even if the working directory has staged changes")
|
.help("Fix code even if the working directory has staged changes")
|
||||||
.requires("fix"),
|
.requires("fix"),
|
||||||
]),
|
]),
|
||||||
Command::new("fmt")
|
Command::new("fmt")
|
||||||
.about("Run rustfmt on all projects and tests")
|
.about("Run rustfmt on all projects and tests")
|
||||||
.args([
|
.args([
|
||||||
Arg::new("check").long("check").help("Use the rustfmt --check option"),
|
Arg::new("check")
|
||||||
Arg::new("verbose").short('v').long("verbose").help("Echo commands run"),
|
.long("check")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("Use the rustfmt --check option"),
|
||||||
|
Arg::new("verbose")
|
||||||
|
.short('v')
|
||||||
|
.long("verbose")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("Echo commands run"),
|
||||||
]),
|
]),
|
||||||
Command::new("update_lints")
|
Command::new("update_lints")
|
||||||
.about("Updates lint registration and information from the source code")
|
.about("Updates lint registration and information from the source code")
|
||||||
|
@ -140,13 +153,17 @@ fn get_clap_config() -> ArgMatches {
|
||||||
* all lints are registered in the lint store",
|
* all lints are registered in the lint store",
|
||||||
)
|
)
|
||||||
.args([
|
.args([
|
||||||
Arg::new("print-only").long("print-only").help(
|
Arg::new("print-only")
|
||||||
"Print a table of lints to STDOUT. \
|
.long("print-only")
|
||||||
This does not include deprecated and internal lints. \
|
.action(ArgAction::SetTrue)
|
||||||
(Does not modify any files)",
|
.help(
|
||||||
),
|
"Print a table of lints to STDOUT. \
|
||||||
|
This does not include deprecated and internal lints. \
|
||||||
|
(Does not modify any files)",
|
||||||
|
),
|
||||||
Arg::new("check")
|
Arg::new("check")
|
||||||
.long("check")
|
.long("check")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
.help("Checks that `cargo dev update_lints` has been run. Used on CI."),
|
.help("Checks that `cargo dev update_lints` has been run. Used on CI."),
|
||||||
]),
|
]),
|
||||||
Command::new("new_lint")
|
Command::new("new_lint")
|
||||||
|
@ -156,15 +173,13 @@ fn get_clap_config() -> ArgMatches {
|
||||||
.short('p')
|
.short('p')
|
||||||
.long("pass")
|
.long("pass")
|
||||||
.help("Specify whether the lint runs during the early or late pass")
|
.help("Specify whether the lint runs during the early or late pass")
|
||||||
.takes_value(true)
|
.value_parser(["early", "late"])
|
||||||
.value_parser([PossibleValue::new("early"), PossibleValue::new("late")])
|
|
||||||
.conflicts_with("type")
|
.conflicts_with("type")
|
||||||
.required_unless_present("type"),
|
.required_unless_present("type"),
|
||||||
Arg::new("name")
|
Arg::new("name")
|
||||||
.short('n')
|
.short('n')
|
||||||
.long("name")
|
.long("name")
|
||||||
.help("Name of the new lint in snake case, ex: fn_too_long")
|
.help("Name of the new lint in snake case, ex: fn_too_long")
|
||||||
.takes_value(true)
|
|
||||||
.required(true),
|
.required(true),
|
||||||
Arg::new("category")
|
Arg::new("category")
|
||||||
.short('c')
|
.short('c')
|
||||||
|
@ -172,25 +187,23 @@ fn get_clap_config() -> ArgMatches {
|
||||||
.help("What category the lint belongs to")
|
.help("What category the lint belongs to")
|
||||||
.default_value("nursery")
|
.default_value("nursery")
|
||||||
.value_parser([
|
.value_parser([
|
||||||
PossibleValue::new("style"),
|
"style",
|
||||||
PossibleValue::new("correctness"),
|
"correctness",
|
||||||
PossibleValue::new("suspicious"),
|
"suspicious",
|
||||||
PossibleValue::new("complexity"),
|
"complexity",
|
||||||
PossibleValue::new("perf"),
|
"perf",
|
||||||
PossibleValue::new("pedantic"),
|
"pedantic",
|
||||||
PossibleValue::new("restriction"),
|
"restriction",
|
||||||
PossibleValue::new("cargo"),
|
"cargo",
|
||||||
PossibleValue::new("nursery"),
|
"nursery",
|
||||||
PossibleValue::new("internal"),
|
"internal",
|
||||||
PossibleValue::new("internal_warn"),
|
"internal_warn",
|
||||||
])
|
]),
|
||||||
.takes_value(true),
|
Arg::new("type").long("type").help("What directory the lint belongs in"),
|
||||||
Arg::new("type")
|
Arg::new("msrv")
|
||||||
.long("type")
|
.long("msrv")
|
||||||
.help("What directory the lint belongs in")
|
.action(ArgAction::SetTrue)
|
||||||
.takes_value(true)
|
.help("Add MSRV config code to the lint"),
|
||||||
.required(false),
|
|
||||||
Arg::new("msrv").long("msrv").help("Add MSRV config code to the lint"),
|
|
||||||
]),
|
]),
|
||||||
Command::new("setup")
|
Command::new("setup")
|
||||||
.about("Support for setting up your personal development environment")
|
.about("Support for setting up your personal development environment")
|
||||||
|
@ -201,13 +214,12 @@ fn get_clap_config() -> ArgMatches {
|
||||||
.args([
|
.args([
|
||||||
Arg::new("remove")
|
Arg::new("remove")
|
||||||
.long("remove")
|
.long("remove")
|
||||||
.help("Remove the dependencies added with 'cargo dev setup intellij'")
|
.action(ArgAction::SetTrue)
|
||||||
.required(false),
|
.help("Remove the dependencies added with 'cargo dev setup intellij'"),
|
||||||
Arg::new("rustc-repo-path")
|
Arg::new("rustc-repo-path")
|
||||||
.long("repo-path")
|
.long("repo-path")
|
||||||
.short('r')
|
.short('r')
|
||||||
.help("The path to a rustc repo that will be used for setting the dependencies")
|
.help("The path to a rustc repo that will be used for setting the dependencies")
|
||||||
.takes_value(true)
|
|
||||||
.value_name("path")
|
.value_name("path")
|
||||||
.conflicts_with("remove")
|
.conflicts_with("remove")
|
||||||
.required(true),
|
.required(true),
|
||||||
|
@ -217,26 +229,26 @@ fn get_clap_config() -> ArgMatches {
|
||||||
.args([
|
.args([
|
||||||
Arg::new("remove")
|
Arg::new("remove")
|
||||||
.long("remove")
|
.long("remove")
|
||||||
.help("Remove the pre-commit hook added with 'cargo dev setup git-hook'")
|
.action(ArgAction::SetTrue)
|
||||||
.required(false),
|
.help("Remove the pre-commit hook added with 'cargo dev setup git-hook'"),
|
||||||
Arg::new("force-override")
|
Arg::new("force-override")
|
||||||
.long("force-override")
|
.long("force-override")
|
||||||
.short('f')
|
.short('f')
|
||||||
.help("Forces the override of an existing git pre-commit hook")
|
.action(ArgAction::SetTrue)
|
||||||
.required(false),
|
.help("Forces the override of an existing git pre-commit hook"),
|
||||||
]),
|
]),
|
||||||
Command::new("vscode-tasks")
|
Command::new("vscode-tasks")
|
||||||
.about("Add several tasks to vscode for formatting, validation and testing")
|
.about("Add several tasks to vscode for formatting, validation and testing")
|
||||||
.args([
|
.args([
|
||||||
Arg::new("remove")
|
Arg::new("remove")
|
||||||
.long("remove")
|
.long("remove")
|
||||||
.help("Remove the tasks added with 'cargo dev setup vscode-tasks'")
|
.action(ArgAction::SetTrue)
|
||||||
.required(false),
|
.help("Remove the tasks added with 'cargo dev setup vscode-tasks'"),
|
||||||
Arg::new("force-override")
|
Arg::new("force-override")
|
||||||
.long("force-override")
|
.long("force-override")
|
||||||
.short('f')
|
.short('f')
|
||||||
.help("Forces the override of existing vscode tasks")
|
.action(ArgAction::SetTrue)
|
||||||
.required(false),
|
.help("Forces the override of existing vscode tasks"),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
Command::new("remove")
|
Command::new("remove")
|
||||||
|
@ -295,6 +307,7 @@ fn get_clap_config() -> ArgMatches {
|
||||||
.help("The new name of the lint"),
|
.help("The new name of the lint"),
|
||||||
Arg::new("uplift")
|
Arg::new("uplift")
|
||||||
.long("uplift")
|
.long("uplift")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
.help("This lint will be uplifted into rustc"),
|
.help("This lint will be uplifted into rustc"),
|
||||||
]),
|
]),
|
||||||
Command::new("deprecate").about("Deprecates the given lint").args([
|
Command::new("deprecate").about("Deprecates the given lint").args([
|
||||||
|
@ -305,8 +318,6 @@ fn get_clap_config() -> ArgMatches {
|
||||||
Arg::new("reason")
|
Arg::new("reason")
|
||||||
.long("reason")
|
.long("reason")
|
||||||
.short('r')
|
.short('r')
|
||||||
.required(false)
|
|
||||||
.takes_value(true)
|
|
||||||
.help("The reason for deprecation"),
|
.help("The reason for deprecation"),
|
||||||
]),
|
]),
|
||||||
])
|
])
|
||||||
|
|
|
@ -9,7 +9,7 @@ keywords = ["clippy", "lint", "plugin"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cargo_metadata = "0.14"
|
cargo_metadata = "0.15.3"
|
||||||
clippy_utils = { path = "../clippy_utils" }
|
clippy_utils = { path = "../clippy_utils" }
|
||||||
declare_clippy_lint = { path = "../declare_clippy_lint" }
|
declare_clippy_lint = { path = "../declare_clippy_lint" }
|
||||||
if_chain = "1.0"
|
if_chain = "1.0"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::macros::{find_assert_eq_args, root_macro_call_first_node};
|
use clippy_utils::macros::{find_assert_eq_args, root_macro_call_first_node};
|
||||||
|
use clippy_utils::sugg::Sugg;
|
||||||
use clippy_utils::ty::{implements_trait, is_copy};
|
use clippy_utils::ty::{implements_trait, is_copy};
|
||||||
use rustc_ast::ast::LitKind;
|
use rustc_ast::ast::LitKind;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
|
@ -34,14 +35,16 @@ declare_clippy_lint! {
|
||||||
|
|
||||||
declare_lint_pass!(BoolAssertComparison => [BOOL_ASSERT_COMPARISON]);
|
declare_lint_pass!(BoolAssertComparison => [BOOL_ASSERT_COMPARISON]);
|
||||||
|
|
||||||
fn is_bool_lit(e: &Expr<'_>) -> bool {
|
fn extract_bool_lit(e: &Expr<'_>) -> Option<bool> {
|
||||||
matches!(
|
if let ExprKind::Lit(Lit {
|
||||||
e.kind,
|
node: LitKind::Bool(b), ..
|
||||||
ExprKind::Lit(Lit {
|
}) = e.kind
|
||||||
node: LitKind::Bool(_),
|
&& !e.span.from_expansion()
|
||||||
..
|
{
|
||||||
})
|
Some(b)
|
||||||
) && !e.span.from_expansion()
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||||
|
@ -69,24 +72,23 @@ impl<'tcx> LateLintPass<'tcx> for BoolAssertComparison {
|
||||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||||
let Some(macro_call) = root_macro_call_first_node(cx, expr) else { return };
|
let Some(macro_call) = root_macro_call_first_node(cx, expr) else { return };
|
||||||
let macro_name = cx.tcx.item_name(macro_call.def_id);
|
let macro_name = cx.tcx.item_name(macro_call.def_id);
|
||||||
if !matches!(
|
let eq_macro = match macro_name.as_str() {
|
||||||
macro_name.as_str(),
|
"assert_eq" | "debug_assert_eq" => true,
|
||||||
"assert_eq" | "debug_assert_eq" | "assert_ne" | "debug_assert_ne"
|
"assert_ne" | "debug_assert_ne" => false,
|
||||||
) {
|
_ => return,
|
||||||
return;
|
};
|
||||||
}
|
|
||||||
let Some ((a, b, _)) = find_assert_eq_args(cx, expr, macro_call.expn) else { return };
|
let Some ((a, b, _)) = find_assert_eq_args(cx, expr, macro_call.expn) else { return };
|
||||||
|
|
||||||
let a_span = a.span.source_callsite();
|
let a_span = a.span.source_callsite();
|
||||||
let b_span = b.span.source_callsite();
|
let b_span = b.span.source_callsite();
|
||||||
|
|
||||||
let (lit_span, non_lit_expr) = match (is_bool_lit(a), is_bool_lit(b)) {
|
let (lit_span, bool_value, non_lit_expr) = match (extract_bool_lit(a), extract_bool_lit(b)) {
|
||||||
// assert_eq!(true, b)
|
// assert_eq!(true/false, b)
|
||||||
// ^^^^^^
|
// ^^^^^^^^^^^^
|
||||||
(true, false) => (a_span.until(b_span), b),
|
(Some(bool_value), None) => (a_span.until(b_span), bool_value, b),
|
||||||
// assert_eq!(a, true)
|
// assert_eq!(a, true/false)
|
||||||
// ^^^^^^
|
// ^^^^^^^^^^^^
|
||||||
(false, true) => (b_span.with_lo(a_span.hi()), a),
|
(None, Some(bool_value)) => (b_span.with_lo(a_span.hi()), bool_value, a),
|
||||||
// If there are two boolean arguments, we definitely don't understand
|
// If there are two boolean arguments, we definitely don't understand
|
||||||
// what's going on, so better leave things as is...
|
// what's going on, so better leave things as is...
|
||||||
//
|
//
|
||||||
|
@ -121,9 +123,16 @@ impl<'tcx> LateLintPass<'tcx> for BoolAssertComparison {
|
||||||
// ^^^^^^^^^
|
// ^^^^^^^^^
|
||||||
let name_span = cx.sess().source_map().span_until_char(macro_call.span, '!');
|
let name_span = cx.sess().source_map().span_until_char(macro_call.span, '!');
|
||||||
|
|
||||||
|
let mut suggestions = vec![(name_span, non_eq_mac.to_string()), (lit_span, String::new())];
|
||||||
|
|
||||||
|
if bool_value ^ eq_macro {
|
||||||
|
let Some(sugg) = Sugg::hir_opt(cx, non_lit_expr) else { return };
|
||||||
|
suggestions.push((non_lit_expr.span, (!sugg).to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
diag.multipart_suggestion(
|
diag.multipart_suggestion(
|
||||||
format!("replace it with `{non_eq_mac}!(..)`"),
|
format!("replace it with `{non_eq_mac}!(..)`"),
|
||||||
vec![(name_span, non_eq_mac.to_string()), (lit_span, String::new())],
|
suggestions,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -156,6 +156,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
||||||
crate::exhaustive_items::EXHAUSTIVE_STRUCTS_INFO,
|
crate::exhaustive_items::EXHAUSTIVE_STRUCTS_INFO,
|
||||||
crate::exit::EXIT_INFO,
|
crate::exit::EXIT_INFO,
|
||||||
crate::explicit_write::EXPLICIT_WRITE_INFO,
|
crate::explicit_write::EXPLICIT_WRITE_INFO,
|
||||||
|
crate::extra_unused_type_parameters::EXTRA_UNUSED_TYPE_PARAMETERS_INFO,
|
||||||
crate::fallible_impl_from::FALLIBLE_IMPL_FROM_INFO,
|
crate::fallible_impl_from::FALLIBLE_IMPL_FROM_INFO,
|
||||||
crate::float_literal::EXCESSIVE_PRECISION_INFO,
|
crate::float_literal::EXCESSIVE_PRECISION_INFO,
|
||||||
crate::float_literal::LOSSY_FLOAT_LITERAL_INFO,
|
crate::float_literal::LOSSY_FLOAT_LITERAL_INFO,
|
||||||
|
|
|
@ -4,8 +4,8 @@ use rustc_hir::intravisit::FnKind;
|
||||||
use rustc_hir::{Body, FnDecl, Item, ItemKind, TraitFn, TraitItem, TraitItemKind, Ty};
|
use rustc_hir::{Body, FnDecl, Item, ItemKind, TraitFn, TraitItem, TraitItemKind, Ty};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||||
use rustc_span::Span;
|
|
||||||
use rustc_span::def_id::LocalDefId;
|
use rustc_span::def_id::LocalDefId;
|
||||||
|
use rustc_span::Span;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
|
|
178
clippy_lints/src/extra_unused_type_parameters.rs
Normal file
178
clippy_lints/src/extra_unused_type_parameters.rs
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
use clippy_utils::diagnostics::span_lint_and_help;
|
||||||
|
use clippy_utils::trait_ref_of_method;
|
||||||
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
use rustc_errors::MultiSpan;
|
||||||
|
use rustc_hir::intravisit::{walk_impl_item, walk_item, walk_param_bound, walk_ty, Visitor};
|
||||||
|
use rustc_hir::{
|
||||||
|
GenericParamKind, Generics, ImplItem, ImplItemKind, Item, ItemKind, PredicateOrigin, Ty, TyKind, WherePredicate,
|
||||||
|
};
|
||||||
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
|
use rustc_middle::hir::nested_filter;
|
||||||
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
|
use rustc_span::{def_id::DefId, Span};
|
||||||
|
|
||||||
|
declare_clippy_lint! {
|
||||||
|
/// ### What it does
|
||||||
|
/// Checks for type parameters in generics that are never used anywhere else.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// Functions cannot infer the value of unused type parameters; therefore, calling them
|
||||||
|
/// requires using a turbofish, which serves no purpose but to satisfy the compiler.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```rust
|
||||||
|
/// // unused type parameters
|
||||||
|
/// fn unused_ty<T>(x: u8) {
|
||||||
|
/// // ..
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
/// Use instead:
|
||||||
|
/// ```rust
|
||||||
|
/// fn no_unused_ty(x: u8) {
|
||||||
|
/// // ..
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[clippy::version = "1.69.0"]
|
||||||
|
pub EXTRA_UNUSED_TYPE_PARAMETERS,
|
||||||
|
complexity,
|
||||||
|
"unused type parameters in function definitions"
|
||||||
|
}
|
||||||
|
declare_lint_pass!(ExtraUnusedTypeParameters => [EXTRA_UNUSED_TYPE_PARAMETERS]);
|
||||||
|
|
||||||
|
/// A visitor struct that walks a given function and gathers generic type parameters, plus any
|
||||||
|
/// trait bounds those parameters have.
|
||||||
|
struct TypeWalker<'cx, 'tcx> {
|
||||||
|
cx: &'cx LateContext<'tcx>,
|
||||||
|
/// Collection of all the type parameters and their spans.
|
||||||
|
ty_params: FxHashMap<DefId, Span>,
|
||||||
|
/// Collection of any (inline) trait bounds corresponding to each type parameter.
|
||||||
|
bounds: FxHashMap<DefId, Span>,
|
||||||
|
/// The entire `Generics` object of the function, useful for querying purposes.
|
||||||
|
generics: &'tcx Generics<'tcx>,
|
||||||
|
/// The value of this will remain `true` if *every* parameter:
|
||||||
|
/// 1. Is a type parameter, and
|
||||||
|
/// 2. Goes unused in the function.
|
||||||
|
/// Otherwise, if any type parameters end up being used, or if any lifetime or const-generic
|
||||||
|
/// parameters are present, this will be set to `false`.
|
||||||
|
all_params_unused: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> {
|
||||||
|
fn new(cx: &'cx LateContext<'tcx>, generics: &'tcx Generics<'tcx>) -> Self {
|
||||||
|
let mut all_params_unused = true;
|
||||||
|
let ty_params = generics
|
||||||
|
.params
|
||||||
|
.iter()
|
||||||
|
.filter_map(|param| {
|
||||||
|
if let GenericParamKind::Type { .. } = param.kind {
|
||||||
|
Some((param.def_id.into(), param.span))
|
||||||
|
} else {
|
||||||
|
if !param.is_elided_lifetime() {
|
||||||
|
all_params_unused = false;
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
Self {
|
||||||
|
cx,
|
||||||
|
ty_params,
|
||||||
|
bounds: FxHashMap::default(),
|
||||||
|
generics,
|
||||||
|
all_params_unused,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_lint(&self) {
|
||||||
|
let (msg, help) = match self.ty_params.len() {
|
||||||
|
0 => return,
|
||||||
|
1 => (
|
||||||
|
"type parameter goes unused in function definition",
|
||||||
|
"consider removing the parameter",
|
||||||
|
),
|
||||||
|
_ => (
|
||||||
|
"type parameters go unused in function definition",
|
||||||
|
"consider removing the parameters",
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
let source_map = self.cx.tcx.sess.source_map();
|
||||||
|
let span = if self.all_params_unused {
|
||||||
|
self.generics.span.into() // Remove the entire list of generics
|
||||||
|
} else {
|
||||||
|
MultiSpan::from_spans(
|
||||||
|
self.ty_params
|
||||||
|
.iter()
|
||||||
|
.map(|(def_id, &span)| {
|
||||||
|
// Extend the span past any trait bounds, and include the comma at the end.
|
||||||
|
let span_to_extend = self.bounds.get(def_id).copied().map_or(span, Span::shrink_to_hi);
|
||||||
|
let comma_range = source_map.span_extend_to_next_char(span_to_extend, '>', false);
|
||||||
|
let comma_span = source_map.span_through_char(comma_range, ',');
|
||||||
|
span.with_hi(comma_span.hi())
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
span_lint_and_help(self.cx, EXTRA_UNUSED_TYPE_PARAMETERS, span, msg, None, help);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'cx, 'tcx> Visitor<'tcx> for TypeWalker<'cx, 'tcx> {
|
||||||
|
type NestedFilter = nested_filter::OnlyBodies;
|
||||||
|
|
||||||
|
fn visit_ty(&mut self, t: &'tcx Ty<'tcx>) {
|
||||||
|
if let Some((def_id, _)) = t.peel_refs().as_generic_param() {
|
||||||
|
if self.ty_params.remove(&def_id).is_some() {
|
||||||
|
self.all_params_unused = false;
|
||||||
|
}
|
||||||
|
} else if let TyKind::OpaqueDef(id, _, _) = t.kind {
|
||||||
|
// Explicitly walk OpaqueDef. Normally `walk_ty` would do the job, but it calls
|
||||||
|
// `visit_nested_item`, which checks that `Self::NestedFilter::INTER` is set. We're
|
||||||
|
// using `OnlyBodies`, so the check ends up failing and the type isn't fully walked.
|
||||||
|
let item = self.nested_visit_map().item(id);
|
||||||
|
walk_item(self, item);
|
||||||
|
} else {
|
||||||
|
walk_ty(self, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_where_predicate(&mut self, predicate: &'tcx WherePredicate<'tcx>) {
|
||||||
|
if let WherePredicate::BoundPredicate(predicate) = predicate {
|
||||||
|
// Collect spans for bounds that appear in the list of generics (not in a where-clause)
|
||||||
|
// for use in forming the help message
|
||||||
|
if let Some((def_id, _)) = predicate.bounded_ty.peel_refs().as_generic_param()
|
||||||
|
&& let PredicateOrigin::GenericParam = predicate.origin
|
||||||
|
{
|
||||||
|
self.bounds.insert(def_id, predicate.span);
|
||||||
|
}
|
||||||
|
// Only walk the right-hand side of where-bounds
|
||||||
|
for bound in predicate.bounds {
|
||||||
|
walk_param_bound(self, bound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nested_visit_map(&mut self) -> Self::Map {
|
||||||
|
self.cx.tcx.hir()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> LateLintPass<'tcx> for ExtraUnusedTypeParameters {
|
||||||
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||||
|
if let ItemKind::Fn(_, generics, _) = item.kind {
|
||||||
|
let mut walker = TypeWalker::new(cx, generics);
|
||||||
|
walk_item(&mut walker, item);
|
||||||
|
walker.emit_lint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'tcx>) {
|
||||||
|
// Only lint on inherent methods, not trait methods.
|
||||||
|
if let ImplItemKind::Fn(..) = item.kind && trait_ref_of_method(cx, item.owner_id.def_id).is_none() {
|
||||||
|
let mut walker = TypeWalker::new(cx, item.generics);
|
||||||
|
walk_impl_item(&mut walker, item);
|
||||||
|
walker.emit_lint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -125,7 +125,7 @@ declare_clippy_lint! {
|
||||||
/// nothing will be suggested, e.g. `println!("{0}={1}", var, 1+2)`.
|
/// nothing will be suggested, e.g. `println!("{0}={1}", var, 1+2)`.
|
||||||
#[clippy::version = "1.66.0"]
|
#[clippy::version = "1.66.0"]
|
||||||
pub UNINLINED_FORMAT_ARGS,
|
pub UNINLINED_FORMAT_ARGS,
|
||||||
style,
|
pedantic,
|
||||||
"using non-inlined variables in `format!` calls"
|
"using non-inlined variables in `format!` calls"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,13 +10,7 @@ use std::iter;
|
||||||
|
|
||||||
use super::MISNAMED_GETTERS;
|
use super::MISNAMED_GETTERS;
|
||||||
|
|
||||||
pub fn check_fn(
|
pub fn check_fn(cx: &LateContext<'_>, kind: FnKind<'_>, decl: &FnDecl<'_>, body: &Body<'_>, span: Span) {
|
||||||
cx: &LateContext<'_>,
|
|
||||||
kind: FnKind<'_>,
|
|
||||||
decl: &FnDecl<'_>,
|
|
||||||
body: &Body<'_>,
|
|
||||||
span: Span,
|
|
||||||
) {
|
|
||||||
let FnKind::Method(ref ident, sig) = kind else {
|
let FnKind::Method(ref ident, sig) = kind else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,7 +25,7 @@ pub(super) fn check_fn<'tcx>(
|
||||||
intravisit::FnKind::Closure => return,
|
intravisit::FnKind::Closure => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
check_raw_ptr(cx, unsafety, decl, body, def_id)
|
check_raw_ptr(cx, unsafety, decl, body, def_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
|
pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
|
||||||
|
|
|
@ -66,7 +66,9 @@ impl<'tcx> LateLintPass<'tcx> for IterNotReturningIterator {
|
||||||
|
|
||||||
fn check_sig(cx: &LateContext<'_>, name: &str, sig: &FnSig<'_>, fn_id: LocalDefId) {
|
fn check_sig(cx: &LateContext<'_>, name: &str, sig: &FnSig<'_>, fn_id: LocalDefId) {
|
||||||
if sig.decl.implicit_self.has_implicit_self() {
|
if sig.decl.implicit_self.has_implicit_self() {
|
||||||
let ret_ty = cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(fn_id).subst_identity().output());
|
let ret_ty = cx
|
||||||
|
.tcx
|
||||||
|
.erase_late_bound_regions(cx.tcx.fn_sig(fn_id).subst_identity().output());
|
||||||
let ret_ty = cx
|
let ret_ty = cx
|
||||||
.tcx
|
.tcx
|
||||||
.try_normalize_erasing_regions(cx.param_env, ret_ty)
|
.try_normalize_erasing_regions(cx.param_env, ret_ty)
|
||||||
|
|
|
@ -135,6 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
|
||||||
if item.ident.name == sym::len;
|
if item.ident.name == sym::len;
|
||||||
if let ImplItemKind::Fn(sig, _) = &item.kind;
|
if let ImplItemKind::Fn(sig, _) = &item.kind;
|
||||||
if sig.decl.implicit_self.has_implicit_self();
|
if sig.decl.implicit_self.has_implicit_self();
|
||||||
|
if sig.decl.inputs.len() == 1;
|
||||||
if cx.effective_visibilities.is_exported(item.owner_id.def_id);
|
if cx.effective_visibilities.is_exported(item.owner_id.def_id);
|
||||||
if matches!(sig.decl.output, FnRetTy::Return(_));
|
if matches!(sig.decl.output, FnRetTy::Return(_));
|
||||||
if let Some(imp) = get_parent_as_impl(cx.tcx, item.hir_id());
|
if let Some(imp) = get_parent_as_impl(cx.tcx, item.hir_id());
|
||||||
|
@ -196,7 +197,15 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items
|
||||||
fn is_named_self(cx: &LateContext<'_>, item: &TraitItemRef, name: Symbol) -> bool {
|
fn is_named_self(cx: &LateContext<'_>, item: &TraitItemRef, name: Symbol) -> bool {
|
||||||
item.ident.name == name
|
item.ident.name == name
|
||||||
&& if let AssocItemKind::Fn { has_self } = item.kind {
|
&& if let AssocItemKind::Fn { has_self } = item.kind {
|
||||||
has_self && { cx.tcx.fn_sig(item.id.owner_id).skip_binder().inputs().skip_binder().len() == 1 }
|
has_self && {
|
||||||
|
cx.tcx
|
||||||
|
.fn_sig(item.id.owner_id)
|
||||||
|
.skip_binder()
|
||||||
|
.inputs()
|
||||||
|
.skip_binder()
|
||||||
|
.len()
|
||||||
|
== 1
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -342,7 +351,11 @@ fn check_for_is_empty<'tcx>(
|
||||||
),
|
),
|
||||||
Some(is_empty)
|
Some(is_empty)
|
||||||
if !(is_empty.fn_has_self_parameter
|
if !(is_empty.fn_has_self_parameter
|
||||||
&& check_is_empty_sig(cx.tcx.fn_sig(is_empty.def_id).subst_identity().skip_binder(), self_kind, output)) =>
|
&& check_is_empty_sig(
|
||||||
|
cx.tcx.fn_sig(is_empty.def_id).subst_identity().skip_binder(),
|
||||||
|
self_kind,
|
||||||
|
output,
|
||||||
|
)) =>
|
||||||
{
|
{
|
||||||
(
|
(
|
||||||
format!(
|
format!(
|
||||||
|
|
|
@ -121,6 +121,7 @@ mod excessive_bools;
|
||||||
mod exhaustive_items;
|
mod exhaustive_items;
|
||||||
mod exit;
|
mod exit;
|
||||||
mod explicit_write;
|
mod explicit_write;
|
||||||
|
mod extra_unused_type_parameters;
|
||||||
mod fallible_impl_from;
|
mod fallible_impl_from;
|
||||||
mod float_literal;
|
mod float_literal;
|
||||||
mod floating_point_arithmetic;
|
mod floating_point_arithmetic;
|
||||||
|
@ -909,6 +910,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||||
store.register_late_pass(|_| Box::new(permissions_set_readonly_false::PermissionsSetReadonlyFalse));
|
store.register_late_pass(|_| Box::new(permissions_set_readonly_false::PermissionsSetReadonlyFalse));
|
||||||
store.register_late_pass(|_| Box::new(size_of_ref::SizeOfRef));
|
store.register_late_pass(|_| Box::new(size_of_ref::SizeOfRef));
|
||||||
store.register_late_pass(|_| Box::new(multiple_unsafe_ops_per_block::MultipleUnsafeOpsPerBlock));
|
store.register_late_pass(|_| Box::new(multiple_unsafe_ops_per_block::MultipleUnsafeOpsPerBlock));
|
||||||
|
store.register_late_pass(|_| Box::new(extra_unused_type_parameters::ExtraUnusedTypeParameters));
|
||||||
// add lints here, do not remove this comment, it's used in `new_lint`
|
// add lints here, do not remove this comment, it's used in `new_lint`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||||
use clippy_utils::trait_ref_of_method;
|
use clippy_utils::trait_ref_of_method;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter};
|
use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter};
|
||||||
use rustc_hir::intravisit::{
|
use rustc_hir::intravisit::{
|
||||||
walk_fn_decl, walk_generic_arg, walk_generic_param, walk_generics, walk_impl_item_ref, walk_item, walk_param_bound,
|
walk_fn_decl, walk_generic_param, walk_generics, walk_impl_item_ref, walk_item, walk_param_bound,
|
||||||
walk_poly_trait_ref, walk_trait_ref, walk_ty, Visitor,
|
walk_poly_trait_ref, walk_trait_ref, walk_ty, Visitor,
|
||||||
};
|
};
|
||||||
use rustc_hir::lang_items;
|
|
||||||
use rustc_hir::FnRetTy::Return;
|
use rustc_hir::FnRetTy::Return;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
|
lang_items, BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics,
|
||||||
ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, PolyTraitRef, PredicateOrigin, TraitFn,
|
Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef,
|
||||||
TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
|
PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_middle::hir::nested_filter as middle_nested_filter;
|
use rustc_middle::hir::nested_filter as middle_nested_filter;
|
||||||
|
use rustc_middle::lint::in_external_macro;
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::def_id::LocalDefId;
|
use rustc_span::def_id::LocalDefId;
|
||||||
use rustc_span::source_map::Span;
|
use rustc_span::source_map::Span;
|
||||||
|
@ -33,8 +34,6 @@ declare_clippy_lint! {
|
||||||
/// ### Known problems
|
/// ### Known problems
|
||||||
/// - We bail out if the function has a `where` clause where lifetimes
|
/// - We bail out if the function has a `where` clause where lifetimes
|
||||||
/// are mentioned due to potential false positives.
|
/// are mentioned due to potential false positives.
|
||||||
/// - Lifetime bounds such as `impl Foo + 'a` and `T: 'a` must be elided with the
|
|
||||||
/// placeholder notation `'_` because the fully elided notation leaves the type bound to `'static`.
|
|
||||||
///
|
///
|
||||||
/// ### Example
|
/// ### Example
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
@ -92,7 +91,7 @@ declare_lint_pass!(Lifetimes => [NEEDLESS_LIFETIMES, EXTRA_UNUSED_LIFETIMES]);
|
||||||
impl<'tcx> LateLintPass<'tcx> for Lifetimes {
|
impl<'tcx> LateLintPass<'tcx> for Lifetimes {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||||
if let ItemKind::Fn(ref sig, generics, id) = item.kind {
|
if let ItemKind::Fn(ref sig, generics, id) = item.kind {
|
||||||
check_fn_inner(cx, sig.decl, Some(id), None, generics, item.span, true);
|
check_fn_inner(cx, sig, Some(id), None, generics, item.span, true);
|
||||||
} else if let ItemKind::Impl(impl_) = item.kind {
|
} else if let ItemKind::Impl(impl_) = item.kind {
|
||||||
if !item.span.from_expansion() {
|
if !item.span.from_expansion() {
|
||||||
report_extra_impl_lifetimes(cx, impl_);
|
report_extra_impl_lifetimes(cx, impl_);
|
||||||
|
@ -105,7 +104,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
|
||||||
let report_extra_lifetimes = trait_ref_of_method(cx, item.owner_id.def_id).is_none();
|
let report_extra_lifetimes = trait_ref_of_method(cx, item.owner_id.def_id).is_none();
|
||||||
check_fn_inner(
|
check_fn_inner(
|
||||||
cx,
|
cx,
|
||||||
sig.decl,
|
sig,
|
||||||
Some(id),
|
Some(id),
|
||||||
None,
|
None,
|
||||||
item.generics,
|
item.generics,
|
||||||
|
@ -121,29 +120,21 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
|
||||||
TraitFn::Required(sig) => (None, Some(sig)),
|
TraitFn::Required(sig) => (None, Some(sig)),
|
||||||
TraitFn::Provided(id) => (Some(id), None),
|
TraitFn::Provided(id) => (Some(id), None),
|
||||||
};
|
};
|
||||||
check_fn_inner(cx, sig.decl, body, trait_sig, item.generics, item.span, true);
|
check_fn_inner(cx, sig, body, trait_sig, item.generics, item.span, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The lifetime of a &-reference.
|
|
||||||
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
|
|
||||||
enum RefLt {
|
|
||||||
Unnamed,
|
|
||||||
Static,
|
|
||||||
Named(LocalDefId),
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_fn_inner<'tcx>(
|
fn check_fn_inner<'tcx>(
|
||||||
cx: &LateContext<'tcx>,
|
cx: &LateContext<'tcx>,
|
||||||
decl: &'tcx FnDecl<'_>,
|
sig: &'tcx FnSig<'_>,
|
||||||
body: Option<BodyId>,
|
body: Option<BodyId>,
|
||||||
trait_sig: Option<&[Ident]>,
|
trait_sig: Option<&[Ident]>,
|
||||||
generics: &'tcx Generics<'_>,
|
generics: &'tcx Generics<'_>,
|
||||||
span: Span,
|
span: Span,
|
||||||
report_extra_lifetimes: bool,
|
report_extra_lifetimes: bool,
|
||||||
) {
|
) {
|
||||||
if span.from_expansion() || has_where_lifetimes(cx, generics) {
|
if in_external_macro(cx.sess(), span) || has_where_lifetimes(cx, generics) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +153,7 @@ fn check_fn_inner<'tcx>(
|
||||||
for bound in pred.bounds {
|
for bound in pred.bounds {
|
||||||
let mut visitor = RefVisitor::new(cx);
|
let mut visitor = RefVisitor::new(cx);
|
||||||
walk_param_bound(&mut visitor, bound);
|
walk_param_bound(&mut visitor, bound);
|
||||||
if visitor.lts.iter().any(|lt| matches!(lt, RefLt::Named(_))) {
|
if visitor.lts.iter().any(|lt| matches!(lt.res, LifetimeName::Param(_))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let GenericBound::Trait(ref trait_ref, _) = *bound {
|
if let GenericBound::Trait(ref trait_ref, _) = *bound {
|
||||||
|
@ -189,12 +180,12 @@ fn check_fn_inner<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(elidable_lts) = could_use_elision(cx, decl, body, trait_sig, generics.params) {
|
if let Some((elidable_lts, usages)) = could_use_elision(cx, sig.decl, body, trait_sig, generics.params) {
|
||||||
let lts = elidable_lts
|
let lts = elidable_lts
|
||||||
.iter()
|
.iter()
|
||||||
// In principle, the result of the call to `Node::ident` could be `unwrap`ped, as `DefId` should refer to a
|
// In principle, the result of the call to `Node::ident` could be `unwrap`ped, as `DefId` should refer to a
|
||||||
// `Node::GenericParam`.
|
// `Node::GenericParam`.
|
||||||
.filter_map(|&(def_id, _)| cx.tcx.hir().get_by_def_id(def_id).ident())
|
.filter_map(|&def_id| cx.tcx.hir().get_by_def_id(def_id).ident())
|
||||||
.map(|ident| ident.to_string())
|
.map(|ident| ident.to_string())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
|
@ -202,21 +193,99 @@ fn check_fn_inner<'tcx>(
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
cx,
|
cx,
|
||||||
NEEDLESS_LIFETIMES,
|
NEEDLESS_LIFETIMES,
|
||||||
span.with_hi(decl.output.span().hi()),
|
span.with_hi(sig.decl.output.span().hi()),
|
||||||
&format!("the following explicit lifetimes could be elided: {lts}"),
|
&format!("the following explicit lifetimes could be elided: {lts}"),
|
||||||
|diag| {
|
|diag| {
|
||||||
if let Some(span) = elidable_lts.iter().find_map(|&(_, span)| span) {
|
if sig.header.is_async() {
|
||||||
diag.span_help(span, "replace with `'_` in generic arguments such as here");
|
// async functions have usages whose spans point at the lifetime declaration which messes up
|
||||||
|
// suggestions
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(suggestions) = elision_suggestions(cx, generics, &elidable_lts, &usages) {
|
||||||
|
diag.multipart_suggestion("elide the lifetimes", suggestions, Applicability::MachineApplicable);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if report_extra_lifetimes {
|
if report_extra_lifetimes {
|
||||||
self::report_extra_lifetimes(cx, decl, generics);
|
self::report_extra_lifetimes(cx, sig.decl, generics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn elision_suggestions(
|
||||||
|
cx: &LateContext<'_>,
|
||||||
|
generics: &Generics<'_>,
|
||||||
|
elidable_lts: &[LocalDefId],
|
||||||
|
usages: &[Lifetime],
|
||||||
|
) -> Option<Vec<(Span, String)>> {
|
||||||
|
let explicit_params = generics
|
||||||
|
.params
|
||||||
|
.iter()
|
||||||
|
.filter(|param| !param.is_elided_lifetime() && !param.is_impl_trait())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let mut suggestions = if elidable_lts.len() == explicit_params.len() {
|
||||||
|
// if all the params are elided remove the whole generic block
|
||||||
|
//
|
||||||
|
// fn x<'a>() {}
|
||||||
|
// ^^^^
|
||||||
|
vec![(generics.span, String::new())]
|
||||||
|
} else {
|
||||||
|
elidable_lts
|
||||||
|
.iter()
|
||||||
|
.map(|&id| {
|
||||||
|
let pos = explicit_params.iter().position(|param| param.def_id == id)?;
|
||||||
|
let param = explicit_params.get(pos)?;
|
||||||
|
|
||||||
|
let span = if let Some(next) = explicit_params.get(pos + 1) {
|
||||||
|
// fn x<'prev, 'a, 'next>() {}
|
||||||
|
// ^^^^
|
||||||
|
param.span.until(next.span)
|
||||||
|
} else {
|
||||||
|
// `pos` should be at least 1 here, because the param in position 0 would either have a `next`
|
||||||
|
// param or would have taken the `elidable_lts.len() == explicit_params.len()` branch.
|
||||||
|
let prev = explicit_params.get(pos - 1)?;
|
||||||
|
|
||||||
|
// fn x<'prev, 'a>() {}
|
||||||
|
// ^^^^
|
||||||
|
param.span.with_lo(prev.span.hi())
|
||||||
|
};
|
||||||
|
|
||||||
|
Some((span, String::new()))
|
||||||
|
})
|
||||||
|
.collect::<Option<Vec<_>>>()?
|
||||||
|
};
|
||||||
|
|
||||||
|
suggestions.extend(
|
||||||
|
usages
|
||||||
|
.iter()
|
||||||
|
.filter(|usage| named_lifetime(usage).map_or(false, |id| elidable_lts.contains(&id)))
|
||||||
|
.map(|usage| {
|
||||||
|
match cx.tcx.hir().get_parent(usage.hir_id) {
|
||||||
|
Node::Ty(Ty {
|
||||||
|
kind: TyKind::Ref(..), ..
|
||||||
|
}) => {
|
||||||
|
// expand `&'a T` to `&'a T`
|
||||||
|
// ^^ ^^^
|
||||||
|
let span = cx
|
||||||
|
.sess()
|
||||||
|
.source_map()
|
||||||
|
.span_extend_while(usage.ident.span, |ch| ch.is_ascii_whitespace())
|
||||||
|
.unwrap_or(usage.ident.span);
|
||||||
|
|
||||||
|
(span, String::new())
|
||||||
|
},
|
||||||
|
// `T<'a>` and `impl Foo + 'a` should be replaced by `'_`
|
||||||
|
_ => (usage.ident.span, String::from("'_")),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
Some(suggestions)
|
||||||
|
}
|
||||||
|
|
||||||
// elision doesn't work for explicit self types, see rust-lang/rust#69064
|
// elision doesn't work for explicit self types, see rust-lang/rust#69064
|
||||||
fn explicit_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident: Option<Ident>) -> bool {
|
fn explicit_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident: Option<Ident>) -> bool {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
|
@ -236,13 +305,20 @@ fn explicit_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn named_lifetime(lt: &Lifetime) -> Option<LocalDefId> {
|
||||||
|
match lt.res {
|
||||||
|
LifetimeName::Param(id) if !lt.is_anonymous() => Some(id),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn could_use_elision<'tcx>(
|
fn could_use_elision<'tcx>(
|
||||||
cx: &LateContext<'tcx>,
|
cx: &LateContext<'tcx>,
|
||||||
func: &'tcx FnDecl<'_>,
|
func: &'tcx FnDecl<'_>,
|
||||||
body: Option<BodyId>,
|
body: Option<BodyId>,
|
||||||
trait_sig: Option<&[Ident]>,
|
trait_sig: Option<&[Ident]>,
|
||||||
named_generics: &'tcx [GenericParam<'_>],
|
named_generics: &'tcx [GenericParam<'_>],
|
||||||
) -> Option<Vec<(LocalDefId, Option<Span>)>> {
|
) -> Option<(Vec<LocalDefId>, Vec<Lifetime>)> {
|
||||||
// There are two scenarios where elision works:
|
// There are two scenarios where elision works:
|
||||||
// * no output references, all input references have different LT
|
// * no output references, all input references have different LT
|
||||||
// * output references, exactly one input reference with same LT
|
// * output references, exactly one input reference with same LT
|
||||||
|
@ -300,32 +376,24 @@ fn could_use_elision<'tcx>(
|
||||||
|
|
||||||
// check for lifetimes from higher scopes
|
// check for lifetimes from higher scopes
|
||||||
for lt in input_lts.iter().chain(output_lts.iter()) {
|
for lt in input_lts.iter().chain(output_lts.iter()) {
|
||||||
if !allowed_lts.contains(lt) {
|
if let Some(id) = named_lifetime(lt)
|
||||||
|
&& !allowed_lts.contains(&id)
|
||||||
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for higher-ranked trait bounds
|
// check for higher-ranked trait bounds
|
||||||
if !input_visitor.nested_elision_site_lts.is_empty() || !output_visitor.nested_elision_site_lts.is_empty() {
|
if !input_visitor.nested_elision_site_lts.is_empty() || !output_visitor.nested_elision_site_lts.is_empty() {
|
||||||
let allowed_lts: FxHashSet<_> = allowed_lts
|
let allowed_lts: FxHashSet<_> = allowed_lts.iter().map(|id| cx.tcx.item_name(id.to_def_id())).collect();
|
||||||
.iter()
|
|
||||||
.filter_map(|lt| match lt {
|
|
||||||
RefLt::Named(def_id) => Some(cx.tcx.item_name(def_id.to_def_id())),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
for lt in input_visitor.nested_elision_site_lts {
|
for lt in input_visitor.nested_elision_site_lts {
|
||||||
if let RefLt::Named(def_id) = lt {
|
if allowed_lts.contains(<.ident.name) {
|
||||||
if allowed_lts.contains(&cx.tcx.item_name(def_id.to_def_id())) {
|
return None;
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for lt in output_visitor.nested_elision_site_lts {
|
for lt in output_visitor.nested_elision_site_lts {
|
||||||
if let RefLt::Named(def_id) = lt {
|
if allowed_lts.contains(<.ident.name) {
|
||||||
if allowed_lts.contains(&cx.tcx.item_name(def_id.to_def_id())) {
|
return None;
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -337,15 +405,10 @@ fn could_use_elision<'tcx>(
|
||||||
let elidable_lts = named_lifetime_occurrences(&input_lts)
|
let elidable_lts = named_lifetime_occurrences(&input_lts)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|(def_id, occurrences)| {
|
.filter_map(|(def_id, occurrences)| {
|
||||||
if occurrences == 1 && (input_lts.len() == 1 || !output_lts.contains(&RefLt::Named(def_id))) {
|
if occurrences == 1
|
||||||
Some((
|
&& (input_lts.len() == 1 || !output_lts.iter().any(|lt| named_lifetime(lt) == Some(def_id)))
|
||||||
def_id,
|
{
|
||||||
input_visitor
|
Some(def_id)
|
||||||
.lifetime_generic_arg_spans
|
|
||||||
.get(&def_id)
|
|
||||||
.or_else(|| output_visitor.lifetime_generic_arg_spans.get(&def_id))
|
|
||||||
.copied(),
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -353,31 +416,34 @@ fn could_use_elision<'tcx>(
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if elidable_lts.is_empty() {
|
if elidable_lts.is_empty() {
|
||||||
None
|
return None;
|
||||||
} else {
|
|
||||||
Some(elidable_lts)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let usages = itertools::chain(input_lts, output_lts).collect();
|
||||||
|
|
||||||
|
Some((elidable_lts, usages))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxHashSet<RefLt> {
|
fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxHashSet<LocalDefId> {
|
||||||
let mut allowed_lts = FxHashSet::default();
|
named_generics
|
||||||
for par in named_generics.iter() {
|
.iter()
|
||||||
if let GenericParamKind::Lifetime { .. } = par.kind {
|
.filter_map(|par| {
|
||||||
allowed_lts.insert(RefLt::Named(par.def_id));
|
if let GenericParamKind::Lifetime { .. } = par.kind {
|
||||||
}
|
Some(par.def_id)
|
||||||
}
|
} else {
|
||||||
allowed_lts.insert(RefLt::Unnamed);
|
None
|
||||||
allowed_lts.insert(RefLt::Static);
|
}
|
||||||
allowed_lts
|
})
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Number of times each named lifetime occurs in the given slice. Returns a vector to preserve
|
/// Number of times each named lifetime occurs in the given slice. Returns a vector to preserve
|
||||||
/// relative order.
|
/// relative order.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn named_lifetime_occurrences(lts: &[RefLt]) -> Vec<(LocalDefId, usize)> {
|
fn named_lifetime_occurrences(lts: &[Lifetime]) -> Vec<(LocalDefId, usize)> {
|
||||||
let mut occurrences = Vec::new();
|
let mut occurrences = Vec::new();
|
||||||
for lt in lts {
|
for lt in lts {
|
||||||
if let &RefLt::Named(curr_def_id) = lt {
|
if let Some(curr_def_id) = named_lifetime(lt) {
|
||||||
if let Some(pair) = occurrences
|
if let Some(pair) = occurrences
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|(prev_def_id, _)| *prev_def_id == curr_def_id)
|
.find(|(prev_def_id, _)| *prev_def_id == curr_def_id)
|
||||||
|
@ -391,12 +457,10 @@ fn named_lifetime_occurrences(lts: &[RefLt]) -> Vec<(LocalDefId, usize)> {
|
||||||
occurrences
|
occurrences
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A visitor usable for `rustc_front::visit::walk_ty()`.
|
|
||||||
struct RefVisitor<'a, 'tcx> {
|
struct RefVisitor<'a, 'tcx> {
|
||||||
cx: &'a LateContext<'tcx>,
|
cx: &'a LateContext<'tcx>,
|
||||||
lts: Vec<RefLt>,
|
lts: Vec<Lifetime>,
|
||||||
lifetime_generic_arg_spans: FxHashMap<LocalDefId, Span>,
|
nested_elision_site_lts: Vec<Lifetime>,
|
||||||
nested_elision_site_lts: Vec<RefLt>,
|
|
||||||
unelided_trait_object_lifetime: bool,
|
unelided_trait_object_lifetime: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,32 +469,16 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> {
|
||||||
Self {
|
Self {
|
||||||
cx,
|
cx,
|
||||||
lts: Vec::new(),
|
lts: Vec::new(),
|
||||||
lifetime_generic_arg_spans: FxHashMap::default(),
|
|
||||||
nested_elision_site_lts: Vec::new(),
|
nested_elision_site_lts: Vec::new(),
|
||||||
unelided_trait_object_lifetime: false,
|
unelided_trait_object_lifetime: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn record(&mut self, lifetime: &Option<Lifetime>) {
|
fn all_lts(&self) -> Vec<Lifetime> {
|
||||||
if let Some(ref lt) = *lifetime {
|
|
||||||
if lt.is_static() {
|
|
||||||
self.lts.push(RefLt::Static);
|
|
||||||
} else if lt.is_anonymous() {
|
|
||||||
// Fresh lifetimes generated should be ignored.
|
|
||||||
self.lts.push(RefLt::Unnamed);
|
|
||||||
} else if let LifetimeName::Param(def_id) = lt.res {
|
|
||||||
self.lts.push(RefLt::Named(def_id));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.lts.push(RefLt::Unnamed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn all_lts(&self) -> Vec<RefLt> {
|
|
||||||
self.lts
|
self.lts
|
||||||
.iter()
|
.iter()
|
||||||
.chain(self.nested_elision_site_lts.iter())
|
.chain(self.nested_elision_site_lts.iter())
|
||||||
.cloned()
|
.copied()
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,7 +490,7 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> {
|
||||||
impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
|
||||||
// for lifetimes as parameters of generics
|
// for lifetimes as parameters of generics
|
||||||
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
|
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
|
||||||
self.record(&Some(*lifetime));
|
self.lts.push(*lifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_poly_trait_ref(&mut self, poly_tref: &'tcx PolyTraitRef<'tcx>) {
|
fn visit_poly_trait_ref(&mut self, poly_tref: &'tcx PolyTraitRef<'tcx>) {
|
||||||
|
@ -467,11 +515,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
|
||||||
walk_item(self, item);
|
walk_item(self, item);
|
||||||
self.lts.truncate(len);
|
self.lts.truncate(len);
|
||||||
self.lts.extend(bounds.iter().filter_map(|bound| match bound {
|
self.lts.extend(bounds.iter().filter_map(|bound| match bound {
|
||||||
GenericArg::Lifetime(l) => Some(if let LifetimeName::Param(def_id) = l.res {
|
GenericArg::Lifetime(&l) => Some(l),
|
||||||
RefLt::Named(def_id)
|
|
||||||
} else {
|
|
||||||
RefLt::Unnamed
|
|
||||||
}),
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
@ -491,13 +535,6 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
|
||||||
_ => walk_ty(self, ty),
|
_ => walk_ty(self, ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_generic_arg(&mut self, generic_arg: &'tcx GenericArg<'tcx>) {
|
|
||||||
if let GenericArg::Lifetime(l) = generic_arg && let LifetimeName::Param(def_id) = l.res {
|
|
||||||
self.lifetime_generic_arg_spans.entry(def_id).or_insert(l.ident.span);
|
|
||||||
}
|
|
||||||
walk_generic_arg(self, generic_arg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Are any lifetimes mentioned in the `where` clause? If so, we don't try to
|
/// Are any lifetimes mentioned in the `where` clause? If so, we don't try to
|
||||||
|
@ -521,8 +558,12 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_
|
||||||
walk_param_bound(&mut visitor, bound);
|
walk_param_bound(&mut visitor, bound);
|
||||||
}
|
}
|
||||||
// and check that all lifetimes are allowed
|
// and check that all lifetimes are allowed
|
||||||
if visitor.all_lts().iter().any(|it| !allowed_lts.contains(it)) {
|
for lt in visitor.all_lts() {
|
||||||
return true;
|
if let Some(id) = named_lifetime(<)
|
||||||
|
&& !allowed_lts.contains(&id)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
WherePredicate::EqPredicate(ref pred) => {
|
WherePredicate::EqPredicate(ref pred) => {
|
||||||
|
|
|
@ -61,7 +61,8 @@ declare_clippy_lint! {
|
||||||
///
|
///
|
||||||
/// ### Why is this bad?
|
/// ### Why is this bad?
|
||||||
/// Just iterating the collection itself makes the intent
|
/// Just iterating the collection itself makes the intent
|
||||||
/// more clear and is probably faster.
|
/// more clear and is probably faster because it eliminates
|
||||||
|
/// the bounds check that is done when indexing.
|
||||||
///
|
///
|
||||||
/// ### Example
|
/// ### Example
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
|
|
@ -149,7 +149,7 @@ pub(super) fn check<'tcx>(
|
||||||
|diag| {
|
|diag| {
|
||||||
multispan_sugg(
|
multispan_sugg(
|
||||||
diag,
|
diag,
|
||||||
"consider using an iterator",
|
"consider using an iterator and enumerate()",
|
||||||
vec![
|
vec![
|
||||||
(pat.span, format!("({}, <item>)", ident.name)),
|
(pat.span, format!("({}, <item>)", ident.name)),
|
||||||
(
|
(
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use crate::rustc_lint::LintContext;
|
use crate::rustc_lint::LintContext;
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::macros::{root_macro_call, FormatArgsExpn};
|
use clippy_utils::macros::root_macro_call;
|
||||||
use clippy_utils::source::snippet_with_applicability;
|
|
||||||
use clippy_utils::{is_else_clause, peel_blocks_with_stmt, span_extract_comment, sugg};
|
use clippy_utils::{is_else_clause, peel_blocks_with_stmt, span_extract_comment, sugg};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{Expr, ExprKind, UnOp};
|
use rustc_hir::{Expr, ExprKind, UnOp};
|
||||||
|
@ -38,57 +37,57 @@ declare_lint_pass!(ManualAssert => [MANUAL_ASSERT]);
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for ManualAssert {
|
impl<'tcx> LateLintPass<'tcx> for ManualAssert {
|
||||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
|
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
|
||||||
if_chain! {
|
if let ExprKind::If(cond, then, None) = expr.kind
|
||||||
if let ExprKind::If(cond, then, None) = expr.kind;
|
&& !matches!(cond.kind, ExprKind::Let(_))
|
||||||
if !matches!(cond.kind, ExprKind::Let(_));
|
&& !expr.span.from_expansion()
|
||||||
if !expr.span.from_expansion();
|
&& let then = peel_blocks_with_stmt(then)
|
||||||
let then = peel_blocks_with_stmt(then);
|
&& let Some(macro_call) = root_macro_call(then.span)
|
||||||
if let Some(macro_call) = root_macro_call(then.span);
|
&& cx.tcx.item_name(macro_call.def_id) == sym::panic
|
||||||
if cx.tcx.item_name(macro_call.def_id) == sym::panic;
|
&& !cx.tcx.sess.source_map().is_multiline(cond.span)
|
||||||
if !cx.tcx.sess.source_map().is_multiline(cond.span);
|
&& let Ok(panic_snippet) = cx.sess().source_map().span_to_snippet(macro_call.span)
|
||||||
if let Some(format_args) = FormatArgsExpn::find_nested(cx, then, macro_call.expn);
|
&& let Some(panic_snippet) = panic_snippet.strip_suffix(')')
|
||||||
|
&& let Some((_, format_args_snip)) = panic_snippet.split_once('(')
|
||||||
// Don't change `else if foo { panic!(..) }` to `else { assert!(foo, ..) }` as it just
|
// Don't change `else if foo { panic!(..) }` to `else { assert!(foo, ..) }` as it just
|
||||||
// shuffles the condition around.
|
// shuffles the condition around.
|
||||||
// Should this have a config value?
|
// Should this have a config value?
|
||||||
if !is_else_clause(cx.tcx, expr);
|
&& !is_else_clause(cx.tcx, expr)
|
||||||
then {
|
{
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
let format_args_snip = snippet_with_applicability(cx, format_args.inputs_span(), "..", &mut applicability);
|
let cond = cond.peel_drop_temps();
|
||||||
let cond = cond.peel_drop_temps();
|
let mut comments = span_extract_comment(cx.sess().source_map(), expr.span);
|
||||||
let mut comments = span_extract_comment(cx.sess().source_map(), expr.span);
|
if !comments.is_empty() {
|
||||||
if !comments.is_empty() {
|
comments += "\n";
|
||||||
comments += "\n";
|
|
||||||
}
|
|
||||||
let (cond, not) = match cond.kind {
|
|
||||||
ExprKind::Unary(UnOp::Not, e) => (e, ""),
|
|
||||||
_ => (cond, "!"),
|
|
||||||
};
|
|
||||||
let cond_sugg = sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par();
|
|
||||||
let sugg = format!("assert!({not}{cond_sugg}, {format_args_snip});");
|
|
||||||
// we show to the user the suggestion without the comments, but when applicating the fix, include the comments in the block
|
|
||||||
span_lint_and_then(
|
|
||||||
cx,
|
|
||||||
MANUAL_ASSERT,
|
|
||||||
expr.span,
|
|
||||||
"only a `panic!` in `if`-then statement",
|
|
||||||
|diag| {
|
|
||||||
// comments can be noisy, do not show them to the user
|
|
||||||
if !comments.is_empty() {
|
|
||||||
diag.tool_only_span_suggestion(
|
|
||||||
expr.span.shrink_to_lo(),
|
|
||||||
"add comments back",
|
|
||||||
comments,
|
|
||||||
applicability);
|
|
||||||
}
|
|
||||||
diag.span_suggestion(
|
|
||||||
expr.span,
|
|
||||||
"try instead",
|
|
||||||
sugg,
|
|
||||||
applicability);
|
|
||||||
}
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
let (cond, not) = match cond.kind {
|
||||||
|
ExprKind::Unary(UnOp::Not, e) => (e, ""),
|
||||||
|
_ => (cond, "!"),
|
||||||
|
};
|
||||||
|
let cond_sugg = sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par();
|
||||||
|
let sugg = format!("assert!({not}{cond_sugg}, {format_args_snip});");
|
||||||
|
// we show to the user the suggestion without the comments, but when applicating the fix, include the comments in the block
|
||||||
|
span_lint_and_then(
|
||||||
|
cx,
|
||||||
|
MANUAL_ASSERT,
|
||||||
|
expr.span,
|
||||||
|
"only a `panic!` in `if`-then statement",
|
||||||
|
|diag| {
|
||||||
|
// comments can be noisy, do not show them to the user
|
||||||
|
if !comments.is_empty() {
|
||||||
|
diag.tool_only_span_suggestion(
|
||||||
|
expr.span.shrink_to_lo(),
|
||||||
|
"add comments back",
|
||||||
|
comments,
|
||||||
|
applicability
|
||||||
|
);
|
||||||
|
}
|
||||||
|
diag.span_suggestion(
|
||||||
|
expr.span,
|
||||||
|
"try instead",
|
||||||
|
sugg,
|
||||||
|
applicability
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,8 +45,13 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
|
||||||
|
|
||||||
// Accumulate the variants which should be put in place of the wildcard because they're not
|
// Accumulate the variants which should be put in place of the wildcard because they're not
|
||||||
// already covered.
|
// already covered.
|
||||||
let has_hidden = adt_def.variants().iter().any(|x| is_hidden(cx, x));
|
let is_external = adt_def.did().as_local().is_none();
|
||||||
let mut missing_variants: Vec<_> = adt_def.variants().iter().filter(|x| !is_hidden(cx, x)).collect();
|
let has_external_hidden = is_external && adt_def.variants().iter().any(|x| is_hidden(cx, x));
|
||||||
|
let mut missing_variants: Vec<_> = adt_def
|
||||||
|
.variants()
|
||||||
|
.iter()
|
||||||
|
.filter(|x| !(is_external && is_hidden(cx, x)))
|
||||||
|
.collect();
|
||||||
|
|
||||||
let mut path_prefix = CommonPrefixSearcher::None;
|
let mut path_prefix = CommonPrefixSearcher::None;
|
||||||
for arm in arms {
|
for arm in arms {
|
||||||
|
@ -133,7 +138,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
|
||||||
|
|
||||||
match missing_variants.as_slice() {
|
match missing_variants.as_slice() {
|
||||||
[] => (),
|
[] => (),
|
||||||
[x] if !adt_def.is_variant_list_non_exhaustive() && !has_hidden => span_lint_and_sugg(
|
[x] if !adt_def.is_variant_list_non_exhaustive() && !has_external_hidden => span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
|
MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
|
||||||
wildcard_span,
|
wildcard_span,
|
||||||
|
@ -144,7 +149,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
|
||||||
),
|
),
|
||||||
variants => {
|
variants => {
|
||||||
let mut suggestions: Vec<_> = variants.iter().copied().map(format_suggestion).collect();
|
let mut suggestions: Vec<_> = variants.iter().copied().map(format_suggestion).collect();
|
||||||
let message = if adt_def.is_variant_list_non_exhaustive() || has_hidden {
|
let message = if adt_def.is_variant_list_non_exhaustive() || has_external_hidden {
|
||||||
suggestions.push("_".into());
|
suggestions.push("_".into());
|
||||||
"wildcard matches known variants and will also match future added variants"
|
"wildcard matches known variants and will also match future added variants"
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1818,6 +1818,7 @@ declare_clippy_lint! {
|
||||||
/// - `or_else` to `or`
|
/// - `or_else` to `or`
|
||||||
/// - `get_or_insert_with` to `get_or_insert`
|
/// - `get_or_insert_with` to `get_or_insert`
|
||||||
/// - `ok_or_else` to `ok_or`
|
/// - `ok_or_else` to `ok_or`
|
||||||
|
/// - `then` to `then_some` (for msrv >= 1.62.0)
|
||||||
///
|
///
|
||||||
/// ### Why is this bad?
|
/// ### Why is this bad?
|
||||||
/// Using eager evaluation is shorter and simpler in some cases.
|
/// Using eager evaluation is shorter and simpler in some cases.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::is_diag_trait_item;
|
use clippy_utils::is_diag_trait_item;
|
||||||
use clippy_utils::source::snippet_with_context;
|
use clippy_utils::source::snippet_with_context;
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
|
@ -17,19 +17,31 @@ pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) -
|
||||||
let input_type = cx.typeck_results().expr_ty(expr);
|
let input_type = cx.typeck_results().expr_ty(expr);
|
||||||
if let ty::Adt(adt, _) = cx.typeck_results().expr_ty(expr).kind();
|
if let ty::Adt(adt, _) = cx.typeck_results().expr_ty(expr).kind();
|
||||||
if cx.tcx.is_diagnostic_item(sym::Cow, adt.did());
|
if cx.tcx.is_diagnostic_item(sym::Cow, adt.did());
|
||||||
|
|
||||||
then {
|
then {
|
||||||
let mut app = Applicability::MaybeIncorrect;
|
let mut app = Applicability::MaybeIncorrect;
|
||||||
let recv_snip = snippet_with_context(cx, recv.span, expr.span.ctxt(), "..", &mut app).0;
|
let recv_snip = snippet_with_context(cx, recv.span, expr.span.ctxt(), "..", &mut app).0;
|
||||||
span_lint_and_sugg(
|
span_lint_and_then(
|
||||||
cx,
|
cx,
|
||||||
SUSPICIOUS_TO_OWNED,
|
SUSPICIOUS_TO_OWNED,
|
||||||
expr.span,
|
expr.span,
|
||||||
&with_forced_trimmed_paths!(format!(
|
&with_forced_trimmed_paths!(format!(
|
||||||
"this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned"
|
"this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned"
|
||||||
)),
|
)),
|
||||||
"consider using, depending on intent",
|
|diag| {
|
||||||
format!("{recv_snip}.clone()` or `{recv_snip}.into_owned()"),
|
diag.span_suggestion(
|
||||||
app,
|
expr.span,
|
||||||
|
"depending on intent, either make the Cow an Owned variant",
|
||||||
|
format!("{recv_snip}.into_owned()"),
|
||||||
|
app
|
||||||
|
);
|
||||||
|
diag.span_suggestion(
|
||||||
|
expr.span,
|
||||||
|
"or clone the Cow itself",
|
||||||
|
format!("{recv_snip}.clone()"),
|
||||||
|
app
|
||||||
|
);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ use hir::{
|
||||||
use rustc_ast::Mutability;
|
use rustc_ast::Mutability;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
|
use rustc_middle::lint::in_external_macro;
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
|
@ -66,7 +67,7 @@ declare_lint_pass!(MultipleUnsafeOpsPerBlock => [MULTIPLE_UNSAFE_OPS_PER_BLOCK])
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for MultipleUnsafeOpsPerBlock {
|
impl<'tcx> LateLintPass<'tcx> for MultipleUnsafeOpsPerBlock {
|
||||||
fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
|
fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
|
||||||
if !matches!(block.rules, BlockCheckMode::UnsafeBlock(_)) {
|
if !matches!(block.rules, BlockCheckMode::UnsafeBlock(_)) || in_external_macro(cx.tcx.sess, block.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mut unsafe_ops = vec![];
|
let mut unsafe_ops = vec![];
|
||||||
|
|
|
@ -25,11 +25,11 @@ declare_clippy_lint! {
|
||||||
/// Using the dedicated functions of the `Option` type is clearer and
|
/// Using the dedicated functions of the `Option` type is clearer and
|
||||||
/// more concise than an `if let` expression.
|
/// more concise than an `if let` expression.
|
||||||
///
|
///
|
||||||
/// ### Known problems
|
/// ### Notes
|
||||||
/// This lint uses a deliberately conservative metric for checking
|
/// This lint uses a deliberately conservative metric for checking if the
|
||||||
/// if the inside of either body contains breaks or continues which will
|
/// inside of either body contains loop control expressions `break` or
|
||||||
/// cause it to not suggest a fix if either block contains a loop with
|
/// `continue` (which cannot be used within closures). If these are found,
|
||||||
/// continues or breaks contained within the loop.
|
/// this lint will not be raised.
|
||||||
///
|
///
|
||||||
/// ### Example
|
/// ### Example
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
|
|
@ -624,7 +624,10 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
match *self.cx.tcx.fn_sig(id).subst_identity().skip_binder().inputs()[i].peel_refs().kind() {
|
match *self.cx.tcx.fn_sig(id).subst_identity().skip_binder().inputs()[i]
|
||||||
|
.peel_refs()
|
||||||
|
.kind()
|
||||||
|
{
|
||||||
ty::Dynamic(preds, _, _) if !matches_preds(self.cx, args.deref_ty.ty(self.cx), preds) => {
|
ty::Dynamic(preds, _, _) if !matches_preds(self.cx, args.deref_ty.ty(self.cx), preds) => {
|
||||||
set_skip_flag();
|
set_skip_flag();
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
use clippy_utils::consts::{constant, Constant};
|
use clippy_utils::consts::{constant, Constant};
|
||||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
|
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
|
||||||
|
use clippy_utils::source::snippet_opt;
|
||||||
use clippy_utils::{match_def_path, paths};
|
use clippy_utils::{match_def_path, paths};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_ast::ast::{LitKind, StrStyle};
|
use rustc_ast::ast::{LitKind, StrStyle};
|
||||||
|
@ -77,13 +80,45 @@ impl<'tcx> LateLintPass<'tcx> for Regex {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
fn lint_syntax_error(cx: &LateContext<'_>, error: ®ex_syntax::Error, unescaped: &str, base: Span, offset: u8) {
|
||||||
fn str_span(base: Span, c: regex_syntax::ast::Span, offset: u8) -> Span {
|
let parts: Option<(_, _, &dyn Display)> = match &error {
|
||||||
let offset = u32::from(offset);
|
regex_syntax::Error::Parse(e) => Some((e.span(), e.auxiliary_span(), e.kind())),
|
||||||
let end = base.lo() + BytePos(u32::try_from(c.end.offset).expect("offset too large") + offset);
|
regex_syntax::Error::Translate(e) => Some((e.span(), None, e.kind())),
|
||||||
let start = base.lo() + BytePos(u32::try_from(c.start.offset).expect("offset too large") + offset);
|
_ => None,
|
||||||
assert!(start <= end);
|
};
|
||||||
Span::new(start, end, base.ctxt(), base.parent())
|
|
||||||
|
let convert_span = |regex_span: ®ex_syntax::ast::Span| {
|
||||||
|
let offset = u32::from(offset);
|
||||||
|
let start = base.lo() + BytePos(u32::try_from(regex_span.start.offset).expect("offset too large") + offset);
|
||||||
|
let end = base.lo() + BytePos(u32::try_from(regex_span.end.offset).expect("offset too large") + offset);
|
||||||
|
|
||||||
|
Span::new(start, end, base.ctxt(), base.parent())
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some((primary, auxiliary, kind)) = parts
|
||||||
|
&& let Some(literal_snippet) = snippet_opt(cx, base)
|
||||||
|
&& let Some(inner) = literal_snippet.get(offset as usize..)
|
||||||
|
// Only convert to native rustc spans if the parsed regex matches the
|
||||||
|
// source snippet exactly, to ensure the span offsets are correct
|
||||||
|
&& inner.get(..unescaped.len()) == Some(unescaped)
|
||||||
|
{
|
||||||
|
let spans = if let Some(auxiliary) = auxiliary {
|
||||||
|
vec![convert_span(primary), convert_span(auxiliary)]
|
||||||
|
} else {
|
||||||
|
vec![convert_span(primary)]
|
||||||
|
};
|
||||||
|
|
||||||
|
span_lint(cx, INVALID_REGEX, spans, &format!("regex syntax error: {kind}"));
|
||||||
|
} else {
|
||||||
|
span_lint_and_help(
|
||||||
|
cx,
|
||||||
|
INVALID_REGEX,
|
||||||
|
base,
|
||||||
|
&error.to_string(),
|
||||||
|
None,
|
||||||
|
"consider using a raw string literal: `r\"..\"`",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn const_str<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option<String> {
|
fn const_str<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option<String> {
|
||||||
|
@ -155,25 +190,7 @@ fn check_regex<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
|
||||||
span_lint_and_help(cx, TRIVIAL_REGEX, expr.span, "trivial regex", None, repl);
|
span_lint_and_help(cx, TRIVIAL_REGEX, expr.span, "trivial regex", None, repl);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(regex_syntax::Error::Parse(e)) => {
|
Err(e) => lint_syntax_error(cx, &e, r, expr.span, offset),
|
||||||
span_lint(
|
|
||||||
cx,
|
|
||||||
INVALID_REGEX,
|
|
||||||
str_span(expr.span, *e.span(), offset),
|
|
||||||
&format!("regex syntax error: {}", e.kind()),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
Err(regex_syntax::Error::Translate(e)) => {
|
|
||||||
span_lint(
|
|
||||||
cx,
|
|
||||||
INVALID_REGEX,
|
|
||||||
str_span(expr.span, *e.span(), offset),
|
|
||||||
&format!("regex syntax error: {}", e.kind()),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
span_lint(cx, INVALID_REGEX, expr.span, &format!("regex syntax error: {e}"));
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let Some(r) = const_str(cx, expr) {
|
} else if let Some(r) = const_str(cx, expr) {
|
||||||
|
@ -183,25 +200,7 @@ fn check_regex<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
|
||||||
span_lint_and_help(cx, TRIVIAL_REGEX, expr.span, "trivial regex", None, repl);
|
span_lint_and_help(cx, TRIVIAL_REGEX, expr.span, "trivial regex", None, repl);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(regex_syntax::Error::Parse(e)) => {
|
Err(e) => span_lint(cx, INVALID_REGEX, expr.span, &e.to_string()),
|
||||||
span_lint(
|
|
||||||
cx,
|
|
||||||
INVALID_REGEX,
|
|
||||||
expr.span,
|
|
||||||
&format!("regex syntax error on position {}: {}", e.span().start.offset, e.kind()),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
Err(regex_syntax::Error::Translate(e)) => {
|
|
||||||
span_lint(
|
|
||||||
cx,
|
|
||||||
INVALID_REGEX,
|
|
||||||
expr.span,
|
|
||||||
&format!("regex syntax error on position {}: {}", e.span().start.offset, e.kind()),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
span_lint(cx, INVALID_REGEX, expr.span, &format!("regex syntax error: {e}"));
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,8 +78,8 @@ fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, spa
|
||||||
// We don't want to emit this lint if the `#[must_use]` attribute is already there.
|
// We don't want to emit this lint if the `#[must_use]` attribute is already there.
|
||||||
if !cx.tcx.hir().attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use));
|
if !cx.tcx.hir().attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use));
|
||||||
if cx.tcx.visibility(fn_def.to_def_id()).is_public();
|
if cx.tcx.visibility(fn_def.to_def_id()).is_public();
|
||||||
let ret_ty = return_ty(cx, owner_id.into());
|
let ret_ty = return_ty(cx, owner_id);
|
||||||
let self_arg = nth_arg(cx, owner_id.into(), 0);
|
let self_arg = nth_arg(cx, owner_id, 0);
|
||||||
// If `Self` has the same type as the returned type, then we want to warn.
|
// If `Self` has the same type as the returned type, then we want to warn.
|
||||||
//
|
//
|
||||||
// For this check, we don't want to remove the reference on the returned type because if
|
// For this check, we don't want to remove the reference on the returned type because if
|
||||||
|
|
|
@ -30,7 +30,7 @@ declare_clippy_lint! {
|
||||||
/// # let x = 0;
|
/// # let x = 0;
|
||||||
/// unsafe { f(x); }
|
/// unsafe { f(x); }
|
||||||
/// ```
|
/// ```
|
||||||
#[clippy::version = "1.66.0"]
|
#[clippy::version = "1.68.0"]
|
||||||
pub SEMICOLON_INSIDE_BLOCK,
|
pub SEMICOLON_INSIDE_BLOCK,
|
||||||
restriction,
|
restriction,
|
||||||
"add a semicolon inside the block"
|
"add a semicolon inside the block"
|
||||||
|
@ -59,7 +59,7 @@ declare_clippy_lint! {
|
||||||
/// # let x = 0;
|
/// # let x = 0;
|
||||||
/// unsafe { f(x) };
|
/// unsafe { f(x) };
|
||||||
/// ```
|
/// ```
|
||||||
#[clippy::version = "1.66.0"]
|
#[clippy::version = "1.68.0"]
|
||||||
pub SEMICOLON_OUTSIDE_BLOCK,
|
pub SEMICOLON_OUTSIDE_BLOCK,
|
||||||
restriction,
|
restriction,
|
||||||
"add a semicolon outside the block"
|
"add a semicolon outside the block"
|
||||||
|
|
|
@ -392,9 +392,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
|
fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
|
||||||
let is_exported = cx
|
let is_exported = cx.effective_visibilities.is_exported(field.def_id);
|
||||||
.effective_visibilities
|
|
||||||
.is_exported(field.def_id);
|
|
||||||
|
|
||||||
self.check_ty(
|
self.check_ty(
|
||||||
cx,
|
cx,
|
||||||
|
|
|
@ -65,7 +65,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hir::ExprKind::MethodCall(path, arg_0, ..) => match path.ident.as_str() {
|
hir::ExprKind::MethodCall(path, arg_0, ..) => match path.ident.as_str() {
|
||||||
"expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => {
|
"expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" | "is_ok" | "is_err" => {
|
||||||
check_map_error(cx, arg_0, expr);
|
check_map_error(cx, arg_0, expr);
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
|
|
|
@ -253,7 +253,7 @@ define_Conf! {
|
||||||
///
|
///
|
||||||
/// Suppress lints whenever the suggested change would cause breakage for other crates.
|
/// Suppress lints whenever the suggested change would cause breakage for other crates.
|
||||||
(avoid_breaking_exported_api: bool = true),
|
(avoid_breaking_exported_api: bool = true),
|
||||||
/// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION.
|
/// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN.
|
||||||
///
|
///
|
||||||
/// The minimum rust version that the project supports
|
/// The minimum rust version that the project supports
|
||||||
(msrv: Option<String> = None),
|
(msrv: Option<String> = None),
|
||||||
|
@ -323,7 +323,7 @@ define_Conf! {
|
||||||
///
|
///
|
||||||
/// The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference.
|
/// The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference.
|
||||||
(trivial_copy_size_limit: Option<u64> = None),
|
(trivial_copy_size_limit: Option<u64> = None),
|
||||||
/// Lint: LARGE_TYPE_PASS_BY_MOVE.
|
/// Lint: LARGE_TYPES_PASSED_BY_VALUE.
|
||||||
///
|
///
|
||||||
/// The minimum size (in bytes) to consider a type for passing by reference instead of by value.
|
/// The minimum size (in bytes) to consider a type for passing by reference instead of by value.
|
||||||
(pass_by_value_size_limit: u64 = 256),
|
(pass_by_value_size_limit: u64 = 256),
|
||||||
|
@ -411,7 +411,7 @@ define_Conf! {
|
||||||
/// the slice pattern that is suggested. If more elements would be necessary, the lint is suppressed.
|
/// the slice pattern that is suggested. If more elements would be necessary, the lint is suppressed.
|
||||||
/// For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
|
/// For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
|
||||||
(max_suggested_slice_pattern_length: u64 = 3),
|
(max_suggested_slice_pattern_length: u64 = 3),
|
||||||
/// Lint: AWAIT_HOLDING_INVALID_TYPE
|
/// Lint: AWAIT_HOLDING_INVALID_TYPE.
|
||||||
(await_holding_invalid_types: Vec<crate::utils::conf::DisallowedPath> = Vec::new()),
|
(await_holding_invalid_types: Vec<crate::utils::conf::DisallowedPath> = Vec::new()),
|
||||||
/// Lint: LARGE_INCLUDE_FILE.
|
/// Lint: LARGE_INCLUDE_FILE.
|
||||||
///
|
///
|
||||||
|
@ -437,7 +437,7 @@ define_Conf! {
|
||||||
///
|
///
|
||||||
/// The maximum size of the `Err`-variant in a `Result` returned from a function
|
/// The maximum size of the `Err`-variant in a `Result` returned from a function
|
||||||
(large_error_threshold: u64 = 128),
|
(large_error_threshold: u64 = 128),
|
||||||
/// Lint: MUTABLE_KEY.
|
/// Lint: MUTABLE_KEY_TYPE.
|
||||||
///
|
///
|
||||||
/// A list of paths to types that should be treated like `Arc`, i.e. ignored but
|
/// A list of paths to types that should be treated like `Arc`, i.e. ignored but
|
||||||
/// for the generic parameters for determining interior mutability
|
/// for the generic parameters for determining interior mutability
|
||||||
|
@ -446,7 +446,7 @@ define_Conf! {
|
||||||
///
|
///
|
||||||
/// Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)`
|
/// Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)`
|
||||||
(allow_mixed_uninlined_format_args: bool = true),
|
(allow_mixed_uninlined_format_args: bool = true),
|
||||||
/// Lint: INDEXING_SLICING
|
/// Lint: INDEXING_SLICING.
|
||||||
///
|
///
|
||||||
/// Whether to suppress a restriction lint in constant code. In same
|
/// Whether to suppress a restriction lint in constant code. In same
|
||||||
/// cases the restructured operation might not be unavoidable, as the
|
/// cases the restructured operation might not be unavoidable, as the
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use clippy_utils::get_attr;
|
use clippy_utils::get_attr;
|
||||||
|
use hir::TraitItem;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
|
@ -47,6 +48,18 @@ impl<'tcx> LateLintPass<'tcx> for DumpHir {
|
||||||
println!("{stmt:#?}");
|
println!("{stmt:#?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) {
|
||||||
|
if has_attr(cx, item.hir_id()) {
|
||||||
|
println!("{item:#?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_impl_item(&mut self, cx: &LateContext<'_>, item: &hir::ImplItem<'_>) {
|
||||||
|
if has_attr(cx, item.hir_id()) {
|
||||||
|
println!("{item:#?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_attr(cx: &LateContext<'_>, hir_id: hir::HirId) -> bool {
|
fn has_attr(cx: &LateContext<'_>, hir_id: hir::HirId) -> bool {
|
||||||
|
|
|
@ -215,14 +215,13 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
|
||||||
cx,
|
cx,
|
||||||
};
|
};
|
||||||
let body_id = cx.tcx.hir().body_owned_by(
|
let body_id = cx.tcx.hir().body_owned_by(
|
||||||
cx.tcx.hir().local_def_id(
|
impl_item_refs
|
||||||
impl_item_refs
|
.iter()
|
||||||
.iter()
|
.find(|iiref| iiref.ident.as_str() == "get_lints")
|
||||||
.find(|iiref| iiref.ident.as_str() == "get_lints")
|
.expect("LintPass needs to implement get_lints")
|
||||||
.expect("LintPass needs to implement get_lints")
|
.id
|
||||||
.id
|
.owner_id
|
||||||
.hir_id(),
|
.def_id,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
collector.visit_expr(cx.tcx.hir().body(body_id).value);
|
collector.visit_expr(cx.tcx.hir().body(body_id).value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -770,10 +770,7 @@ impl<'tcx> FormatSpec<'tcx> {
|
||||||
/// Has no other formatting specifiers than setting the format trait. returns true for `{}`,
|
/// Has no other formatting specifiers than setting the format trait. returns true for `{}`,
|
||||||
/// `{foo}`, `{:?}`, but false for `{foo:5}`, `{3:.5?}`
|
/// `{foo}`, `{:?}`, but false for `{foo:5}`, `{3:.5?}`
|
||||||
pub fn is_default_for_trait(&self) -> bool {
|
pub fn is_default_for_trait(&self) -> bool {
|
||||||
self.width.is_implied()
|
self.width.is_implied() && self.precision.is_implied() && self.align == Alignment::AlignUnknown && self.no_flags
|
||||||
&& self.precision.is_implied()
|
|
||||||
&& self.align == Alignment::AlignUnknown
|
|
||||||
&& self.no_flags
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -809,7 +809,10 @@ pub struct DerefClosure {
|
||||||
///
|
///
|
||||||
/// note: this only works on single line immutable closures with exactly one input parameter.
|
/// note: this only works on single line immutable closures with exactly one input parameter.
|
||||||
pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Option<DerefClosure> {
|
pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Option<DerefClosure> {
|
||||||
if let hir::ExprKind::Closure(&Closure { fn_decl, def_id, body, .. }) = closure.kind {
|
if let hir::ExprKind::Closure(&Closure {
|
||||||
|
fn_decl, def_id, body, ..
|
||||||
|
}) = closure.kind
|
||||||
|
{
|
||||||
let closure_body = cx.tcx.hir().body(body);
|
let closure_body = cx.tcx.hir().body(body);
|
||||||
// is closure arg a type annotated double reference (i.e.: `|x: &&i32| ...`)
|
// is closure arg a type annotated double reference (i.e.: `|x: &&i32| ...`)
|
||||||
// a type annotation is present if param `kind` is different from `TyKind::Infer`
|
// a type annotation is present if param `kind` is different from `TyKind::Infer`
|
||||||
|
|
|
@ -392,12 +392,16 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool {
|
||||||
.cx
|
.cx
|
||||||
.typeck_results()
|
.typeck_results()
|
||||||
.type_dependent_def_id(e.hir_id)
|
.type_dependent_def_id(e.hir_id)
|
||||||
.map_or(false, |id| self.cx.tcx.fn_sig(id).skip_binder().unsafety() == Unsafety::Unsafe) =>
|
.map_or(false, |id| {
|
||||||
|
self.cx.tcx.fn_sig(id).skip_binder().unsafety() == Unsafety::Unsafe
|
||||||
|
}) =>
|
||||||
{
|
{
|
||||||
self.is_unsafe = true;
|
self.is_unsafe = true;
|
||||||
},
|
},
|
||||||
ExprKind::Call(func, _) => match *self.cx.typeck_results().expr_ty(func).peel_refs().kind() {
|
ExprKind::Call(func, _) => match *self.cx.typeck_results().expr_ty(func).peel_refs().kind() {
|
||||||
ty::FnDef(id, _) if self.cx.tcx.fn_sig(id).skip_binder().unsafety() == Unsafety::Unsafe => self.is_unsafe = true,
|
ty::FnDef(id, _) if self.cx.tcx.fn_sig(id).skip_binder().unsafety() == Unsafety::Unsafe => {
|
||||||
|
self.is_unsafe = true;
|
||||||
|
},
|
||||||
ty::FnPtr(sig) if sig.unsafety() == Unsafety::Unsafe => self.is_unsafe = true,
|
ty::FnPtr(sig) if sig.unsafety() == Unsafety::Unsafe => self.is_unsafe = true,
|
||||||
_ => walk_expr(self, e),
|
_ => walk_expr(self, e),
|
||||||
},
|
},
|
||||||
|
|
|
@ -10,8 +10,8 @@ edition = "2021"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cargo_metadata = "0.14"
|
cargo_metadata = "0.15.3"
|
||||||
clap = "3.2"
|
clap = "4.1.4"
|
||||||
crossbeam-channel = "0.5.6"
|
crossbeam-channel = "0.5.6"
|
||||||
flate2 = "1.0"
|
flate2 = "1.0"
|
||||||
rayon = "1.5.1"
|
rayon = "1.5.1"
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly-2023-01-27"
|
channel = "nightly-2023-02-10"
|
||||||
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
||||||
|
|
|
@ -1,12 +1,3 @@
|
||||||
error: hardcoded path to a diagnostic item
|
|
||||||
--> $DIR/unnecessary_def_path_hardcoded_path.rs:10:36
|
|
||||||
|
|
|
||||||
LL | const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"];
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= help: convert all references to use `sym::Deref`
|
|
||||||
= note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
|
|
||||||
|
|
||||||
error: hardcoded path to a diagnostic item
|
error: hardcoded path to a diagnostic item
|
||||||
--> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
|
--> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
|
||||||
|
|
|
|
||||||
|
@ -14,6 +5,15 @@ LL | const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref",
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: convert all references to use `sym::deref_method`
|
= help: convert all references to use `sym::deref_method`
|
||||||
|
= note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
|
||||||
|
|
||||||
|
error: hardcoded path to a diagnostic item
|
||||||
|
--> $DIR/unnecessary_def_path_hardcoded_path.rs:10:36
|
||||||
|
|
|
||||||
|
LL | const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"];
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: convert all references to use `sym::Deref`
|
||||||
|
|
||||||
error: hardcoded path to a language item
|
error: hardcoded path to a language item
|
||||||
--> $DIR/unnecessary_def_path_hardcoded_path.rs:11:40
|
--> $DIR/unnecessary_def_path_hardcoded_path.rs:11:40
|
||||||
|
|
|
@ -149,3 +149,22 @@ macro_rules! almost_complete_range {
|
||||||
let _ = '0'..'9';
|
let _ = '0'..'9';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! unsafe_macro {
|
||||||
|
() => {
|
||||||
|
unsafe {
|
||||||
|
*core::ptr::null::<()>();
|
||||||
|
*core::ptr::null::<()>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! needless_lifetime {
|
||||||
|
() => {
|
||||||
|
fn needless_lifetime<'a>(x: &'a u8) -> &'a u8 {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ fn main() {
|
||||||
let b = ImplNotTraitWithBool;
|
let b = ImplNotTraitWithBool;
|
||||||
|
|
||||||
assert_eq!("a".len(), 1);
|
assert_eq!("a".len(), 1);
|
||||||
assert!("a".is_empty());
|
assert!(!"a".is_empty());
|
||||||
assert!("".is_empty());
|
assert!("".is_empty());
|
||||||
assert!("".is_empty());
|
assert!("".is_empty());
|
||||||
assert_eq!(a!(), b!());
|
assert_eq!(a!(), b!());
|
||||||
|
@ -97,16 +97,16 @@ fn main() {
|
||||||
|
|
||||||
assert_ne!("a".len(), 1);
|
assert_ne!("a".len(), 1);
|
||||||
assert!("a".is_empty());
|
assert!("a".is_empty());
|
||||||
assert!("".is_empty());
|
assert!(!"".is_empty());
|
||||||
assert!("".is_empty());
|
assert!(!"".is_empty());
|
||||||
assert_ne!(a!(), b!());
|
assert_ne!(a!(), b!());
|
||||||
assert_ne!(a!(), "".is_empty());
|
assert_ne!(a!(), "".is_empty());
|
||||||
assert_ne!("".is_empty(), b!());
|
assert_ne!("".is_empty(), b!());
|
||||||
assert_ne!(a, true);
|
assert_ne!(a, true);
|
||||||
assert!(b);
|
assert!(!b);
|
||||||
|
|
||||||
debug_assert_eq!("a".len(), 1);
|
debug_assert_eq!("a".len(), 1);
|
||||||
debug_assert!("a".is_empty());
|
debug_assert!(!"a".is_empty());
|
||||||
debug_assert!("".is_empty());
|
debug_assert!("".is_empty());
|
||||||
debug_assert!("".is_empty());
|
debug_assert!("".is_empty());
|
||||||
debug_assert_eq!(a!(), b!());
|
debug_assert_eq!(a!(), b!());
|
||||||
|
@ -117,27 +117,27 @@ fn main() {
|
||||||
|
|
||||||
debug_assert_ne!("a".len(), 1);
|
debug_assert_ne!("a".len(), 1);
|
||||||
debug_assert!("a".is_empty());
|
debug_assert!("a".is_empty());
|
||||||
debug_assert!("".is_empty());
|
debug_assert!(!"".is_empty());
|
||||||
debug_assert!("".is_empty());
|
debug_assert!(!"".is_empty());
|
||||||
debug_assert_ne!(a!(), b!());
|
debug_assert_ne!(a!(), b!());
|
||||||
debug_assert_ne!(a!(), "".is_empty());
|
debug_assert_ne!(a!(), "".is_empty());
|
||||||
debug_assert_ne!("".is_empty(), b!());
|
debug_assert_ne!("".is_empty(), b!());
|
||||||
debug_assert_ne!(a, true);
|
debug_assert_ne!(a, true);
|
||||||
debug_assert!(b);
|
debug_assert!(!b);
|
||||||
|
|
||||||
// assert with error messages
|
// assert with error messages
|
||||||
assert_eq!("a".len(), 1, "tadam {}", 1);
|
assert_eq!("a".len(), 1, "tadam {}", 1);
|
||||||
assert_eq!("a".len(), 1, "tadam {}", true);
|
assert_eq!("a".len(), 1, "tadam {}", true);
|
||||||
assert!("a".is_empty(), "tadam {}", 1);
|
assert!(!"a".is_empty(), "tadam {}", 1);
|
||||||
assert!("a".is_empty(), "tadam {}", true);
|
assert!(!"a".is_empty(), "tadam {}", true);
|
||||||
assert!("a".is_empty(), "tadam {}", true);
|
assert!(!"a".is_empty(), "tadam {}", true);
|
||||||
assert_eq!(a, true, "tadam {}", false);
|
assert_eq!(a, true, "tadam {}", false);
|
||||||
|
|
||||||
debug_assert_eq!("a".len(), 1, "tadam {}", 1);
|
debug_assert_eq!("a".len(), 1, "tadam {}", 1);
|
||||||
debug_assert_eq!("a".len(), 1, "tadam {}", true);
|
debug_assert_eq!("a".len(), 1, "tadam {}", true);
|
||||||
debug_assert!("a".is_empty(), "tadam {}", 1);
|
debug_assert!(!"a".is_empty(), "tadam {}", 1);
|
||||||
debug_assert!("a".is_empty(), "tadam {}", true);
|
debug_assert!(!"a".is_empty(), "tadam {}", true);
|
||||||
debug_assert!("a".is_empty(), "tadam {}", true);
|
debug_assert!(!"a".is_empty(), "tadam {}", true);
|
||||||
debug_assert_eq!(a, true, "tadam {}", false);
|
debug_assert_eq!(a, true, "tadam {}", false);
|
||||||
|
|
||||||
assert!(a!());
|
assert!(a!());
|
||||||
|
@ -158,4 +158,14 @@ fn main() {
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
in_macro!(a);
|
in_macro!(a);
|
||||||
|
|
||||||
|
assert!("".is_empty());
|
||||||
|
assert!("".is_empty());
|
||||||
|
assert!(!"requires negation".is_empty());
|
||||||
|
assert!(!"requires negation".is_empty());
|
||||||
|
|
||||||
|
debug_assert!("".is_empty());
|
||||||
|
debug_assert!("".is_empty());
|
||||||
|
debug_assert!(!"requires negation".is_empty());
|
||||||
|
debug_assert!(!"requires negation".is_empty());
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,4 +158,14 @@ fn main() {
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
in_macro!(a);
|
in_macro!(a);
|
||||||
|
|
||||||
|
assert_eq!("".is_empty(), true);
|
||||||
|
assert_ne!("".is_empty(), false);
|
||||||
|
assert_ne!("requires negation".is_empty(), true);
|
||||||
|
assert_eq!("requires negation".is_empty(), false);
|
||||||
|
|
||||||
|
debug_assert_eq!("".is_empty(), true);
|
||||||
|
debug_assert_ne!("".is_empty(), false);
|
||||||
|
debug_assert_ne!("requires negation".is_empty(), true);
|
||||||
|
debug_assert_eq!("requires negation".is_empty(), false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ LL | assert_eq!("a".is_empty(), false);
|
||||||
help: replace it with `assert!(..)`
|
help: replace it with `assert!(..)`
|
||||||
|
|
|
|
||||||
LL - assert_eq!("a".is_empty(), false);
|
LL - assert_eq!("a".is_empty(), false);
|
||||||
LL + assert!("a".is_empty());
|
LL + assert!(!"a".is_empty());
|
||||||
|
|
|
|
||||||
|
|
||||||
error: used `assert_eq!` with a literal bool
|
error: used `assert_eq!` with a literal bool
|
||||||
|
@ -68,7 +68,7 @@ LL | assert_ne!("".is_empty(), true);
|
||||||
help: replace it with `assert!(..)`
|
help: replace it with `assert!(..)`
|
||||||
|
|
|
|
||||||
LL - assert_ne!("".is_empty(), true);
|
LL - assert_ne!("".is_empty(), true);
|
||||||
LL + assert!("".is_empty());
|
LL + assert!(!"".is_empty());
|
||||||
|
|
|
|
||||||
|
|
||||||
error: used `assert_ne!` with a literal bool
|
error: used `assert_ne!` with a literal bool
|
||||||
|
@ -80,7 +80,7 @@ LL | assert_ne!(true, "".is_empty());
|
||||||
help: replace it with `assert!(..)`
|
help: replace it with `assert!(..)`
|
||||||
|
|
|
|
||||||
LL - assert_ne!(true, "".is_empty());
|
LL - assert_ne!(true, "".is_empty());
|
||||||
LL + assert!("".is_empty());
|
LL + assert!(!"".is_empty());
|
||||||
|
|
|
|
||||||
|
|
||||||
error: used `assert_ne!` with a literal bool
|
error: used `assert_ne!` with a literal bool
|
||||||
|
@ -92,7 +92,7 @@ LL | assert_ne!(b, true);
|
||||||
help: replace it with `assert!(..)`
|
help: replace it with `assert!(..)`
|
||||||
|
|
|
|
||||||
LL - assert_ne!(b, true);
|
LL - assert_ne!(b, true);
|
||||||
LL + assert!(b);
|
LL + assert!(!b);
|
||||||
|
|
|
|
||||||
|
|
||||||
error: used `debug_assert_eq!` with a literal bool
|
error: used `debug_assert_eq!` with a literal bool
|
||||||
|
@ -104,7 +104,7 @@ LL | debug_assert_eq!("a".is_empty(), false);
|
||||||
help: replace it with `debug_assert!(..)`
|
help: replace it with `debug_assert!(..)`
|
||||||
|
|
|
|
||||||
LL - debug_assert_eq!("a".is_empty(), false);
|
LL - debug_assert_eq!("a".is_empty(), false);
|
||||||
LL + debug_assert!("a".is_empty());
|
LL + debug_assert!(!"a".is_empty());
|
||||||
|
|
|
|
||||||
|
|
||||||
error: used `debug_assert_eq!` with a literal bool
|
error: used `debug_assert_eq!` with a literal bool
|
||||||
|
@ -164,7 +164,7 @@ LL | debug_assert_ne!("".is_empty(), true);
|
||||||
help: replace it with `debug_assert!(..)`
|
help: replace it with `debug_assert!(..)`
|
||||||
|
|
|
|
||||||
LL - debug_assert_ne!("".is_empty(), true);
|
LL - debug_assert_ne!("".is_empty(), true);
|
||||||
LL + debug_assert!("".is_empty());
|
LL + debug_assert!(!"".is_empty());
|
||||||
|
|
|
|
||||||
|
|
||||||
error: used `debug_assert_ne!` with a literal bool
|
error: used `debug_assert_ne!` with a literal bool
|
||||||
|
@ -176,7 +176,7 @@ LL | debug_assert_ne!(true, "".is_empty());
|
||||||
help: replace it with `debug_assert!(..)`
|
help: replace it with `debug_assert!(..)`
|
||||||
|
|
|
|
||||||
LL - debug_assert_ne!(true, "".is_empty());
|
LL - debug_assert_ne!(true, "".is_empty());
|
||||||
LL + debug_assert!("".is_empty());
|
LL + debug_assert!(!"".is_empty());
|
||||||
|
|
|
|
||||||
|
|
||||||
error: used `debug_assert_ne!` with a literal bool
|
error: used `debug_assert_ne!` with a literal bool
|
||||||
|
@ -188,7 +188,7 @@ LL | debug_assert_ne!(b, true);
|
||||||
help: replace it with `debug_assert!(..)`
|
help: replace it with `debug_assert!(..)`
|
||||||
|
|
|
|
||||||
LL - debug_assert_ne!(b, true);
|
LL - debug_assert_ne!(b, true);
|
||||||
LL + debug_assert!(b);
|
LL + debug_assert!(!b);
|
||||||
|
|
|
|
||||||
|
|
||||||
error: used `assert_eq!` with a literal bool
|
error: used `assert_eq!` with a literal bool
|
||||||
|
@ -200,7 +200,7 @@ LL | assert_eq!("a".is_empty(), false, "tadam {}", 1);
|
||||||
help: replace it with `assert!(..)`
|
help: replace it with `assert!(..)`
|
||||||
|
|
|
|
||||||
LL - assert_eq!("a".is_empty(), false, "tadam {}", 1);
|
LL - assert_eq!("a".is_empty(), false, "tadam {}", 1);
|
||||||
LL + assert!("a".is_empty(), "tadam {}", 1);
|
LL + assert!(!"a".is_empty(), "tadam {}", 1);
|
||||||
|
|
|
|
||||||
|
|
||||||
error: used `assert_eq!` with a literal bool
|
error: used `assert_eq!` with a literal bool
|
||||||
|
@ -212,7 +212,7 @@ LL | assert_eq!("a".is_empty(), false, "tadam {}", true);
|
||||||
help: replace it with `assert!(..)`
|
help: replace it with `assert!(..)`
|
||||||
|
|
|
|
||||||
LL - assert_eq!("a".is_empty(), false, "tadam {}", true);
|
LL - assert_eq!("a".is_empty(), false, "tadam {}", true);
|
||||||
LL + assert!("a".is_empty(), "tadam {}", true);
|
LL + assert!(!"a".is_empty(), "tadam {}", true);
|
||||||
|
|
|
|
||||||
|
|
||||||
error: used `assert_eq!` with a literal bool
|
error: used `assert_eq!` with a literal bool
|
||||||
|
@ -224,7 +224,7 @@ LL | assert_eq!(false, "a".is_empty(), "tadam {}", true);
|
||||||
help: replace it with `assert!(..)`
|
help: replace it with `assert!(..)`
|
||||||
|
|
|
|
||||||
LL - assert_eq!(false, "a".is_empty(), "tadam {}", true);
|
LL - assert_eq!(false, "a".is_empty(), "tadam {}", true);
|
||||||
LL + assert!("a".is_empty(), "tadam {}", true);
|
LL + assert!(!"a".is_empty(), "tadam {}", true);
|
||||||
|
|
|
|
||||||
|
|
||||||
error: used `debug_assert_eq!` with a literal bool
|
error: used `debug_assert_eq!` with a literal bool
|
||||||
|
@ -236,7 +236,7 @@ LL | debug_assert_eq!("a".is_empty(), false, "tadam {}", 1);
|
||||||
help: replace it with `debug_assert!(..)`
|
help: replace it with `debug_assert!(..)`
|
||||||
|
|
|
|
||||||
LL - debug_assert_eq!("a".is_empty(), false, "tadam {}", 1);
|
LL - debug_assert_eq!("a".is_empty(), false, "tadam {}", 1);
|
||||||
LL + debug_assert!("a".is_empty(), "tadam {}", 1);
|
LL + debug_assert!(!"a".is_empty(), "tadam {}", 1);
|
||||||
|
|
|
|
||||||
|
|
||||||
error: used `debug_assert_eq!` with a literal bool
|
error: used `debug_assert_eq!` with a literal bool
|
||||||
|
@ -248,7 +248,7 @@ LL | debug_assert_eq!("a".is_empty(), false, "tadam {}", true);
|
||||||
help: replace it with `debug_assert!(..)`
|
help: replace it with `debug_assert!(..)`
|
||||||
|
|
|
|
||||||
LL - debug_assert_eq!("a".is_empty(), false, "tadam {}", true);
|
LL - debug_assert_eq!("a".is_empty(), false, "tadam {}", true);
|
||||||
LL + debug_assert!("a".is_empty(), "tadam {}", true);
|
LL + debug_assert!(!"a".is_empty(), "tadam {}", true);
|
||||||
|
|
|
|
||||||
|
|
||||||
error: used `debug_assert_eq!` with a literal bool
|
error: used `debug_assert_eq!` with a literal bool
|
||||||
|
@ -260,7 +260,7 @@ LL | debug_assert_eq!(false, "a".is_empty(), "tadam {}", true);
|
||||||
help: replace it with `debug_assert!(..)`
|
help: replace it with `debug_assert!(..)`
|
||||||
|
|
|
|
||||||
LL - debug_assert_eq!(false, "a".is_empty(), "tadam {}", true);
|
LL - debug_assert_eq!(false, "a".is_empty(), "tadam {}", true);
|
||||||
LL + debug_assert!("a".is_empty(), "tadam {}", true);
|
LL + debug_assert!(!"a".is_empty(), "tadam {}", true);
|
||||||
|
|
|
|
||||||
|
|
||||||
error: used `assert_eq!` with a literal bool
|
error: used `assert_eq!` with a literal bool
|
||||||
|
@ -299,5 +299,101 @@ LL - renamed!(b, true);
|
||||||
LL + debug_assert!(b);
|
LL + debug_assert!(b);
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 25 previous errors
|
error: used `assert_eq!` with a literal bool
|
||||||
|
--> $DIR/bool_assert_comparison.rs:162:5
|
||||||
|
|
|
||||||
|
LL | assert_eq!("".is_empty(), true);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: replace it with `assert!(..)`
|
||||||
|
|
|
||||||
|
LL - assert_eq!("".is_empty(), true);
|
||||||
|
LL + assert!("".is_empty());
|
||||||
|
|
|
||||||
|
|
||||||
|
error: used `assert_ne!` with a literal bool
|
||||||
|
--> $DIR/bool_assert_comparison.rs:163:5
|
||||||
|
|
|
||||||
|
LL | assert_ne!("".is_empty(), false);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: replace it with `assert!(..)`
|
||||||
|
|
|
||||||
|
LL - assert_ne!("".is_empty(), false);
|
||||||
|
LL + assert!("".is_empty());
|
||||||
|
|
|
||||||
|
|
||||||
|
error: used `assert_ne!` with a literal bool
|
||||||
|
--> $DIR/bool_assert_comparison.rs:164:5
|
||||||
|
|
|
||||||
|
LL | assert_ne!("requires negation".is_empty(), true);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: replace it with `assert!(..)`
|
||||||
|
|
|
||||||
|
LL - assert_ne!("requires negation".is_empty(), true);
|
||||||
|
LL + assert!(!"requires negation".is_empty());
|
||||||
|
|
|
||||||
|
|
||||||
|
error: used `assert_eq!` with a literal bool
|
||||||
|
--> $DIR/bool_assert_comparison.rs:165:5
|
||||||
|
|
|
||||||
|
LL | assert_eq!("requires negation".is_empty(), false);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: replace it with `assert!(..)`
|
||||||
|
|
|
||||||
|
LL - assert_eq!("requires negation".is_empty(), false);
|
||||||
|
LL + assert!(!"requires negation".is_empty());
|
||||||
|
|
|
||||||
|
|
||||||
|
error: used `debug_assert_eq!` with a literal bool
|
||||||
|
--> $DIR/bool_assert_comparison.rs:167:5
|
||||||
|
|
|
||||||
|
LL | debug_assert_eq!("".is_empty(), true);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: replace it with `debug_assert!(..)`
|
||||||
|
|
|
||||||
|
LL - debug_assert_eq!("".is_empty(), true);
|
||||||
|
LL + debug_assert!("".is_empty());
|
||||||
|
|
|
||||||
|
|
||||||
|
error: used `debug_assert_ne!` with a literal bool
|
||||||
|
--> $DIR/bool_assert_comparison.rs:168:5
|
||||||
|
|
|
||||||
|
LL | debug_assert_ne!("".is_empty(), false);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: replace it with `debug_assert!(..)`
|
||||||
|
|
|
||||||
|
LL - debug_assert_ne!("".is_empty(), false);
|
||||||
|
LL + debug_assert!("".is_empty());
|
||||||
|
|
|
||||||
|
|
||||||
|
error: used `debug_assert_ne!` with a literal bool
|
||||||
|
--> $DIR/bool_assert_comparison.rs:169:5
|
||||||
|
|
|
||||||
|
LL | debug_assert_ne!("requires negation".is_empty(), true);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: replace it with `debug_assert!(..)`
|
||||||
|
|
|
||||||
|
LL - debug_assert_ne!("requires negation".is_empty(), true);
|
||||||
|
LL + debug_assert!(!"requires negation".is_empty());
|
||||||
|
|
|
||||||
|
|
||||||
|
error: used `debug_assert_eq!` with a literal bool
|
||||||
|
--> $DIR/bool_assert_comparison.rs:170:5
|
||||||
|
|
|
||||||
|
LL | debug_assert_eq!("requires negation".is_empty(), false);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: replace it with `debug_assert!(..)`
|
||||||
|
|
|
||||||
|
LL - debug_assert_eq!("requires negation".is_empty(), false);
|
||||||
|
LL + debug_assert!(!"requires negation".is_empty());
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 33 previous errors
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,11 @@ LL | pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: `-D clippy::needless-lifetimes` implied by `-D warnings`
|
= note: `-D clippy::needless-lifetimes` implied by `-D warnings`
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) {
|
||||||
|
LL + pub fn add_barfoos_to_foos(bars: &HashSet<&Bar>) {
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,11 @@ note: the lint level is defined here
|
||||||
|
|
|
|
||||||
LL | #![deny(clippy::needless_lifetimes)]
|
LL | #![deny(clippy::needless_lifetimes)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn baz<'a>(&'a self) -> impl Foo + 'a {
|
||||||
|
LL + fn baz(&self) -> impl Foo + '_ {
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
69
tests/ui/extra_unused_type_parameters.rs
Normal file
69
tests/ui/extra_unused_type_parameters.rs
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
#![allow(unused, clippy::needless_lifetimes)]
|
||||||
|
#![warn(clippy::extra_unused_type_parameters)]
|
||||||
|
|
||||||
|
fn unused_ty<T>(x: u8) {}
|
||||||
|
|
||||||
|
fn unused_multi<T, U>(x: u8) {}
|
||||||
|
|
||||||
|
fn unused_with_lt<'a, T>(x: &'a u8) {}
|
||||||
|
|
||||||
|
fn used_ty<T>(x: T, y: u8) {}
|
||||||
|
|
||||||
|
fn used_ref<'a, T>(x: &'a T) {}
|
||||||
|
|
||||||
|
fn used_ret<T: Default>(x: u8) -> T {
|
||||||
|
T::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unused_bounded<T: Default, U>(x: U) {}
|
||||||
|
|
||||||
|
fn unused_where_clause<T, U>(x: U)
|
||||||
|
where
|
||||||
|
T: Default,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
fn some_unused<A, B, C, D: Iterator<Item = (B, C)>, E>(b: B, c: C) {}
|
||||||
|
|
||||||
|
fn used_opaque<A>(iter: impl Iterator<Item = A>) -> usize {
|
||||||
|
iter.count()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn used_ret_opaque<A>() -> impl Iterator<Item = A> {
|
||||||
|
std::iter::empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn used_vec_box<T>(x: Vec<Box<T>>) {}
|
||||||
|
|
||||||
|
fn used_body<T: Default + ToString>() -> String {
|
||||||
|
T::default().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn used_closure<T: Default + ToString>() -> impl Fn() {
|
||||||
|
|| println!("{}", T::default().to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
impl S {
|
||||||
|
fn unused_ty_impl<T>(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't lint on trait methods
|
||||||
|
trait Foo {
|
||||||
|
fn bar<T>(&self);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Foo for S {
|
||||||
|
fn bar<T>(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn skip_index<A, Iter>(iter: Iter, index: usize) -> impl Iterator<Item = A>
|
||||||
|
where
|
||||||
|
Iter: Iterator<Item = A>,
|
||||||
|
{
|
||||||
|
iter.enumerate()
|
||||||
|
.filter_map(move |(i, a)| if i == index { None } else { Some(a) })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
59
tests/ui/extra_unused_type_parameters.stderr
Normal file
59
tests/ui/extra_unused_type_parameters.stderr
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
error: type parameter goes unused in function definition
|
||||||
|
--> $DIR/extra_unused_type_parameters.rs:4:13
|
||||||
|
|
|
||||||
|
LL | fn unused_ty<T>(x: u8) {}
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
= help: consider removing the parameter
|
||||||
|
= note: `-D clippy::extra-unused-type-parameters` implied by `-D warnings`
|
||||||
|
|
||||||
|
error: type parameters go unused in function definition
|
||||||
|
--> $DIR/extra_unused_type_parameters.rs:6:16
|
||||||
|
|
|
||||||
|
LL | fn unused_multi<T, U>(x: u8) {}
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= help: consider removing the parameters
|
||||||
|
|
||||||
|
error: type parameter goes unused in function definition
|
||||||
|
--> $DIR/extra_unused_type_parameters.rs:8:23
|
||||||
|
|
|
||||||
|
LL | fn unused_with_lt<'a, T>(x: &'a u8) {}
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= help: consider removing the parameter
|
||||||
|
|
||||||
|
error: type parameter goes unused in function definition
|
||||||
|
--> $DIR/extra_unused_type_parameters.rs:18:19
|
||||||
|
|
|
||||||
|
LL | fn unused_bounded<T: Default, U>(x: U) {}
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: consider removing the parameter
|
||||||
|
|
||||||
|
error: type parameter goes unused in function definition
|
||||||
|
--> $DIR/extra_unused_type_parameters.rs:20:24
|
||||||
|
|
|
||||||
|
LL | fn unused_where_clause<T, U>(x: U)
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= help: consider removing the parameter
|
||||||
|
|
||||||
|
error: type parameters go unused in function definition
|
||||||
|
--> $DIR/extra_unused_type_parameters.rs:26:16
|
||||||
|
|
|
||||||
|
LL | fn some_unused<A, B, C, D: Iterator<Item = (B, C)>, E>(b: B, c: C) {}
|
||||||
|
| ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^
|
||||||
|
|
|
||||||
|
= help: consider removing the parameters
|
||||||
|
|
||||||
|
error: type parameter goes unused in function definition
|
||||||
|
--> $DIR/extra_unused_type_parameters.rs:49:22
|
||||||
|
|
|
||||||
|
LL | fn unused_ty_impl<T>(&self) {}
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
= help: consider removing the parameter
|
||||||
|
|
||||||
|
error: aborting due to 7 previous errors
|
||||||
|
|
|
@ -282,4 +282,50 @@ impl AsyncLen {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// issue #9520
|
||||||
|
pub struct NonStandardLenAndIsEmptySignature;
|
||||||
|
impl NonStandardLenAndIsEmptySignature {
|
||||||
|
// don't lint
|
||||||
|
pub fn len(&self, something: usize) -> usize {
|
||||||
|
something
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_empty(&self, something: usize) -> bool {
|
||||||
|
something == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test case for #9520 with generics in the function signature
|
||||||
|
pub trait TestResource {
|
||||||
|
type NonStandardSignatureWithGenerics: Copy;
|
||||||
|
fn lookup_content(&self, item: Self::NonStandardSignatureWithGenerics) -> Result<Option<&[u8]>, String>;
|
||||||
|
}
|
||||||
|
pub struct NonStandardSignatureWithGenerics(u32);
|
||||||
|
impl NonStandardSignatureWithGenerics {
|
||||||
|
pub fn is_empty<T, U>(self, resource: &T) -> bool
|
||||||
|
where
|
||||||
|
T: TestResource<NonStandardSignatureWithGenerics = U>,
|
||||||
|
U: Copy + From<NonStandardSignatureWithGenerics>,
|
||||||
|
{
|
||||||
|
if let Ok(Some(content)) = resource.lookup_content(self.into()) {
|
||||||
|
content.is_empty()
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test case for #9520 with generics in the function signature
|
||||||
|
pub fn len<T, U>(self, resource: &T) -> usize
|
||||||
|
where
|
||||||
|
T: TestResource<NonStandardSignatureWithGenerics = U>,
|
||||||
|
U: Copy + From<NonStandardSignatureWithGenerics>,
|
||||||
|
{
|
||||||
|
if let Ok(Some(content)) = resource.lookup_content(self.into()) {
|
||||||
|
content.len()
|
||||||
|
} else {
|
||||||
|
0_usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -29,9 +29,7 @@ fn main() {
|
||||||
panic!("qaqaq{:?}", a);
|
panic!("qaqaq{:?}", a);
|
||||||
}
|
}
|
||||||
assert!(a.is_empty(), "qaqaq{:?}", a);
|
assert!(a.is_empty(), "qaqaq{:?}", a);
|
||||||
if !a.is_empty() {
|
assert!(a.is_empty(), "qwqwq");
|
||||||
panic!("qwqwq");
|
|
||||||
}
|
|
||||||
if a.len() == 3 {
|
if a.len() == 3 {
|
||||||
println!("qwq");
|
println!("qwq");
|
||||||
println!("qwq");
|
println!("qwq");
|
||||||
|
@ -46,21 +44,11 @@ fn main() {
|
||||||
println!("qwq");
|
println!("qwq");
|
||||||
}
|
}
|
||||||
let b = vec![1, 2, 3];
|
let b = vec![1, 2, 3];
|
||||||
if b.is_empty() {
|
assert!(!b.is_empty(), "panic1");
|
||||||
panic!("panic1");
|
assert!(!(b.is_empty() && a.is_empty()), "panic2");
|
||||||
}
|
assert!(!(a.is_empty() && !b.is_empty()), "panic3");
|
||||||
if b.is_empty() && a.is_empty() {
|
assert!(!(b.is_empty() || a.is_empty()), "panic4");
|
||||||
panic!("panic2");
|
assert!(!(a.is_empty() || !b.is_empty()), "panic5");
|
||||||
}
|
|
||||||
if a.is_empty() && !b.is_empty() {
|
|
||||||
panic!("panic3");
|
|
||||||
}
|
|
||||||
if b.is_empty() || a.is_empty() {
|
|
||||||
panic!("panic4");
|
|
||||||
}
|
|
||||||
if a.is_empty() || !b.is_empty() {
|
|
||||||
panic!("panic5");
|
|
||||||
}
|
|
||||||
assert!(!a.is_empty(), "with expansion {}", one!());
|
assert!(!a.is_empty(), "with expansion {}", one!());
|
||||||
if a.is_empty() {
|
if a.is_empty() {
|
||||||
let _ = 0;
|
let _ = 0;
|
||||||
|
@ -71,12 +59,11 @@ fn main() {
|
||||||
|
|
||||||
fn issue7730(a: u8) {
|
fn issue7730(a: u8) {
|
||||||
// Suggestion should preserve comment
|
// Suggestion should preserve comment
|
||||||
if a > 2 {
|
// comment
|
||||||
// comment
|
/* this is a
|
||||||
/* this is a
|
|
||||||
multiline
|
multiline
|
||||||
comment */
|
comment */
|
||||||
/// Doc comment
|
/// Doc comment
|
||||||
panic!("panic with comment") // comment after `panic!`
|
// comment after `panic!`
|
||||||
}
|
assert!(!(a > 2), "panic with comment");
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,54 @@ LL | | }
|
||||||
|
|
|
|
||||||
= note: `-D clippy::manual-assert` implied by `-D warnings`
|
= note: `-D clippy::manual-assert` implied by `-D warnings`
|
||||||
|
|
||||||
|
error: only a `panic!` in `if`-then statement
|
||||||
|
--> $DIR/manual_assert.rs:34:5
|
||||||
|
|
|
||||||
|
LL | / if !a.is_empty() {
|
||||||
|
LL | | panic!("qwqwq");
|
||||||
|
LL | | }
|
||||||
|
| |_____^ help: try instead: `assert!(a.is_empty(), "qwqwq");`
|
||||||
|
|
||||||
|
error: only a `panic!` in `if`-then statement
|
||||||
|
--> $DIR/manual_assert.rs:51:5
|
||||||
|
|
|
||||||
|
LL | / if b.is_empty() {
|
||||||
|
LL | | panic!("panic1");
|
||||||
|
LL | | }
|
||||||
|
| |_____^ help: try instead: `assert!(!b.is_empty(), "panic1");`
|
||||||
|
|
||||||
|
error: only a `panic!` in `if`-then statement
|
||||||
|
--> $DIR/manual_assert.rs:54:5
|
||||||
|
|
|
||||||
|
LL | / if b.is_empty() && a.is_empty() {
|
||||||
|
LL | | panic!("panic2");
|
||||||
|
LL | | }
|
||||||
|
| |_____^ help: try instead: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
|
||||||
|
|
||||||
|
error: only a `panic!` in `if`-then statement
|
||||||
|
--> $DIR/manual_assert.rs:57:5
|
||||||
|
|
|
||||||
|
LL | / if a.is_empty() && !b.is_empty() {
|
||||||
|
LL | | panic!("panic3");
|
||||||
|
LL | | }
|
||||||
|
| |_____^ help: try instead: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
|
||||||
|
|
||||||
|
error: only a `panic!` in `if`-then statement
|
||||||
|
--> $DIR/manual_assert.rs:60:5
|
||||||
|
|
|
||||||
|
LL | / if b.is_empty() || a.is_empty() {
|
||||||
|
LL | | panic!("panic4");
|
||||||
|
LL | | }
|
||||||
|
| |_____^ help: try instead: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
|
||||||
|
|
||||||
|
error: only a `panic!` in `if`-then statement
|
||||||
|
--> $DIR/manual_assert.rs:63:5
|
||||||
|
|
|
||||||
|
LL | / if a.is_empty() || !b.is_empty() {
|
||||||
|
LL | | panic!("panic5");
|
||||||
|
LL | | }
|
||||||
|
| |_____^ help: try instead: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
|
||||||
|
|
||||||
error: only a `panic!` in `if`-then statement
|
error: only a `panic!` in `if`-then statement
|
||||||
--> $DIR/manual_assert.rs:66:5
|
--> $DIR/manual_assert.rs:66:5
|
||||||
|
|
|
|
||||||
|
@ -16,5 +64,22 @@ LL | | panic!("with expansion {}", one!())
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());`
|
| |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: only a `panic!` in `if`-then statement
|
||||||
|
--> $DIR/manual_assert.rs:78:5
|
||||||
|
|
|
||||||
|
LL | / if a > 2 {
|
||||||
|
LL | | // comment
|
||||||
|
LL | | /* this is a
|
||||||
|
LL | | multiline
|
||||||
|
... |
|
||||||
|
LL | | panic!("panic with comment") // comment after `panic!`
|
||||||
|
LL | | }
|
||||||
|
| |_____^
|
||||||
|
|
|
||||||
|
help: try instead
|
||||||
|
|
|
||||||
|
LL | assert!(!(a > 2), "panic with comment");
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 9 previous errors
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,7 @@ fn main() {
|
||||||
Enum::A => (),
|
Enum::A => (),
|
||||||
Enum::B => (),
|
Enum::B => (),
|
||||||
Enum::C => (),
|
Enum::C => (),
|
||||||
_ => (),
|
Enum::__Private => (),
|
||||||
}
|
}
|
||||||
match Enum::A {
|
match Enum::A {
|
||||||
Enum::A => (),
|
Enum::A => (),
|
||||||
|
|
|
@ -48,11 +48,17 @@ error: wildcard matches only a single variant and will also match any future add
|
||||||
LL | _ => (),
|
LL | _ => (),
|
||||||
| ^ help: try this: `Color::Blue`
|
| ^ help: try this: `Color::Blue`
|
||||||
|
|
||||||
|
error: wildcard matches only a single variant and will also match any future added variants
|
||||||
|
--> $DIR/match_wildcard_for_single_variants.rs:126:13
|
||||||
|
|
|
||||||
|
LL | _ => (),
|
||||||
|
| ^ help: try this: `Enum::__Private`
|
||||||
|
|
||||||
error: wildcard matches only a single variant and will also match any future added variants
|
error: wildcard matches only a single variant and will also match any future added variants
|
||||||
--> $DIR/match_wildcard_for_single_variants.rs:153:13
|
--> $DIR/match_wildcard_for_single_variants.rs:153:13
|
||||||
|
|
|
|
||||||
LL | _ => 2,
|
LL | _ => 2,
|
||||||
| ^ help: try this: `Foo::B`
|
| ^ help: try this: `Foo::B`
|
||||||
|
|
||||||
error: aborting due to 9 previous errors
|
error: aborting due to 10 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
|
// aux-build:macro_rules.rs
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
#![allow(deref_nullptr)]
|
#![allow(deref_nullptr)]
|
||||||
#![allow(clippy::unnecessary_operation)]
|
#![allow(clippy::unnecessary_operation)]
|
||||||
#![allow(clippy::drop_copy)]
|
#![allow(clippy::drop_copy)]
|
||||||
#![warn(clippy::multiple_unsafe_ops_per_block)]
|
#![warn(clippy::multiple_unsafe_ops_per_block)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate macro_rules;
|
||||||
|
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
|
|
||||||
fn raw_ptr() -> *const () {
|
fn raw_ptr() -> *const () {
|
||||||
|
@ -107,4 +111,9 @@ unsafe fn read_char_good(ptr: *const u8) -> char {
|
||||||
unsafe { core::char::from_u32_unchecked(int_value) }
|
unsafe { core::char::from_u32_unchecked(int_value) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// no lint
|
||||||
|
fn issue10259() {
|
||||||
|
unsafe_macro!();
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:32:5
|
--> $DIR/multiple_unsafe_ops_per_block.rs:36:5
|
||||||
|
|
|
|
||||||
LL | / unsafe {
|
LL | / unsafe {
|
||||||
LL | | STATIC += 1;
|
LL | | STATIC += 1;
|
||||||
|
@ -8,19 +8,19 @@ LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
note: modification of a mutable static occurs here
|
note: modification of a mutable static occurs here
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:33:9
|
--> $DIR/multiple_unsafe_ops_per_block.rs:37:9
|
||||||
|
|
|
|
||||||
LL | STATIC += 1;
|
LL | STATIC += 1;
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
note: unsafe function call occurs here
|
note: unsafe function call occurs here
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:34:9
|
--> $DIR/multiple_unsafe_ops_per_block.rs:38:9
|
||||||
|
|
|
|
||||||
LL | not_very_safe();
|
LL | not_very_safe();
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
= note: `-D clippy::multiple-unsafe-ops-per-block` implied by `-D warnings`
|
= note: `-D clippy::multiple-unsafe-ops-per-block` implied by `-D warnings`
|
||||||
|
|
||||||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:41:5
|
--> $DIR/multiple_unsafe_ops_per_block.rs:45:5
|
||||||
|
|
|
|
||||||
LL | / unsafe {
|
LL | / unsafe {
|
||||||
LL | | drop(u.u);
|
LL | | drop(u.u);
|
||||||
|
@ -29,18 +29,18 @@ LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
note: union field access occurs here
|
note: union field access occurs here
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:42:14
|
--> $DIR/multiple_unsafe_ops_per_block.rs:46:14
|
||||||
|
|
|
|
||||||
LL | drop(u.u);
|
LL | drop(u.u);
|
||||||
| ^^^
|
| ^^^
|
||||||
note: raw pointer dereference occurs here
|
note: raw pointer dereference occurs here
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:43:9
|
--> $DIR/multiple_unsafe_ops_per_block.rs:47:9
|
||||||
|
|
|
|
||||||
LL | *raw_ptr();
|
LL | *raw_ptr();
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: this `unsafe` block contains 3 unsafe operations, expected only one
|
error: this `unsafe` block contains 3 unsafe operations, expected only one
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:48:5
|
--> $DIR/multiple_unsafe_ops_per_block.rs:52:5
|
||||||
|
|
|
|
||||||
LL | / unsafe {
|
LL | / unsafe {
|
||||||
LL | | asm!("nop");
|
LL | | asm!("nop");
|
||||||
|
@ -50,23 +50,23 @@ LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
note: inline assembly used here
|
note: inline assembly used here
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:49:9
|
--> $DIR/multiple_unsafe_ops_per_block.rs:53:9
|
||||||
|
|
|
|
||||||
LL | asm!("nop");
|
LL | asm!("nop");
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
note: unsafe method call occurs here
|
note: unsafe method call occurs here
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:50:9
|
--> $DIR/multiple_unsafe_ops_per_block.rs:54:9
|
||||||
|
|
|
|
||||||
LL | sample.not_very_safe();
|
LL | sample.not_very_safe();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: modification of a mutable static occurs here
|
note: modification of a mutable static occurs here
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:51:9
|
--> $DIR/multiple_unsafe_ops_per_block.rs:55:9
|
||||||
|
|
|
|
||||||
LL | STATIC = 0;
|
LL | STATIC = 0;
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: this `unsafe` block contains 6 unsafe operations, expected only one
|
error: this `unsafe` block contains 6 unsafe operations, expected only one
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:57:5
|
--> $DIR/multiple_unsafe_ops_per_block.rs:61:5
|
||||||
|
|
|
|
||||||
LL | / unsafe {
|
LL | / unsafe {
|
||||||
LL | | drop(u.u);
|
LL | | drop(u.u);
|
||||||
|
@ -78,49 +78,49 @@ LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
note: union field access occurs here
|
note: union field access occurs here
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:58:14
|
--> $DIR/multiple_unsafe_ops_per_block.rs:62:14
|
||||||
|
|
|
|
||||||
LL | drop(u.u);
|
LL | drop(u.u);
|
||||||
| ^^^
|
| ^^^
|
||||||
note: access of a mutable static occurs here
|
note: access of a mutable static occurs here
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:59:14
|
--> $DIR/multiple_unsafe_ops_per_block.rs:63:14
|
||||||
|
|
|
|
||||||
LL | drop(STATIC);
|
LL | drop(STATIC);
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
note: unsafe method call occurs here
|
note: unsafe method call occurs here
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:60:9
|
--> $DIR/multiple_unsafe_ops_per_block.rs:64:9
|
||||||
|
|
|
|
||||||
LL | sample.not_very_safe();
|
LL | sample.not_very_safe();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: unsafe function call occurs here
|
note: unsafe function call occurs here
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:61:9
|
--> $DIR/multiple_unsafe_ops_per_block.rs:65:9
|
||||||
|
|
|
|
||||||
LL | not_very_safe();
|
LL | not_very_safe();
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
note: raw pointer dereference occurs here
|
note: raw pointer dereference occurs here
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:62:9
|
--> $DIR/multiple_unsafe_ops_per_block.rs:66:9
|
||||||
|
|
|
|
||||||
LL | *raw_ptr();
|
LL | *raw_ptr();
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
note: inline assembly used here
|
note: inline assembly used here
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:63:9
|
--> $DIR/multiple_unsafe_ops_per_block.rs:67:9
|
||||||
|
|
|
|
||||||
LL | asm!("nop");
|
LL | asm!("nop");
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:101:5
|
--> $DIR/multiple_unsafe_ops_per_block.rs:105:5
|
||||||
|
|
|
|
||||||
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: unsafe function call occurs here
|
note: unsafe function call occurs here
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:101:14
|
--> $DIR/multiple_unsafe_ops_per_block.rs:105:14
|
||||||
|
|
|
|
||||||
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: raw pointer dereference occurs here
|
note: raw pointer dereference occurs here
|
||||||
--> $DIR/multiple_unsafe_ops_per_block.rs:101:39
|
--> $DIR/multiple_unsafe_ops_per_block.rs:105:39
|
||||||
|
|
|
|
||||||
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
538
tests/ui/needless_lifetimes.fixed
Normal file
538
tests/ui/needless_lifetimes.fixed
Normal file
|
@ -0,0 +1,538 @@
|
||||||
|
// run-rustfix
|
||||||
|
// aux-build:macro_rules.rs
|
||||||
|
|
||||||
|
#![warn(clippy::needless_lifetimes)]
|
||||||
|
#![allow(
|
||||||
|
unused,
|
||||||
|
clippy::boxed_local,
|
||||||
|
clippy::extra_unused_type_parameters,
|
||||||
|
clippy::needless_pass_by_value,
|
||||||
|
clippy::unnecessary_wraps,
|
||||||
|
dyn_drop,
|
||||||
|
clippy::get_first
|
||||||
|
)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate macro_rules;
|
||||||
|
|
||||||
|
fn distinct_lifetimes(_x: &u8, _y: &u8, _z: u8) {}
|
||||||
|
|
||||||
|
fn distinct_and_static(_x: &u8, _y: &u8, _z: &'static u8) {}
|
||||||
|
|
||||||
|
// No error; same lifetime on two params.
|
||||||
|
fn same_lifetime_on_input<'a>(_x: &'a u8, _y: &'a u8) {}
|
||||||
|
|
||||||
|
// No error; static involved.
|
||||||
|
fn only_static_on_input(_x: &u8, _y: &u8, _z: &'static u8) {}
|
||||||
|
|
||||||
|
fn mut_and_static_input(_x: &mut u8, _y: &'static str) {}
|
||||||
|
|
||||||
|
fn in_and_out(x: &u8, _y: u8) -> &u8 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
// No error; multiple input refs.
|
||||||
|
fn multiple_in_and_out_1<'a>(x: &'a u8, _y: &'a u8) -> &'a u8 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
|
||||||
|
// fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8
|
||||||
|
// ^^^
|
||||||
|
fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
|
||||||
|
// fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8
|
||||||
|
// ^^^
|
||||||
|
fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8 {
|
||||||
|
y
|
||||||
|
}
|
||||||
|
|
||||||
|
// No error; multiple input refs
|
||||||
|
async fn func<'a>(args: &[&'a str]) -> Option<&'a str> {
|
||||||
|
args.get(0).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
// No error; static involved.
|
||||||
|
fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
|
||||||
|
// fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()>
|
||||||
|
// ^^^
|
||||||
|
fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()> {
|
||||||
|
Ok(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
|
||||||
|
// fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()>
|
||||||
|
// ^^^
|
||||||
|
fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()> {
|
||||||
|
Ok(y)
|
||||||
|
}
|
||||||
|
|
||||||
|
// No error; two input refs.
|
||||||
|
fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 {
|
||||||
|
x.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deep_reference_3(x: &u8, _y: u8) -> Result<&u8, ()> {
|
||||||
|
Ok(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Where-clause, but without lifetimes.
|
||||||
|
fn where_clause_without_lt<T>(x: &u8, _y: u8) -> Result<&u8, ()>
|
||||||
|
where
|
||||||
|
T: Copy,
|
||||||
|
{
|
||||||
|
Ok(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Ref<'r> = &'r u8;
|
||||||
|
|
||||||
|
// No error; same lifetime on two params.
|
||||||
|
fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) {}
|
||||||
|
|
||||||
|
fn lifetime_param_2(_x: Ref<'_>, _y: &u8) {}
|
||||||
|
|
||||||
|
// No error; bounded lifetime.
|
||||||
|
fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) {}
|
||||||
|
|
||||||
|
// No error; bounded lifetime.
|
||||||
|
fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8)
|
||||||
|
where
|
||||||
|
'b: 'a,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Lt<'a, I: 'static> {
|
||||||
|
x: &'a I,
|
||||||
|
}
|
||||||
|
|
||||||
|
// No error; fn bound references `'a`.
|
||||||
|
fn fn_bound<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
|
||||||
|
where
|
||||||
|
F: Fn(Lt<'a, I>) -> Lt<'a, I>,
|
||||||
|
{
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fn_bound_2<F, I>(_m: Lt<'_, I>, _f: F) -> Lt<'_, I>
|
||||||
|
where
|
||||||
|
for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>,
|
||||||
|
{
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// No error; see below.
|
||||||
|
fn fn_bound_3<'a, F: FnOnce(&'a i32)>(x: &'a i32, f: F) {
|
||||||
|
f(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fn_bound_3_cannot_elide() {
|
||||||
|
let x = 42;
|
||||||
|
let p = &x;
|
||||||
|
let mut q = &x;
|
||||||
|
// This will fail if we elide lifetimes of `fn_bound_3`.
|
||||||
|
fn_bound_3(p, |y| q = y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No error; multiple input refs.
|
||||||
|
fn fn_bound_4<'a, F: FnOnce() -> &'a ()>(cond: bool, x: &'a (), f: F) -> &'a () {
|
||||||
|
if cond { x } else { f() }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct X {
|
||||||
|
x: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl X {
|
||||||
|
fn self_and_out(&self) -> &u8 {
|
||||||
|
&self.x
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
|
||||||
|
// fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8
|
||||||
|
// ^^^
|
||||||
|
fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8 {
|
||||||
|
&self.x
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
|
||||||
|
// fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8
|
||||||
|
// ^^^^^
|
||||||
|
fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn distinct_self_and_in(&self, _x: &u8) {}
|
||||||
|
|
||||||
|
// No error; same lifetimes on two params.
|
||||||
|
fn self_and_same_in<'s>(&'s self, _x: &'s u8) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo<'a>(&'a u8);
|
||||||
|
|
||||||
|
impl<'a> Foo<'a> {
|
||||||
|
// No error; lifetime `'a` not defined in method.
|
||||||
|
fn self_shared_lifetime(&self, _: &'a u8) {}
|
||||||
|
// No error; bounds exist.
|
||||||
|
fn self_bound_lifetime<'b: 'a>(&self, _: &'b u8) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn already_elided<'a>(_: &u8, _: &'a u8) -> &'a u8 {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn struct_with_lt(_foo: Foo<'_>) -> &str {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// No warning; two input lifetimes (named on the reference, anonymous on `Foo`).
|
||||||
|
fn struct_with_lt2<'a>(_foo: &'a Foo) -> &'a str {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// No warning; two input lifetimes (anonymous on the reference, named on `Foo`).
|
||||||
|
fn struct_with_lt3<'a>(_foo: &Foo<'a>) -> &'a str {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
|
||||||
|
// valid:
|
||||||
|
// fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str
|
||||||
|
// ^^
|
||||||
|
fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
|
||||||
|
// valid:
|
||||||
|
// fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str
|
||||||
|
// ^^^^
|
||||||
|
fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
trait WithLifetime<'a> {}
|
||||||
|
|
||||||
|
type WithLifetimeAlias<'a> = dyn WithLifetime<'a>;
|
||||||
|
|
||||||
|
// Should not warn because it won't build without the lifetime.
|
||||||
|
fn trait_obj_elided<'a>(_arg: &'a dyn WithLifetime) -> &'a str {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should warn because there is no lifetime on `Drop`, so this would be
|
||||||
|
// unambiguous if we elided the lifetime.
|
||||||
|
fn trait_obj_elided2(_arg: &dyn Drop) -> &str {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooAlias<'a> = Foo<'a>;
|
||||||
|
|
||||||
|
fn alias_with_lt(_foo: FooAlias<'_>) -> &str {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// No warning; two input lifetimes (named on the reference, anonymous on `FooAlias`).
|
||||||
|
fn alias_with_lt2<'a>(_foo: &'a FooAlias) -> &'a str {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// No warning; two input lifetimes (anonymous on the reference, named on `FooAlias`).
|
||||||
|
fn alias_with_lt3<'a>(_foo: &FooAlias<'a>) -> &'a str {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
|
||||||
|
// valid:
|
||||||
|
// fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str
|
||||||
|
// ^^
|
||||||
|
fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
|
||||||
|
// valid:
|
||||||
|
// fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str
|
||||||
|
// ^^^^^^^^^
|
||||||
|
fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn named_input_elided_output(_arg: &str) -> &str {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn elided_input_named_output<'a>(_arg: &str) -> &'a str {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn trait_bound_ok<T: WithLifetime<'static>>(_: &u8, _: T) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
fn trait_bound<'a, T: WithLifetime<'a>>(_: &'a u8, _: T) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't warn on these; see issue #292.
|
||||||
|
fn trait_bound_bug<'a, T: WithLifetime<'a>>() {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// See issue #740.
|
||||||
|
struct Test {
|
||||||
|
vec: Vec<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Test {
|
||||||
|
fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = usize> + 'a> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait LintContext<'a> {}
|
||||||
|
|
||||||
|
fn f<'a, T: LintContext<'a>>(_: &T) {}
|
||||||
|
|
||||||
|
fn test<'a>(x: &'a [u8]) -> u8 {
|
||||||
|
let y: &'a u8 = &x[5];
|
||||||
|
*y
|
||||||
|
}
|
||||||
|
|
||||||
|
// Issue #3284: give hint regarding lifetime in return type.
|
||||||
|
struct Cow<'a> {
|
||||||
|
x: &'a str,
|
||||||
|
}
|
||||||
|
fn out_return_type_lts(e: &str) -> Cow<'_> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we still warn on implementations
|
||||||
|
mod issue4291 {
|
||||||
|
trait BadTrait {
|
||||||
|
fn needless_lt(x: &u8) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BadTrait for () {
|
||||||
|
fn needless_lt(_x: &u8) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod issue2944 {
|
||||||
|
trait Foo {}
|
||||||
|
struct Bar;
|
||||||
|
struct Baz<'a> {
|
||||||
|
bar: &'a Bar,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Foo for Baz<'a> {}
|
||||||
|
impl Bar {
|
||||||
|
fn baz(&self) -> impl Foo + '_ {
|
||||||
|
Baz { bar: self }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod nested_elision_sites {
|
||||||
|
// issue #issue2944
|
||||||
|
|
||||||
|
// closure trait bounds subject to nested elision
|
||||||
|
// don't lint because they refer to outer lifetimes
|
||||||
|
fn trait_fn<'a>(i: &'a i32) -> impl Fn() -> &'a i32 {
|
||||||
|
move || i
|
||||||
|
}
|
||||||
|
fn trait_fn_mut<'a>(i: &'a i32) -> impl FnMut() -> &'a i32 {
|
||||||
|
move || i
|
||||||
|
}
|
||||||
|
fn trait_fn_once<'a>(i: &'a i32) -> impl FnOnce() -> &'a i32 {
|
||||||
|
move || i
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't lint
|
||||||
|
fn impl_trait_in_input_position<'a>(f: impl Fn() -> &'a i32) -> &'a i32 {
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
fn impl_trait_in_output_position<'a>(i: &'a i32) -> impl Fn() -> &'a i32 {
|
||||||
|
move || i
|
||||||
|
}
|
||||||
|
// lint
|
||||||
|
fn impl_trait_elidable_nested_named_lifetimes<'a>(i: &'a i32, f: impl for<'b> Fn(&'b i32) -> &'b i32) -> &'a i32 {
|
||||||
|
f(i)
|
||||||
|
}
|
||||||
|
fn impl_trait_elidable_nested_anonymous_lifetimes(i: &i32, f: impl Fn(&i32) -> &i32) -> &i32 {
|
||||||
|
f(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't lint
|
||||||
|
fn generics_not_elidable<'a, T: Fn() -> &'a i32>(f: T) -> &'a i32 {
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
// lint
|
||||||
|
fn generics_elidable<T: Fn(&i32) -> &i32>(i: &i32, f: T) -> &i32 {
|
||||||
|
f(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't lint
|
||||||
|
fn where_clause_not_elidable<'a, T>(f: T) -> &'a i32
|
||||||
|
where
|
||||||
|
T: Fn() -> &'a i32,
|
||||||
|
{
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
// lint
|
||||||
|
fn where_clause_elidadable<T>(i: &i32, f: T) -> &i32
|
||||||
|
where
|
||||||
|
T: Fn(&i32) -> &i32,
|
||||||
|
{
|
||||||
|
f(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't lint
|
||||||
|
fn pointer_fn_in_input_position<'a>(f: fn(&'a i32) -> &'a i32, i: &'a i32) -> &'a i32 {
|
||||||
|
f(i)
|
||||||
|
}
|
||||||
|
fn pointer_fn_in_output_position<'a>(_: &'a i32) -> fn(&'a i32) -> &'a i32 {
|
||||||
|
|i| i
|
||||||
|
}
|
||||||
|
// lint
|
||||||
|
fn pointer_fn_elidable(i: &i32, f: fn(&i32) -> &i32) -> &i32 {
|
||||||
|
f(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't lint
|
||||||
|
fn nested_fn_pointer_1<'a>(_: &'a i32) -> fn(fn(&'a i32) -> &'a i32) -> i32 {
|
||||||
|
|f| 42
|
||||||
|
}
|
||||||
|
fn nested_fn_pointer_2<'a>(_: &'a i32) -> impl Fn(fn(&'a i32)) {
|
||||||
|
|f| ()
|
||||||
|
}
|
||||||
|
|
||||||
|
// lint
|
||||||
|
fn nested_fn_pointer_3(_: &i32) -> fn(fn(&i32) -> &i32) -> i32 {
|
||||||
|
|f| 42
|
||||||
|
}
|
||||||
|
fn nested_fn_pointer_4(_: &i32) -> impl Fn(fn(&i32)) {
|
||||||
|
|f| ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod issue6159 {
|
||||||
|
use std::ops::Deref;
|
||||||
|
pub fn apply_deref<'a, T, F, R>(x: &'a T, f: F) -> R
|
||||||
|
where
|
||||||
|
T: Deref,
|
||||||
|
F: FnOnce(&'a T::Target) -> R,
|
||||||
|
{
|
||||||
|
f(x.deref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod issue7296 {
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
impl Foo {
|
||||||
|
fn implicit(&self) -> &() {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
fn implicit_mut(&mut self) -> &() {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn explicit<'a>(self: &'a Arc<Self>) -> &'a () {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
fn explicit_mut<'a>(self: &'a mut Rc<Self>) -> &'a () {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &() {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Bar {
|
||||||
|
fn implicit(&self) -> &();
|
||||||
|
fn implicit_provided(&self) -> &() {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn explicit<'a>(self: &'a Arc<Self>) -> &'a ();
|
||||||
|
fn explicit_provided<'a>(self: &'a Arc<Self>) -> &'a () {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &();
|
||||||
|
fn lifetime_elsewhere_provided(self: Box<Self>, here: &()) -> &() {
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod pr_9743_false_negative_fix {
|
||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
|
fn foo(x: &u8, y: &'_ u8) {}
|
||||||
|
|
||||||
|
fn bar(x: &u8, y: &'_ u8, z: &'_ u8) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod pr_9743_output_lifetime_checks {
|
||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
|
// lint: only one input
|
||||||
|
fn one_input(x: &u8) -> &u8 {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// lint: multiple inputs, output would not be elided
|
||||||
|
fn multiple_inputs_output_not_elided<'b>(x: &u8, y: &'b u8, z: &'b u8) -> &'b u8 {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't lint: multiple inputs, output would be elided (which would create an ambiguity)
|
||||||
|
fn multiple_inputs_output_would_be_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'a u8 {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod in_macro {
|
||||||
|
macro_rules! local_one_input_macro {
|
||||||
|
() => {
|
||||||
|
fn one_input(x: &u8) -> &u8 {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// lint local macro expands to function with needless lifetimes
|
||||||
|
local_one_input_macro!();
|
||||||
|
|
||||||
|
// no lint on external macro
|
||||||
|
macro_rules::needless_lifetime!();
|
||||||
|
}
|
||||||
|
|
||||||
|
mod issue5787 {
|
||||||
|
use std::sync::MutexGuard;
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
// doesn't get linted without async
|
||||||
|
pub async fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> MutexGuard<'a, T> {
|
||||||
|
guard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn foo<'a>(_x: &i32, y: &'a str) -> &'a str {
|
||||||
|
y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -1,13 +1,20 @@
|
||||||
|
// run-rustfix
|
||||||
|
// aux-build:macro_rules.rs
|
||||||
|
|
||||||
#![warn(clippy::needless_lifetimes)]
|
#![warn(clippy::needless_lifetimes)]
|
||||||
#![allow(
|
#![allow(
|
||||||
dead_code,
|
unused,
|
||||||
clippy::boxed_local,
|
clippy::boxed_local,
|
||||||
|
clippy::extra_unused_type_parameters,
|
||||||
clippy::needless_pass_by_value,
|
clippy::needless_pass_by_value,
|
||||||
clippy::unnecessary_wraps,
|
clippy::unnecessary_wraps,
|
||||||
dyn_drop,
|
dyn_drop,
|
||||||
clippy::get_first
|
clippy::get_first
|
||||||
)]
|
)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate macro_rules;
|
||||||
|
|
||||||
fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
|
fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
|
||||||
|
|
||||||
fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
|
fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
|
||||||
|
@ -495,4 +502,37 @@ mod pr_9743_output_lifetime_checks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod in_macro {
|
||||||
|
macro_rules! local_one_input_macro {
|
||||||
|
() => {
|
||||||
|
fn one_input<'a>(x: &'a u8) -> &'a u8 {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// lint local macro expands to function with needless lifetimes
|
||||||
|
local_one_input_macro!();
|
||||||
|
|
||||||
|
// no lint on external macro
|
||||||
|
macro_rules::needless_lifetime!();
|
||||||
|
}
|
||||||
|
|
||||||
|
mod issue5787 {
|
||||||
|
use std::sync::MutexGuard;
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
// doesn't get linted without async
|
||||||
|
pub async fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> MutexGuard<'a, T> {
|
||||||
|
guard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn foo<'a>(_x: &i32, y: &'a str) -> &'a str {
|
||||||
|
y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,316 +1,559 @@
|
||||||
error: the following explicit lifetimes could be elided: 'a, 'b
|
error: the following explicit lifetimes could be elided: 'a, 'b
|
||||||
--> $DIR/needless_lifetimes.rs:11:1
|
--> $DIR/needless_lifetimes.rs:18:1
|
||||||
|
|
|
|
||||||
LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
|
LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: `-D clippy::needless-lifetimes` implied by `-D warnings`
|
= note: `-D clippy::needless-lifetimes` implied by `-D warnings`
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
|
||||||
|
LL + fn distinct_lifetimes(_x: &u8, _y: &u8, _z: u8) {}
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a, 'b
|
error: the following explicit lifetimes could be elided: 'a, 'b
|
||||||
--> $DIR/needless_lifetimes.rs:13:1
|
--> $DIR/needless_lifetimes.rs:20:1
|
||||||
|
|
|
|
||||||
LL | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
|
LL | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
|
||||||
|
LL + fn distinct_and_static(_x: &u8, _y: &u8, _z: &'static u8) {}
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:23:1
|
--> $DIR/needless_lifetimes.rs:30:1
|
||||||
|
|
|
|
||||||
LL | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
|
LL | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
|
||||||
|
LL + fn in_and_out(x: &u8, _y: u8) -> &u8 {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'b
|
error: the following explicit lifetimes could be elided: 'b
|
||||||
--> $DIR/needless_lifetimes.rs:35:1
|
--> $DIR/needless_lifetimes.rs:42:1
|
||||||
|
|
|
|
||||||
LL | fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
|
LL | fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
|
||||||
|
LL + fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8 {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:42:1
|
--> $DIR/needless_lifetimes.rs:49:1
|
||||||
|
|
|
|
||||||
LL | fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 {
|
LL | fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 {
|
||||||
|
LL + fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8 {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'b
|
error: the following explicit lifetimes could be elided: 'b
|
||||||
--> $DIR/needless_lifetimes.rs:59:1
|
--> $DIR/needless_lifetimes.rs:66:1
|
||||||
|
|
|
|
||||||
LL | fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
|
LL | fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
|
||||||
|
LL + fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()> {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:66:1
|
--> $DIR/needless_lifetimes.rs:73:1
|
||||||
|
|
|
|
||||||
LL | fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> {
|
LL | fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> {
|
||||||
|
LL + fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()> {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:75:1
|
--> $DIR/needless_lifetimes.rs:82:1
|
||||||
|
|
|
|
||||||
LL | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
|
LL | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
|
||||||
|
LL + fn deep_reference_3(x: &u8, _y: u8) -> Result<&u8, ()> {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:80:1
|
--> $DIR/needless_lifetimes.rs:87:1
|
||||||
|
|
|
|
||||||
LL | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
|
LL | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
|
||||||
|
LL + fn where_clause_without_lt<T>(x: &u8, _y: u8) -> Result<&u8, ()>
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a, 'b
|
error: the following explicit lifetimes could be elided: 'a, 'b
|
||||||
--> $DIR/needless_lifetimes.rs:92:1
|
--> $DIR/needless_lifetimes.rs:99:1
|
||||||
|
|
|
|
||||||
LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
|
LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: replace with `'_` in generic arguments such as here
|
help: elide the lifetimes
|
||||||
--> $DIR/needless_lifetimes.rs:92:37
|
|
|
||||||
|
LL - fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
|
||||||
|
LL + fn lifetime_param_2(_x: Ref<'_>, _y: &u8) {}
|
||||||
|
|
|
|
||||||
LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
|
|
||||||
| ^^
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:116:1
|
--> $DIR/needless_lifetimes.rs:123:1
|
||||||
|
|
|
|
||||||
LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
|
LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: replace with `'_` in generic arguments such as here
|
help: elide the lifetimes
|
||||||
--> $DIR/needless_lifetimes.rs:116:32
|
|
|
||||||
|
LL - fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
|
||||||
|
LL + fn fn_bound_2<F, I>(_m: Lt<'_, I>, _f: F) -> Lt<'_, I>
|
||||||
|
|
|
|
||||||
LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
|
|
||||||
| ^^
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 's
|
error: the following explicit lifetimes could be elided: 's
|
||||||
--> $DIR/needless_lifetimes.rs:146:5
|
--> $DIR/needless_lifetimes.rs:153:5
|
||||||
|
|
|
|
||||||
LL | fn self_and_out<'s>(&'s self) -> &'s u8 {
|
LL | fn self_and_out<'s>(&'s self) -> &'s u8 {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn self_and_out<'s>(&'s self) -> &'s u8 {
|
||||||
|
LL + fn self_and_out(&self) -> &u8 {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 't
|
error: the following explicit lifetimes could be elided: 't
|
||||||
--> $DIR/needless_lifetimes.rs:153:5
|
--> $DIR/needless_lifetimes.rs:160:5
|
||||||
|
|
|
|
||||||
LL | fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
|
LL | fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
|
||||||
|
LL + fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8 {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 's
|
error: the following explicit lifetimes could be elided: 's
|
||||||
--> $DIR/needless_lifetimes.rs:160:5
|
--> $DIR/needless_lifetimes.rs:167:5
|
||||||
|
|
|
|
||||||
LL | fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 {
|
LL | fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 {
|
||||||
|
LL + fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8 {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 's, 't
|
error: the following explicit lifetimes could be elided: 's, 't
|
||||||
--> $DIR/needless_lifetimes.rs:164:5
|
--> $DIR/needless_lifetimes.rs:171:5
|
||||||
|
|
|
|
||||||
LL | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
|
LL | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
|
||||||
|
LL + fn distinct_self_and_in(&self, _x: &u8) {}
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:183:1
|
--> $DIR/needless_lifetimes.rs:190:1
|
||||||
|
|
|
|
||||||
LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
|
LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: replace with `'_` in generic arguments such as here
|
help: elide the lifetimes
|
||||||
--> $DIR/needless_lifetimes.rs:183:33
|
|
|
||||||
|
LL - fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
|
||||||
|
LL + fn struct_with_lt(_foo: Foo<'_>) -> &str {
|
||||||
|
|
|
|
||||||
LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
|
|
||||||
| ^^
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'b
|
error: the following explicit lifetimes could be elided: 'b
|
||||||
--> $DIR/needless_lifetimes.rs:201:1
|
--> $DIR/needless_lifetimes.rs:208:1
|
||||||
|
|
|
|
||||||
LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
|
LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: replace with `'_` in generic arguments such as here
|
help: elide the lifetimes
|
||||||
--> $DIR/needless_lifetimes.rs:201:43
|
|
|
||||||
|
LL - fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
|
||||||
|
LL + fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str {
|
||||||
|
|
|
|
||||||
LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
|
|
||||||
| ^^
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:209:1
|
--> $DIR/needless_lifetimes.rs:216:1
|
||||||
|
|
|
|
||||||
LL | fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str {
|
LL | fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str {
|
||||||
|
LL + fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:224:1
|
--> $DIR/needless_lifetimes.rs:231:1
|
||||||
|
|
|
|
||||||
LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
|
LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
|
||||||
|
LL + fn trait_obj_elided2(_arg: &dyn Drop) -> &str {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:230:1
|
--> $DIR/needless_lifetimes.rs:237:1
|
||||||
|
|
|
|
||||||
LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
|
LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: replace with `'_` in generic arguments such as here
|
help: elide the lifetimes
|
||||||
--> $DIR/needless_lifetimes.rs:230:37
|
|
|
||||||
|
LL - fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
|
||||||
|
LL + fn alias_with_lt(_foo: FooAlias<'_>) -> &str {
|
||||||
|
|
|
|
||||||
LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
|
|
||||||
| ^^
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'b
|
error: the following explicit lifetimes could be elided: 'b
|
||||||
--> $DIR/needless_lifetimes.rs:248:1
|
--> $DIR/needless_lifetimes.rs:255:1
|
||||||
|
|
|
|
||||||
LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
|
LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: replace with `'_` in generic arguments such as here
|
help: elide the lifetimes
|
||||||
--> $DIR/needless_lifetimes.rs:248:47
|
|
|
||||||
|
LL - fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
|
||||||
|
LL + fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str {
|
||||||
|
|
|
|
||||||
LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
|
|
||||||
| ^^
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:256:1
|
--> $DIR/needless_lifetimes.rs:263:1
|
||||||
|
|
|
|
||||||
LL | fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str {
|
LL | fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str {
|
||||||
|
LL + fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:260:1
|
--> $DIR/needless_lifetimes.rs:267:1
|
||||||
|
|
|
|
||||||
LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
|
LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
|
||||||
|
LL + fn named_input_elided_output(_arg: &str) -> &str {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:268:1
|
--> $DIR/needless_lifetimes.rs:275:1
|
||||||
|
|
|
|
||||||
LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
|
LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
|
||||||
|
LL + fn trait_bound_ok<T: WithLifetime<'static>>(_: &u8, _: T) {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:304:1
|
--> $DIR/needless_lifetimes.rs:311:1
|
||||||
|
|
|
|
||||||
LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
|
LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: replace with `'_` in generic arguments such as here
|
help: elide the lifetimes
|
||||||
--> $DIR/needless_lifetimes.rs:304:47
|
|
|
||||||
|
LL - fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
|
||||||
|
LL + fn out_return_type_lts(e: &str) -> Cow<'_> {
|
||||||
|
|
|
|
||||||
LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
|
|
||||||
| ^^
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:311:9
|
--> $DIR/needless_lifetimes.rs:318:9
|
||||||
|
|
|
|
||||||
LL | fn needless_lt<'a>(x: &'a u8) {}
|
LL | fn needless_lt<'a>(x: &'a u8) {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn needless_lt<'a>(x: &'a u8) {}
|
||||||
|
LL + fn needless_lt(x: &u8) {}
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:315:9
|
--> $DIR/needless_lifetimes.rs:322:9
|
||||||
|
|
|
|
||||||
LL | fn needless_lt<'a>(_x: &'a u8) {}
|
LL | fn needless_lt<'a>(_x: &'a u8) {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn needless_lt<'a>(_x: &'a u8) {}
|
||||||
|
LL + fn needless_lt(_x: &u8) {}
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:328:9
|
--> $DIR/needless_lifetimes.rs:335:9
|
||||||
|
|
|
|
||||||
LL | fn baz<'a>(&'a self) -> impl Foo + 'a {
|
LL | fn baz<'a>(&'a self) -> impl Foo + 'a {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn baz<'a>(&'a self) -> impl Foo + 'a {
|
||||||
|
LL + fn baz(&self) -> impl Foo + '_ {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:360:5
|
--> $DIR/needless_lifetimes.rs:367:5
|
||||||
|
|
|
|
||||||
LL | fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
|
LL | fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
|
||||||
|
LL + fn impl_trait_elidable_nested_anonymous_lifetimes(i: &i32, f: impl Fn(&i32) -> &i32) -> &i32 {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:369:5
|
--> $DIR/needless_lifetimes.rs:376:5
|
||||||
|
|
|
|
||||||
LL | fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
|
LL | fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
|
||||||
|
LL + fn generics_elidable<T: Fn(&i32) -> &i32>(i: &i32, f: T) -> &i32 {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:381:5
|
--> $DIR/needless_lifetimes.rs:388:5
|
||||||
|
|
|
|
||||||
LL | fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
|
LL | fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
|
||||||
|
LL + fn where_clause_elidadable<T>(i: &i32, f: T) -> &i32
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:396:5
|
--> $DIR/needless_lifetimes.rs:403:5
|
||||||
|
|
|
|
||||||
LL | fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
|
LL | fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
|
||||||
|
LL + fn pointer_fn_elidable(i: &i32, f: fn(&i32) -> &i32) -> &i32 {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:409:5
|
--> $DIR/needless_lifetimes.rs:416:5
|
||||||
|
|
|
|
||||||
LL | fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
|
LL | fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
|
||||||
|
LL + fn nested_fn_pointer_3(_: &i32) -> fn(fn(&i32) -> &i32) -> i32 {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:412:5
|
--> $DIR/needless_lifetimes.rs:419:5
|
||||||
|
|
|
|
||||||
LL | fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
|
LL | fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
|
||||||
|
LL + fn nested_fn_pointer_4(_: &i32) -> impl Fn(fn(&i32)) {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:434:9
|
--> $DIR/needless_lifetimes.rs:441:9
|
||||||
|
|
|
|
||||||
LL | fn implicit<'a>(&'a self) -> &'a () {
|
LL | fn implicit<'a>(&'a self) -> &'a () {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn implicit<'a>(&'a self) -> &'a () {
|
||||||
|
LL + fn implicit(&self) -> &() {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:437:9
|
--> $DIR/needless_lifetimes.rs:444:9
|
||||||
|
|
|
|
||||||
LL | fn implicit_mut<'a>(&'a mut self) -> &'a () {
|
LL | fn implicit_mut<'a>(&'a mut self) -> &'a () {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
|
||||||
--> $DIR/needless_lifetimes.rs:448:9
|
|
||||||
|
|
|
|
||||||
LL | fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
|
help: elide the lifetimes
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
||||||
|
LL - fn implicit_mut<'a>(&'a mut self) -> &'a () {
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
LL + fn implicit_mut(&mut self) -> &() {
|
||||||
--> $DIR/needless_lifetimes.rs:454:9
|
|
||||||
|
|
|
|
||||||
LL | fn implicit<'a>(&'a self) -> &'a ();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:455:9
|
--> $DIR/needless_lifetimes.rs:455:9
|
||||||
|
|
|
|
||||||
LL | fn implicit_provided<'a>(&'a self) -> &'a () {
|
LL | fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
|
||||||
|
LL + fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &() {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:464:9
|
--> $DIR/needless_lifetimes.rs:461:9
|
||||||
|
|
|
||||||
|
LL | fn implicit<'a>(&'a self) -> &'a ();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn implicit<'a>(&'a self) -> &'a ();
|
||||||
|
LL + fn implicit(&self) -> &();
|
||||||
|
|
|
||||||
|
|
||||||
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
|
--> $DIR/needless_lifetimes.rs:462:9
|
||||||
|
|
|
||||||
|
LL | fn implicit_provided<'a>(&'a self) -> &'a () {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn implicit_provided<'a>(&'a self) -> &'a () {
|
||||||
|
LL + fn implicit_provided(&self) -> &() {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
|
--> $DIR/needless_lifetimes.rs:471:9
|
||||||
|
|
|
|
||||||
LL | fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a ();
|
LL | fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a ();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a ();
|
||||||
|
LL + fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &();
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:465:9
|
--> $DIR/needless_lifetimes.rs:472:9
|
||||||
|
|
|
|
||||||
LL | fn lifetime_elsewhere_provided<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
|
LL | fn lifetime_elsewhere_provided<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn lifetime_elsewhere_provided<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
|
||||||
|
LL + fn lifetime_elsewhere_provided(self: Box<Self>, here: &()) -> &() {
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:474:5
|
--> $DIR/needless_lifetimes.rs:481:5
|
||||||
|
|
|
|
||||||
LL | fn foo<'a>(x: &'a u8, y: &'_ u8) {}
|
LL | fn foo<'a>(x: &'a u8, y: &'_ u8) {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
|
||||||
--> $DIR/needless_lifetimes.rs:476:5
|
|
||||||
|
|
|
|
||||||
LL | fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {}
|
help: elide the lifetimes
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
||||||
|
LL - fn foo<'a>(x: &'a u8, y: &'_ u8) {}
|
||||||
|
LL + fn foo(x: &u8, y: &'_ u8) {}
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:483:5
|
--> $DIR/needless_lifetimes.rs:483:5
|
||||||
|
|
|
|
||||||
LL | fn one_input<'a>(x: &'a u8) -> &'a u8 {
|
LL | fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {}
|
||||||
|
LL + fn bar(x: &u8, y: &'_ u8, z: &'_ u8) {}
|
||||||
|
|
|
||||||
|
|
||||||
error: the following explicit lifetimes could be elided: 'a
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
--> $DIR/needless_lifetimes.rs:488:5
|
--> $DIR/needless_lifetimes.rs:490:5
|
||||||
|
|
|
||||||
|
LL | fn one_input<'a>(x: &'a u8) -> &'a u8 {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn one_input<'a>(x: &'a u8) -> &'a u8 {
|
||||||
|
LL + fn one_input(x: &u8) -> &u8 {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
|
--> $DIR/needless_lifetimes.rs:495:5
|
||||||
|
|
|
|
||||||
LL | fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 {
|
LL | fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 {
|
||||||
|
LL + fn multiple_inputs_output_not_elided<'b>(x: &u8, y: &'b u8, z: &'b u8) -> &'b u8 {
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to 45 previous errors
|
error: the following explicit lifetimes could be elided: 'a
|
||||||
|
--> $DIR/needless_lifetimes.rs:508:13
|
||||||
|
|
|
||||||
|
LL | fn one_input<'a>(x: &'a u8) -> &'a u8 {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
...
|
||||||
|
LL | local_one_input_macro!();
|
||||||
|
| ------------------------ in this macro invocation
|
||||||
|
|
|
||||||
|
= note: this error originates in the macro `local_one_input_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
help: elide the lifetimes
|
||||||
|
|
|
||||||
|
LL - fn one_input<'a>(x: &'a u8) -> &'a u8 {
|
||||||
|
LL + fn one_input(x: &u8) -> &u8 {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 46 previous errors
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ error: the loop variable `i` is used to index `vec`
|
||||||
LL | for i in 0..vec.len() {
|
LL | for i in 0..vec.len() {
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: consider using an iterator
|
help: consider using an iterator and enumerate()
|
||||||
|
|
|
|
||||||
LL | for (i, <item>) in vec.iter().enumerate() {
|
LL | for (i, <item>) in vec.iter().enumerate() {
|
||||||
| ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -126,7 +126,7 @@ error: the loop variable `i` is used to index `vec`
|
||||||
LL | for i in 5..vec.len() {
|
LL | for i in 5..vec.len() {
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: consider using an iterator
|
help: consider using an iterator and enumerate()
|
||||||
|
|
|
|
||||||
LL | for (i, <item>) in vec.iter().enumerate().skip(5) {
|
LL | for (i, <item>) in vec.iter().enumerate().skip(5) {
|
||||||
| ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -137,7 +137,7 @@ error: the loop variable `i` is used to index `vec`
|
||||||
LL | for i in 5..10 {
|
LL | for i in 5..10 {
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
help: consider using an iterator
|
help: consider using an iterator and enumerate()
|
||||||
|
|
|
|
||||||
LL | for (i, <item>) in vec.iter().enumerate().take(10).skip(5) {
|
LL | for (i, <item>) in vec.iter().enumerate().take(10).skip(5) {
|
||||||
| ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -148,7 +148,7 @@ error: the loop variable `i` is used to index `vec`
|
||||||
LL | for i in 0..vec.len() {
|
LL | for i in 0..vec.len() {
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: consider using an iterator
|
help: consider using an iterator and enumerate()
|
||||||
|
|
|
|
||||||
LL | for (i, <item>) in vec.iter_mut().enumerate() {
|
LL | for (i, <item>) in vec.iter_mut().enumerate() {
|
||||||
| ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
#![allow(dead_code, clippy::missing_safety_doc, clippy::extra_unused_lifetimes)]
|
#![allow(
|
||||||
|
dead_code,
|
||||||
|
clippy::missing_safety_doc,
|
||||||
|
clippy::extra_unused_lifetimes,
|
||||||
|
clippy::extra_unused_type_parameters
|
||||||
|
)]
|
||||||
#![warn(clippy::new_without_default)]
|
#![warn(clippy::new_without_default)]
|
||||||
|
|
||||||
pub struct Foo;
|
pub struct Foo;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: you should consider adding a `Default` implementation for `Foo`
|
error: you should consider adding a `Default` implementation for `Foo`
|
||||||
--> $DIR/new_without_default.rs:7:5
|
--> $DIR/new_without_default.rs:12:5
|
||||||
|
|
|
|
||||||
LL | / pub fn new() -> Foo {
|
LL | / pub fn new() -> Foo {
|
||||||
LL | | Foo
|
LL | | Foo
|
||||||
|
@ -17,7 +17,7 @@ LL + }
|
||||||
|
|
|
|
||||||
|
|
||||||
error: you should consider adding a `Default` implementation for `Bar`
|
error: you should consider adding a `Default` implementation for `Bar`
|
||||||
--> $DIR/new_without_default.rs:15:5
|
--> $DIR/new_without_default.rs:20:5
|
||||||
|
|
|
|
||||||
LL | / pub fn new() -> Self {
|
LL | / pub fn new() -> Self {
|
||||||
LL | | Bar
|
LL | | Bar
|
||||||
|
@ -34,7 +34,7 @@ LL + }
|
||||||
|
|
|
|
||||||
|
|
||||||
error: you should consider adding a `Default` implementation for `LtKo<'c>`
|
error: you should consider adding a `Default` implementation for `LtKo<'c>`
|
||||||
--> $DIR/new_without_default.rs:79:5
|
--> $DIR/new_without_default.rs:84:5
|
||||||
|
|
|
|
||||||
LL | / pub fn new() -> LtKo<'c> {
|
LL | / pub fn new() -> LtKo<'c> {
|
||||||
LL | | unimplemented!()
|
LL | | unimplemented!()
|
||||||
|
@ -51,7 +51,7 @@ LL + }
|
||||||
|
|
|
|
||||||
|
|
||||||
error: you should consider adding a `Default` implementation for `NewNotEqualToDerive`
|
error: you should consider adding a `Default` implementation for `NewNotEqualToDerive`
|
||||||
--> $DIR/new_without_default.rs:172:5
|
--> $DIR/new_without_default.rs:177:5
|
||||||
|
|
|
|
||||||
LL | / pub fn new() -> Self {
|
LL | / pub fn new() -> Self {
|
||||||
LL | | NewNotEqualToDerive { foo: 1 }
|
LL | | NewNotEqualToDerive { foo: 1 }
|
||||||
|
@ -68,7 +68,7 @@ LL + }
|
||||||
|
|
|
|
||||||
|
|
||||||
error: you should consider adding a `Default` implementation for `FooGenerics<T>`
|
error: you should consider adding a `Default` implementation for `FooGenerics<T>`
|
||||||
--> $DIR/new_without_default.rs:180:5
|
--> $DIR/new_without_default.rs:185:5
|
||||||
|
|
|
|
||||||
LL | / pub fn new() -> Self {
|
LL | / pub fn new() -> Self {
|
||||||
LL | | Self(Default::default())
|
LL | | Self(Default::default())
|
||||||
|
@ -85,7 +85,7 @@ LL + }
|
||||||
|
|
|
|
||||||
|
|
||||||
error: you should consider adding a `Default` implementation for `BarGenerics<T>`
|
error: you should consider adding a `Default` implementation for `BarGenerics<T>`
|
||||||
--> $DIR/new_without_default.rs:187:5
|
--> $DIR/new_without_default.rs:192:5
|
||||||
|
|
|
|
||||||
LL | / pub fn new() -> Self {
|
LL | / pub fn new() -> Self {
|
||||||
LL | | Self(Default::default())
|
LL | | Self(Default::default())
|
||||||
|
@ -102,7 +102,7 @@ LL + }
|
||||||
|
|
|
|
||||||
|
|
||||||
error: you should consider adding a `Default` implementation for `Foo<T>`
|
error: you should consider adding a `Default` implementation for `Foo<T>`
|
||||||
--> $DIR/new_without_default.rs:198:9
|
--> $DIR/new_without_default.rs:203:9
|
||||||
|
|
|
|
||||||
LL | / pub fn new() -> Self {
|
LL | / pub fn new() -> Self {
|
||||||
LL | | todo!()
|
LL | | todo!()
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// run-rustfix
|
// run-rustfix
|
||||||
|
|
||||||
#![warn(clippy::redundant_field_names)]
|
#![warn(clippy::redundant_field_names)]
|
||||||
#![allow(clippy::no_effect, dead_code, unused_variables)]
|
#![allow(clippy::extra_unused_type_parameters, clippy::no_effect, dead_code, unused_variables)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate derive_new;
|
extern crate derive_new;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// run-rustfix
|
// run-rustfix
|
||||||
|
|
||||||
#![warn(clippy::redundant_field_names)]
|
#![warn(clippy::redundant_field_names)]
|
||||||
#![allow(clippy::no_effect, dead_code, unused_variables)]
|
#![allow(clippy::extra_unused_type_parameters, clippy::no_effect, dead_code, unused_variables)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate derive_new;
|
extern crate derive_new;
|
||||||
|
|
|
@ -36,6 +36,10 @@ fn syntax_error() {
|
||||||
|
|
||||||
let raw_string_error = Regex::new(r"[...\/...]");
|
let raw_string_error = Regex::new(r"[...\/...]");
|
||||||
let raw_string_error = Regex::new(r#"[...\/...]"#);
|
let raw_string_error = Regex::new(r#"[...\/...]"#);
|
||||||
|
|
||||||
|
let escaped_string_span = Regex::new("\\b\\c");
|
||||||
|
|
||||||
|
let aux_span = Regex::new("(?ixi)");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trivial_regex() {
|
fn trivial_regex() {
|
||||||
|
|
|
@ -29,7 +29,10 @@ error: regex syntax error: invalid character class range, the start must be <= t
|
||||||
LL | let some_unicode = Regex::new("[é-è]");
|
LL | let some_unicode = Regex::new("[é-è]");
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: regex syntax error on position 0: unclosed group
|
error: regex parse error:
|
||||||
|
(
|
||||||
|
^
|
||||||
|
error: unclosed group
|
||||||
--> $DIR/regex.rs:18:33
|
--> $DIR/regex.rs:18:33
|
||||||
|
|
|
|
||||||
LL | let some_regex = Regex::new(OPENING_PAREN);
|
LL | let some_regex = Regex::new(OPENING_PAREN);
|
||||||
|
@ -43,25 +46,37 @@ LL | let binary_pipe_in_wrong_position = BRegex::new("|");
|
||||||
|
|
|
|
||||||
= help: the regex is unlikely to be useful as it is
|
= help: the regex is unlikely to be useful as it is
|
||||||
|
|
||||||
error: regex syntax error on position 0: unclosed group
|
error: regex parse error:
|
||||||
|
(
|
||||||
|
^
|
||||||
|
error: unclosed group
|
||||||
--> $DIR/regex.rs:21:41
|
--> $DIR/regex.rs:21:41
|
||||||
|
|
|
|
||||||
LL | let some_binary_regex = BRegex::new(OPENING_PAREN);
|
LL | let some_binary_regex = BRegex::new(OPENING_PAREN);
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: regex syntax error on position 0: unclosed group
|
error: regex parse error:
|
||||||
|
(
|
||||||
|
^
|
||||||
|
error: unclosed group
|
||||||
--> $DIR/regex.rs:22:56
|
--> $DIR/regex.rs:22:56
|
||||||
|
|
|
|
||||||
LL | let some_binary_regex_builder = BRegexBuilder::new(OPENING_PAREN);
|
LL | let some_binary_regex_builder = BRegexBuilder::new(OPENING_PAREN);
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: regex syntax error on position 0: unclosed group
|
error: regex parse error:
|
||||||
|
(
|
||||||
|
^
|
||||||
|
error: unclosed group
|
||||||
--> $DIR/regex.rs:34:37
|
--> $DIR/regex.rs:34:37
|
||||||
|
|
|
|
||||||
LL | let set_error = RegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]);
|
LL | let set_error = RegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]);
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: regex syntax error on position 0: unclosed group
|
error: regex parse error:
|
||||||
|
(
|
||||||
|
^
|
||||||
|
error: unclosed group
|
||||||
--> $DIR/regex.rs:35:39
|
--> $DIR/regex.rs:35:39
|
||||||
|
|
|
|
||||||
LL | let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]);
|
LL | let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]);
|
||||||
|
@ -79,8 +94,25 @@ error: regex syntax error: unrecognized escape sequence
|
||||||
LL | let raw_string_error = Regex::new(r#"[...//...]"#);
|
LL | let raw_string_error = Regex::new(r#"[...//...]"#);
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
|
error: regex parse error:
|
||||||
|
/b/c
|
||||||
|
^^
|
||||||
|
error: unrecognized escape sequence
|
||||||
|
--> $DIR/regex.rs:40:42
|
||||||
|
|
|
||||||
|
LL | let escaped_string_span = Regex::new("/b/c");
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: consider using a raw string literal: `r".."`
|
||||||
|
|
||||||
|
error: regex syntax error: duplicate flag
|
||||||
|
--> $DIR/regex.rs:42:34
|
||||||
|
|
|
||||||
|
LL | let aux_span = Regex::new("(?ixi)");
|
||||||
|
| ^ ^
|
||||||
|
|
||||||
error: trivial regex
|
error: trivial regex
|
||||||
--> $DIR/regex.rs:42:33
|
--> $DIR/regex.rs:46:33
|
||||||
|
|
|
|
||||||
LL | let trivial_eq = Regex::new("^foobar$");
|
LL | let trivial_eq = Regex::new("^foobar$");
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
@ -88,7 +120,7 @@ LL | let trivial_eq = Regex::new("^foobar$");
|
||||||
= help: consider using `==` on `str`s
|
= help: consider using `==` on `str`s
|
||||||
|
|
||||||
error: trivial regex
|
error: trivial regex
|
||||||
--> $DIR/regex.rs:44:48
|
--> $DIR/regex.rs:48:48
|
||||||
|
|
|
|
||||||
LL | let trivial_eq_builder = RegexBuilder::new("^foobar$");
|
LL | let trivial_eq_builder = RegexBuilder::new("^foobar$");
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
@ -96,7 +128,7 @@ LL | let trivial_eq_builder = RegexBuilder::new("^foobar$");
|
||||||
= help: consider using `==` on `str`s
|
= help: consider using `==` on `str`s
|
||||||
|
|
||||||
error: trivial regex
|
error: trivial regex
|
||||||
--> $DIR/regex.rs:46:42
|
--> $DIR/regex.rs:50:42
|
||||||
|
|
|
|
||||||
LL | let trivial_starts_with = Regex::new("^foobar");
|
LL | let trivial_starts_with = Regex::new("^foobar");
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -104,7 +136,7 @@ LL | let trivial_starts_with = Regex::new("^foobar");
|
||||||
= help: consider using `str::starts_with`
|
= help: consider using `str::starts_with`
|
||||||
|
|
||||||
error: trivial regex
|
error: trivial regex
|
||||||
--> $DIR/regex.rs:48:40
|
--> $DIR/regex.rs:52:40
|
||||||
|
|
|
|
||||||
LL | let trivial_ends_with = Regex::new("foobar$");
|
LL | let trivial_ends_with = Regex::new("foobar$");
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -112,7 +144,7 @@ LL | let trivial_ends_with = Regex::new("foobar$");
|
||||||
= help: consider using `str::ends_with`
|
= help: consider using `str::ends_with`
|
||||||
|
|
||||||
error: trivial regex
|
error: trivial regex
|
||||||
--> $DIR/regex.rs:50:39
|
--> $DIR/regex.rs:54:39
|
||||||
|
|
|
|
||||||
LL | let trivial_contains = Regex::new("foobar");
|
LL | let trivial_contains = Regex::new("foobar");
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
@ -120,7 +152,7 @@ LL | let trivial_contains = Regex::new("foobar");
|
||||||
= help: consider using `str::contains`
|
= help: consider using `str::contains`
|
||||||
|
|
||||||
error: trivial regex
|
error: trivial regex
|
||||||
--> $DIR/regex.rs:52:39
|
--> $DIR/regex.rs:56:39
|
||||||
|
|
|
|
||||||
LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX);
|
LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX);
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
@ -128,7 +160,7 @@ LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX);
|
||||||
= help: consider using `str::contains`
|
= help: consider using `str::contains`
|
||||||
|
|
||||||
error: trivial regex
|
error: trivial regex
|
||||||
--> $DIR/regex.rs:54:40
|
--> $DIR/regex.rs:58:40
|
||||||
|
|
|
|
||||||
LL | let trivial_backslash = Regex::new("a/.b");
|
LL | let trivial_backslash = Regex::new("a/.b");
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
@ -136,7 +168,7 @@ LL | let trivial_backslash = Regex::new("a/.b");
|
||||||
= help: consider using `str::contains`
|
= help: consider using `str::contains`
|
||||||
|
|
||||||
error: trivial regex
|
error: trivial regex
|
||||||
--> $DIR/regex.rs:57:36
|
--> $DIR/regex.rs:61:36
|
||||||
|
|
|
|
||||||
LL | let trivial_empty = Regex::new("");
|
LL | let trivial_empty = Regex::new("");
|
||||||
| ^^
|
| ^^
|
||||||
|
@ -144,7 +176,7 @@ LL | let trivial_empty = Regex::new("");
|
||||||
= help: the regex is unlikely to be useful as it is
|
= help: the regex is unlikely to be useful as it is
|
||||||
|
|
||||||
error: trivial regex
|
error: trivial regex
|
||||||
--> $DIR/regex.rs:59:36
|
--> $DIR/regex.rs:63:36
|
||||||
|
|
|
|
||||||
LL | let trivial_empty = Regex::new("^");
|
LL | let trivial_empty = Regex::new("^");
|
||||||
| ^^^
|
| ^^^
|
||||||
|
@ -152,7 +184,7 @@ LL | let trivial_empty = Regex::new("^");
|
||||||
= help: the regex is unlikely to be useful as it is
|
= help: the regex is unlikely to be useful as it is
|
||||||
|
|
||||||
error: trivial regex
|
error: trivial regex
|
||||||
--> $DIR/regex.rs:61:36
|
--> $DIR/regex.rs:65:36
|
||||||
|
|
|
|
||||||
LL | let trivial_empty = Regex::new("^$");
|
LL | let trivial_empty = Regex::new("^$");
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
@ -160,12 +192,12 @@ LL | let trivial_empty = Regex::new("^$");
|
||||||
= help: consider using `str::is_empty`
|
= help: consider using `str::is_empty`
|
||||||
|
|
||||||
error: trivial regex
|
error: trivial regex
|
||||||
--> $DIR/regex.rs:63:44
|
--> $DIR/regex.rs:67:44
|
||||||
|
|
|
|
||||||
LL | let binary_trivial_empty = BRegex::new("^$");
|
LL | let binary_trivial_empty = BRegex::new("^$");
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
|
|
||||||
= help: consider using `str::is_empty`
|
= help: consider using `str::is_empty`
|
||||||
|
|
||||||
error: aborting due to 23 previous errors
|
error: aborting due to 25 previous errors
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ fn seek_to_start_false_method(t: &mut StructWithSeekMethod) {
|
||||||
|
|
||||||
// This should NOT trigger clippy warning because
|
// This should NOT trigger clippy warning because
|
||||||
// StructWithSeekMethod does not implement std::io::Seek;
|
// StructWithSeekMethod does not implement std::io::Seek;
|
||||||
fn seek_to_start_method_owned_false<T>(mut t: StructWithSeekMethod) {
|
fn seek_to_start_method_owned_false(mut t: StructWithSeekMethod) {
|
||||||
t.seek(SeekFrom::Start(0));
|
t.seek(SeekFrom::Start(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ fn seek_to_start_false_trait(t: &mut StructWithSeekTrait) {
|
||||||
|
|
||||||
// This should NOT trigger clippy warning because
|
// This should NOT trigger clippy warning because
|
||||||
// StructWithSeekMethod does not implement std::io::Seek;
|
// StructWithSeekMethod does not implement std::io::Seek;
|
||||||
fn seek_to_start_false_trait_owned<T>(mut t: StructWithSeekTrait) {
|
fn seek_to_start_false_trait_owned(mut t: StructWithSeekTrait) {
|
||||||
t.seek(SeekFrom::Start(0));
|
t.seek(SeekFrom::Start(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ fn seek_to_start_false_method(t: &mut StructWithSeekMethod) {
|
||||||
|
|
||||||
// This should NOT trigger clippy warning because
|
// This should NOT trigger clippy warning because
|
||||||
// StructWithSeekMethod does not implement std::io::Seek;
|
// StructWithSeekMethod does not implement std::io::Seek;
|
||||||
fn seek_to_start_method_owned_false<T>(mut t: StructWithSeekMethod) {
|
fn seek_to_start_method_owned_false(mut t: StructWithSeekMethod) {
|
||||||
t.seek(SeekFrom::Start(0));
|
t.seek(SeekFrom::Start(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ fn seek_to_start_false_trait(t: &mut StructWithSeekTrait) {
|
||||||
|
|
||||||
// This should NOT trigger clippy warning because
|
// This should NOT trigger clippy warning because
|
||||||
// StructWithSeekMethod does not implement std::io::Seek;
|
// StructWithSeekMethod does not implement std::io::Seek;
|
||||||
fn seek_to_start_false_trait_owned<T>(mut t: StructWithSeekTrait) {
|
fn seek_to_start_false_trait_owned(mut t: StructWithSeekTrait) {
|
||||||
t.seek(SeekFrom::Start(0));
|
t.seek(SeekFrom::Start(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,27 +2,62 @@ error: this `to_owned` call clones the Cow<'_, str> itself and does not cause th
|
||||||
--> $DIR/suspicious_to_owned.rs:16:13
|
--> $DIR/suspicious_to_owned.rs:16:13
|
||||||
|
|
|
|
||||||
LL | let _ = cow.to_owned();
|
LL | let _ = cow.to_owned();
|
||||||
| ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: `-D clippy::suspicious-to-owned` implied by `-D warnings`
|
= note: `-D clippy::suspicious-to-owned` implied by `-D warnings`
|
||||||
|
help: depending on intent, either make the Cow an Owned variant
|
||||||
|
|
|
||||||
|
LL | let _ = cow.into_owned();
|
||||||
|
| ~~~~~~~~~~~~~~~~
|
||||||
|
help: or clone the Cow itself
|
||||||
|
|
|
||||||
|
LL | let _ = cow.clone();
|
||||||
|
| ~~~~~~~~~~~
|
||||||
|
|
||||||
error: this `to_owned` call clones the Cow<'_, [char; 3]> itself and does not cause the Cow<'_, [char; 3]> contents to become owned
|
error: this `to_owned` call clones the Cow<'_, [char; 3]> itself and does not cause the Cow<'_, [char; 3]> contents to become owned
|
||||||
--> $DIR/suspicious_to_owned.rs:26:13
|
--> $DIR/suspicious_to_owned.rs:26:13
|
||||||
|
|
|
|
||||||
LL | let _ = cow.to_owned();
|
LL | let _ = cow.to_owned();
|
||||||
| ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: depending on intent, either make the Cow an Owned variant
|
||||||
|
|
|
||||||
|
LL | let _ = cow.into_owned();
|
||||||
|
| ~~~~~~~~~~~~~~~~
|
||||||
|
help: or clone the Cow itself
|
||||||
|
|
|
||||||
|
LL | let _ = cow.clone();
|
||||||
|
| ~~~~~~~~~~~
|
||||||
|
|
||||||
error: this `to_owned` call clones the Cow<'_, Vec<char>> itself and does not cause the Cow<'_, Vec<char>> contents to become owned
|
error: this `to_owned` call clones the Cow<'_, Vec<char>> itself and does not cause the Cow<'_, Vec<char>> contents to become owned
|
||||||
--> $DIR/suspicious_to_owned.rs:36:13
|
--> $DIR/suspicious_to_owned.rs:36:13
|
||||||
|
|
|
|
||||||
LL | let _ = cow.to_owned();
|
LL | let _ = cow.to_owned();
|
||||||
| ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: depending on intent, either make the Cow an Owned variant
|
||||||
|
|
|
||||||
|
LL | let _ = cow.into_owned();
|
||||||
|
| ~~~~~~~~~~~~~~~~
|
||||||
|
help: or clone the Cow itself
|
||||||
|
|
|
||||||
|
LL | let _ = cow.clone();
|
||||||
|
| ~~~~~~~~~~~
|
||||||
|
|
||||||
error: this `to_owned` call clones the Cow<'_, str> itself and does not cause the Cow<'_, str> contents to become owned
|
error: this `to_owned` call clones the Cow<'_, str> itself and does not cause the Cow<'_, str> contents to become owned
|
||||||
--> $DIR/suspicious_to_owned.rs:46:13
|
--> $DIR/suspicious_to_owned.rs:46:13
|
||||||
|
|
|
|
||||||
LL | let _ = cow.to_owned();
|
LL | let _ = cow.to_owned();
|
||||||
| ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: depending on intent, either make the Cow an Owned variant
|
||||||
|
|
|
||||||
|
LL | let _ = cow.into_owned();
|
||||||
|
| ~~~~~~~~~~~~~~~~
|
||||||
|
help: or clone the Cow itself
|
||||||
|
|
|
||||||
|
LL | let _ = cow.clone();
|
||||||
|
| ~~~~~~~~~~~
|
||||||
|
|
||||||
error: implicitly cloning a `String` by calling `to_owned` on its dereferenced type
|
error: implicitly cloning a `String` by calling `to_owned` on its dereferenced type
|
||||||
--> $DIR/suspicious_to_owned.rs:60:13
|
--> $DIR/suspicious_to_owned.rs:60:13
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#![deny(clippy::type_repetition_in_bounds)]
|
#![deny(clippy::type_repetition_in_bounds)]
|
||||||
|
#![allow(clippy::extra_unused_type_parameters)]
|
||||||
|
|
||||||
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
|
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: this type has already been used as a bound predicate
|
error: this type has already been used as a bound predicate
|
||||||
--> $DIR/type_repetition_in_bounds.rs:8:5
|
--> $DIR/type_repetition_in_bounds.rs:9:5
|
||||||
|
|
|
|
||||||
LL | T: Clone,
|
LL | T: Clone,
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
@ -12,7 +12,7 @@ LL | #![deny(clippy::type_repetition_in_bounds)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: this type has already been used as a bound predicate
|
error: this type has already been used as a bound predicate
|
||||||
--> $DIR/type_repetition_in_bounds.rs:25:5
|
--> $DIR/type_repetition_in_bounds.rs:26:5
|
||||||
|
|
|
|
||||||
LL | Self: Copy + Default + Ord,
|
LL | Self: Copy + Default + Ord,
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -20,7 +20,7 @@ LL | Self: Copy + Default + Ord,
|
||||||
= help: consider combining the bounds: `Self: Clone + Copy + Default + Ord`
|
= help: consider combining the bounds: `Self: Clone + Copy + Default + Ord`
|
||||||
|
|
||||||
error: this type has already been used as a bound predicate
|
error: this type has already been used as a bound predicate
|
||||||
--> $DIR/type_repetition_in_bounds.rs:85:5
|
--> $DIR/type_repetition_in_bounds.rs:86:5
|
||||||
|
|
|
|
||||||
LL | T: Clone,
|
LL | T: Clone,
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
@ -28,7 +28,7 @@ LL | T: Clone,
|
||||||
= help: consider combining the bounds: `T: ?Sized + Clone`
|
= help: consider combining the bounds: `T: ?Sized + Clone`
|
||||||
|
|
||||||
error: this type has already been used as a bound predicate
|
error: this type has already been used as a bound predicate
|
||||||
--> $DIR/type_repetition_in_bounds.rs:90:5
|
--> $DIR/type_repetition_in_bounds.rs:91:5
|
||||||
|
|
|
|
||||||
LL | T: ?Sized,
|
LL | T: ?Sized,
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
|
@ -63,6 +63,14 @@ fn combine_or(file: &str) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_ok_err<T: io::Read + io::Write>(s: &mut T) {
|
||||||
|
s.write(b"ok").is_ok();
|
||||||
|
s.write(b"err").is_err();
|
||||||
|
let mut buf = [0u8; 0];
|
||||||
|
s.read(&mut buf).is_ok();
|
||||||
|
s.read(&mut buf).is_err();
|
||||||
|
}
|
||||||
|
|
||||||
async fn bad_async_write<W: AsyncWrite + Unpin>(w: &mut W) {
|
async fn bad_async_write<W: AsyncWrite + Unpin>(w: &mut W) {
|
||||||
w.write(b"hello world").await.unwrap();
|
w.write(b"hello world").await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,13 +82,45 @@ LL | | .expect("error");
|
||||||
error: written amount is not handled
|
error: written amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:67:5
|
--> $DIR/unused_io_amount.rs:67:5
|
||||||
|
|
|
|
||||||
|
LL | s.write(b"ok").is_ok();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: use `Write::write_all` instead, or handle partial writes
|
||||||
|
|
||||||
|
error: written amount is not handled
|
||||||
|
--> $DIR/unused_io_amount.rs:68:5
|
||||||
|
|
|
||||||
|
LL | s.write(b"err").is_err();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: use `Write::write_all` instead, or handle partial writes
|
||||||
|
|
||||||
|
error: read amount is not handled
|
||||||
|
--> $DIR/unused_io_amount.rs:70:5
|
||||||
|
|
|
||||||
|
LL | s.read(&mut buf).is_ok();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: use `Read::read_exact` instead, or handle partial reads
|
||||||
|
|
||||||
|
error: read amount is not handled
|
||||||
|
--> $DIR/unused_io_amount.rs:71:5
|
||||||
|
|
|
||||||
|
LL | s.read(&mut buf).is_err();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: use `Read::read_exact` instead, or handle partial reads
|
||||||
|
|
||||||
|
error: written amount is not handled
|
||||||
|
--> $DIR/unused_io_amount.rs:75:5
|
||||||
|
|
|
||||||
LL | w.write(b"hello world").await.unwrap();
|
LL | w.write(b"hello world").await.unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: use `AsyncWriteExt::write_all` instead, or handle partial writes
|
= help: use `AsyncWriteExt::write_all` instead, or handle partial writes
|
||||||
|
|
||||||
error: read amount is not handled
|
error: read amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:72:5
|
--> $DIR/unused_io_amount.rs:80:5
|
||||||
|
|
|
|
||||||
LL | r.read(&mut buf[..]).await.unwrap();
|
LL | r.read(&mut buf[..]).await.unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -96,7 +128,7 @@ LL | r.read(&mut buf[..]).await.unwrap();
|
||||||
= help: use `AsyncReadExt::read_exact` instead, or handle partial reads
|
= help: use `AsyncReadExt::read_exact` instead, or handle partial reads
|
||||||
|
|
||||||
error: written amount is not handled
|
error: written amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:85:9
|
--> $DIR/unused_io_amount.rs:93:9
|
||||||
|
|
|
|
||||||
LL | w.write(b"hello world").await?;
|
LL | w.write(b"hello world").await?;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -104,7 +136,7 @@ LL | w.write(b"hello world").await?;
|
||||||
= help: use `AsyncWriteExt::write_all` instead, or handle partial writes
|
= help: use `AsyncWriteExt::write_all` instead, or handle partial writes
|
||||||
|
|
||||||
error: read amount is not handled
|
error: read amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:93:9
|
--> $DIR/unused_io_amount.rs:101:9
|
||||||
|
|
|
|
||||||
LL | r.read(&mut buf[..]).await.or(Err(Error::Kind))?;
|
LL | r.read(&mut buf[..]).await.or(Err(Error::Kind))?;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -112,7 +144,7 @@ LL | r.read(&mut buf[..]).await.or(Err(Error::Kind))?;
|
||||||
= help: use `AsyncReadExt::read_exact` instead, or handle partial reads
|
= help: use `AsyncReadExt::read_exact` instead, or handle partial reads
|
||||||
|
|
||||||
error: written amount is not handled
|
error: written amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:101:5
|
--> $DIR/unused_io_amount.rs:109:5
|
||||||
|
|
|
|
||||||
LL | w.write(b"hello world").await.unwrap();
|
LL | w.write(b"hello world").await.unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -120,12 +152,12 @@ LL | w.write(b"hello world").await.unwrap();
|
||||||
= help: use `AsyncWriteExt::write_all` instead, or handle partial writes
|
= help: use `AsyncWriteExt::write_all` instead, or handle partial writes
|
||||||
|
|
||||||
error: read amount is not handled
|
error: read amount is not handled
|
||||||
--> $DIR/unused_io_amount.rs:106:5
|
--> $DIR/unused_io_amount.rs:114:5
|
||||||
|
|
|
|
||||||
LL | r.read(&mut buf[..]).await.unwrap();
|
LL | r.read(&mut buf[..]).await.unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: use `AsyncReadExt::read_exact` instead, or handle partial reads
|
= help: use `AsyncReadExt::read_exact` instead, or handle partial reads
|
||||||
|
|
||||||
error: aborting due to 16 previous errors
|
error: aborting due to 20 previous errors
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
match Enum::A {
|
match Enum::A {
|
||||||
Enum::A => (),
|
Enum::A => (),
|
||||||
Enum::B | _ => (),
|
Enum::B | Enum::__Private => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,11 +34,11 @@ error: wildcard matches known variants and will also match future added variants
|
||||||
LL | _ => {},
|
LL | _ => {},
|
||||||
| ^ help: try this: `ErrorKind::PermissionDenied | _`
|
| ^ help: try this: `ErrorKind::PermissionDenied | _`
|
||||||
|
|
||||||
error: wildcard matches known variants and will also match future added variants
|
error: wildcard match will also match any future added variants
|
||||||
--> $DIR/wildcard_enum_match_arm.rs:99:13
|
--> $DIR/wildcard_enum_match_arm.rs:99:13
|
||||||
|
|
|
|
||||||
LL | _ => (),
|
LL | _ => (),
|
||||||
| ^ help: try this: `Enum::B | _`
|
| ^ help: try this: `Enum::B | Enum::__Private`
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue