mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Merge commit '9725c4a162502a02c1c67fdca6b797fe09b2b73c' into clippy-subtree-update
This commit is contained in:
parent
53e31dc45c
commit
0ae4a048c6
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,6 @@
|
||||
# Generated by ui-test
|
||||
rustc-ice-*
|
||||
|
||||
# Used by CI to be able to push:
|
||||
/.github/deploy_key
|
||||
out
|
||||
|
@ -5379,6 +5379,7 @@ Released 2018-09-13
|
||||
[`large_stack_arrays`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays
|
||||
[`large_stack_frames`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames
|
||||
[`large_types_passed_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value
|
||||
[`legacy_numeric_constants`]: https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants
|
||||
[`len_without_is_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_without_is_empty
|
||||
[`len_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_zero
|
||||
[`let_and_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return
|
||||
@ -5481,6 +5482,7 @@ Released 2018-09-13
|
||||
[`missing_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc
|
||||
[`missing_spin_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_spin_loop
|
||||
[`missing_trait_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_trait_methods
|
||||
[`missing_transmute_annotations`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_transmute_annotations
|
||||
[`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes
|
||||
[`mixed_attributes_style`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_attributes_style
|
||||
[`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals
|
||||
|
@ -31,7 +31,6 @@ anstream = "0.6.0"
|
||||
|
||||
[dev-dependencies]
|
||||
ui_test = "0.22.2"
|
||||
tester = "0.9"
|
||||
regex = "1.5.5"
|
||||
toml = "0.7.3"
|
||||
walkdir = "2.3"
|
||||
|
@ -32,3 +32,4 @@
|
||||
- [Proposals](development/proposals/README.md)
|
||||
- [Roadmap 2021](development/proposals/roadmap-2021.md)
|
||||
- [Syntax Tree Patterns](development/proposals/syntax-tree-patterns.md)
|
||||
- [The Team](development/the_team.md)
|
||||
|
@ -62,9 +62,8 @@ $ cargo dev new_lint --name=lint_name --pass=late --category=pedantic
|
||||
There are two things to note here:
|
||||
|
||||
1. `--pass`: We set `--pass=late` in this command to do a late lint pass. The
|
||||
alternative is an `early` lint pass. We will discuss this difference in a
|
||||
later chapter.
|
||||
<!-- FIXME: Link that "later chapter" when lint_passes.md is merged -->
|
||||
alternative is an `early` lint pass. We will discuss this difference in the
|
||||
[Lint Passes] chapter.
|
||||
2. `--category`: If not provided, the `category` of this new lint will default
|
||||
to `nursery`.
|
||||
|
||||
@ -194,8 +193,7 @@ store.register_late_pass(|_| Box::new(foo_functions::FooFunctions));
|
||||
|
||||
As you might have guessed, where there's something late, there is something
|
||||
early: in Clippy there is a `register_early_pass` method as well. More on early
|
||||
vs. late passes in a later chapter.
|
||||
<!-- FIXME: Link that "later chapter" when lint_passes.md is merged -->
|
||||
vs. late passes in the [Lint Passes] chapter.
|
||||
|
||||
Without a call to one of `register_early_pass` or `register_late_pass`, the lint
|
||||
pass in question will not be run.
|
||||
@ -203,3 +201,4 @@ pass in question will not be run.
|
||||
|
||||
[all_lints]: https://rust-lang.github.io/rust-clippy/master/
|
||||
[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
|
||||
[Lint Passes]: lint_passes.md
|
||||
|
@ -50,7 +50,7 @@ questions already, but the parser is okay with it. This is what we
|
||||
mean when we say `EarlyLintPass` deals with only syntax on the AST level.
|
||||
|
||||
Alternatively, think of the `foo_functions` lint we mentioned in
|
||||
define new lints <!-- FIXME: add link --> chapter.
|
||||
the [Define New Lints](defining_lints.md) chapter.
|
||||
|
||||
We want the `foo_functions` lint to detect functions with `foo` as their name.
|
||||
Writing a lint that only checks for the name of a function means that we only
|
||||
|
130
book/src/development/the_team.md
Normal file
130
book/src/development/the_team.md
Normal file
@ -0,0 +1,130 @@
|
||||
# The team
|
||||
|
||||
Everyone who contributes to Clippy makes the project what it is. Collaboration
|
||||
and discussions are the lifeblood of every open-source project. Clippy has a
|
||||
very flat hierarchy. The teams mainly have additional access rights to the repo.
|
||||
|
||||
This document outlines the onboarding process, as well as duties, and access
|
||||
rights for members of a group.
|
||||
|
||||
All regular events mentioned in this chapter are tracked in the [calendar repository].
|
||||
The calendar file is also available for download: [clippy.ics]
|
||||
|
||||
## Everyone
|
||||
|
||||
Everyone, including you, is welcome to join discussions and contribute in other
|
||||
ways, like PRs.
|
||||
|
||||
You also have some triage rights, using `@rustbot` to add labels and claim
|
||||
issues. See [labeling with @rustbot].
|
||||
|
||||
A rule for everyone should be to keep a healthy work-life balance. Take a break
|
||||
when you need one.
|
||||
|
||||
## Clippy-Contributors
|
||||
|
||||
This is a group of regular contributors to Clippy to help with triaging.
|
||||
|
||||
### Duties
|
||||
|
||||
This team exists to make contributing easier for regular members. It doesn't
|
||||
carry any duties that need to be done. However, we want to encourage members of
|
||||
this group to help with triaging, which can include:
|
||||
|
||||
1. **Labeling issues**
|
||||
|
||||
For the `good-first-issue` label, it can still be good to use `@rustbot` to
|
||||
subscribe to the issue and help interested parties, if they post questions
|
||||
in the comments.
|
||||
|
||||
2. **Closing duplicate or resolved issues**
|
||||
|
||||
When you manually close an issue, it's often a good idea, to add a short
|
||||
comment explaining the reason.
|
||||
|
||||
3. **Ping people after two weeks of inactivity**
|
||||
|
||||
We try to keep issue assignments and PRs fairly up-to-date. After two weeks,
|
||||
it can be good to send a friendly ping to the delaying party.
|
||||
|
||||
You might close a PR with the `I-inactive-closed` label if the author is
|
||||
busy or wants to abandon it. If the reviewer is busy, the PR can be
|
||||
reassigned to someone else.
|
||||
|
||||
Checkout: https://triage.rust-lang.org/triage/rust-lang/rust-clippy to
|
||||
monitor PRs.
|
||||
|
||||
While not part of their duties, contributors are encouraged to review PRs
|
||||
and help on Zulip. The team always appreciates help!
|
||||
|
||||
### Membership
|
||||
|
||||
If you have been contributing to Clippy for some time, we'll probably ask you if
|
||||
you want to join this team. Members of this team are also welcome to suggest
|
||||
people who they think would make a great addition to this group.
|
||||
|
||||
For this group, there is no direct onboarding process. You're welcome to just
|
||||
continue what you've been doing. If you like, you can ask for someone to mentor
|
||||
you, either in the Clippy stream on Zulip or privately via a PM.
|
||||
|
||||
If you have been inactive in Clippy for over three months, we'll probably move
|
||||
you to the alumni group. You're always welcome to come back.
|
||||
|
||||
## The Clippy Team
|
||||
|
||||
[The Clippy team](https://www.rust-lang.org/governance/teams/dev-tools#Clippy%20team)
|
||||
is responsible for maintaining Clippy.
|
||||
|
||||
### Duties
|
||||
|
||||
1. **Respond to PRs in a timely manner**
|
||||
|
||||
It's totally fine, if you don't have the time for reviews right now.
|
||||
You can reassign the PR to a random member by commenting `r? clippy`.
|
||||
|
||||
2. **Take a break when you need one**
|
||||
|
||||
You are valuable! Clippy wouldn't be what it is without you. So take a break
|
||||
early and recharge some energy when you need to.
|
||||
|
||||
3. **Be responsive on Zulip**
|
||||
|
||||
This means in a reasonable time frame, so responding within one or two days
|
||||
is totally fine.
|
||||
|
||||
It's also good, if you answer threads on Zulip and take part in our Clippy
|
||||
meetings, every two weeks. The meeting dates are tracked in the [calendar repository].
|
||||
|
||||
|
||||
4. **Sync Clippy with the rust-lang/rust repo**
|
||||
|
||||
This is done every two weeks, usually by @flip1995.
|
||||
|
||||
5. **Update the changelog**
|
||||
|
||||
This needs to be done for every release, every six weeks. This is usually
|
||||
done by @xFrednet.
|
||||
|
||||
### Membership
|
||||
|
||||
If you have been active for some time, we'll probably reach out and ask
|
||||
if you want to help with reviews and eventually join the Clippy team.
|
||||
|
||||
During the onboarding process, you'll be assigned pull requests to review.
|
||||
You'll also have an active team member as a mentor who'll stay in contact via
|
||||
Zulip DMs to provide advice and feedback. If you have questions, you're always
|
||||
welcome to ask, that is the best way to learn. Once you're done with the review,
|
||||
you can ping your mentor for a full review and to r+ the PR in both of your names.
|
||||
|
||||
When your mentor is confident that you can handle reviews on your own, they'll
|
||||
start an informal vote among the active team members to officially add you to
|
||||
the team. This vote is usually accepted unanimously. Then you'll be added to
|
||||
the team once you've confirmed that you're still interested in joining. The
|
||||
onboarding phase typically takes a couple of weeks to a few months.
|
||||
|
||||
If you have been inactive in Clippy for over three months, we'll probably move
|
||||
you to the alumni group. You're always welcome to come back.
|
||||
|
||||
[calendar repository]: https://github.com/rust-lang/calendar/blob/main/clippy.toml
|
||||
[clippy.ics]: https://rust-lang.github.io/calendar/clippy.ics
|
||||
[labeling with @rustbot]: https://forge.rust-lang.org/triagebot/labeling.html
|
@ -616,6 +616,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio
|
||||
* [`if_then_some_else_none`](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none)
|
||||
* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice)
|
||||
* [`iter_kv_map`](https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map)
|
||||
* [`legacy_numeric_constants`](https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants)
|
||||
* [`manual_bits`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits)
|
||||
* [`manual_c_str_literals`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals)
|
||||
* [`manual_clamp`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp)
|
||||
|
@ -262,7 +262,7 @@ define_Conf! {
|
||||
///
|
||||
/// Suppress lints whenever the suggested change would cause breakage for other crates.
|
||||
(avoid_breaking_exported_api: bool = true),
|
||||
/// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, 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, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS, ASSIGNING_CLONES.
|
||||
/// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, 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, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS, ASSIGNING_CLONES, LEGACY_NUMERIC_CONSTANTS.
|
||||
///
|
||||
/// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml`
|
||||
#[default_text = ""]
|
||||
@ -856,11 +856,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
assert!(
|
||||
names.remove("allow-one-hash-in-raw-strings"),
|
||||
"remove this when #11481 is fixed"
|
||||
);
|
||||
|
||||
assert!(
|
||||
names.is_empty(),
|
||||
"Configuration variable lacks test: {names:?}\nAdd a test to `tests/ui-toml`"
|
||||
|
@ -1,6 +1,12 @@
|
||||
#![feature(rustc_private, let_chains)]
|
||||
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
|
||||
#![warn(rust_2018_idioms, unused_lifetimes)]
|
||||
#![warn(
|
||||
trivial_casts,
|
||||
trivial_numeric_casts,
|
||||
rust_2018_idioms,
|
||||
unused_lifetimes,
|
||||
unused_qualifications
|
||||
)]
|
||||
#![allow(
|
||||
clippy::must_use_candidate,
|
||||
clippy::missing_panics_doc,
|
||||
|
@ -36,7 +36,7 @@ msrv_aliases! {
|
||||
1,47,0 { TAU, IS_ASCII_DIGIT_CONST, ARRAY_IMPL_ANY_LEN }
|
||||
1,46,0 { CONST_IF_MATCH }
|
||||
1,45,0 { STR_STRIP_PREFIX }
|
||||
1,43,0 { LOG2_10, LOG10_2 }
|
||||
1,43,0 { LOG2_10, LOG10_2, NUMERIC_ASSOCIATED_CONSTANTS }
|
||||
1,42,0 { MATCHES_MACRO, SLICE_PATTERNS, PTR_SLICE_RAW_PARTS }
|
||||
1,41,0 { RE_REBALANCING_COHERENCE, RESULT_MAP_OR_ELSE }
|
||||
1,40,0 { MEM_TAKE, NON_EXHAUSTIVE, OPTION_AS_DEREF }
|
||||
|
@ -2,8 +2,13 @@
|
||||
#![feature(let_chains)]
|
||||
#![feature(rustc_private)]
|
||||
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
|
||||
// warn on lints, that are included in `rust-lang/rust`s bootstrap
|
||||
#![warn(rust_2018_idioms, unused_lifetimes)]
|
||||
#![warn(
|
||||
trivial_casts,
|
||||
trivial_numeric_casts,
|
||||
rust_2018_idioms,
|
||||
unused_lifetimes,
|
||||
unused_qualifications
|
||||
)]
|
||||
|
||||
// The `rustc_driver` crate seems to be required in order to use the `rust_lexer` crate.
|
||||
#[allow(unused_extern_crates)]
|
||||
|
@ -20,6 +20,8 @@ pub fn run<'a>(path: &str, args: impl Iterator<Item = &'a String>) {
|
||||
.args(["--edition", "2021"])
|
||||
.arg(path)
|
||||
.args(args)
|
||||
// Prevent rustc from creating `rustc-ice-*` files the console output is enough.
|
||||
.env("RUSTC_ICE", "0")
|
||||
.status(),
|
||||
);
|
||||
} else {
|
||||
@ -32,6 +34,8 @@ pub fn run<'a>(path: &str, args: impl Iterator<Item = &'a String>) {
|
||||
let status = Command::new(cargo_clippy_path())
|
||||
.arg("clippy")
|
||||
.args(args)
|
||||
// Prevent rustc from creating `rustc-ice-*` files the console output is enough.
|
||||
.env("RUSTC_ICE", "0")
|
||||
.current_dir(path)
|
||||
.status();
|
||||
|
||||
|
@ -992,7 +992,7 @@ fn replace_region_in_text<'a>(
|
||||
}
|
||||
|
||||
fn try_rename_file(old_name: &Path, new_name: &Path) -> bool {
|
||||
match fs::OpenOptions::new().create_new(true).write(true).open(new_name) {
|
||||
match OpenOptions::new().create_new(true).write(true).open(new_name) {
|
||||
Ok(file) => drop(file),
|
||||
Err(e) if matches!(e.kind(), io::ErrorKind::AlreadyExists | io::ErrorKind::NotFound) => return false,
|
||||
Err(e) => panic_file(e, new_name, "create"),
|
||||
@ -1016,7 +1016,7 @@ fn panic_file(error: io::Error, name: &Path, action: &str) -> ! {
|
||||
}
|
||||
|
||||
fn rewrite_file(path: &Path, f: impl FnOnce(&str) -> Option<String>) {
|
||||
let mut file = fs::OpenOptions::new()
|
||||
let mut file = OpenOptions::new()
|
||||
.write(true)
|
||||
.read(true)
|
||||
.open(path)
|
||||
|
@ -95,7 +95,7 @@ impl ApproxConstant {
|
||||
cx,
|
||||
APPROX_CONSTANT,
|
||||
e.span,
|
||||
&format!("approximate value of `{module}::consts::{}` found", &name),
|
||||
format!("approximate value of `{module}::consts::{}` found", &name),
|
||||
None,
|
||||
"consider using the constant directly",
|
||||
);
|
||||
|
@ -53,9 +53,9 @@ fn check_asm_syntax(
|
||||
cx,
|
||||
lint,
|
||||
span,
|
||||
&format!("{style} x86 assembly syntax used"),
|
||||
format!("{style} x86 assembly syntax used"),
|
||||
None,
|
||||
&format!("use {} x86 assembly syntax", !style),
|
||||
format!("use {} x86 assembly syntax", !style),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants {
|
||||
cx,
|
||||
ASSERTIONS_ON_CONSTANTS,
|
||||
macro_call.span,
|
||||
&format!(
|
||||
format!(
|
||||
"`{}!(true)` will be optimized out by the compiler",
|
||||
cx.tcx.item_name(macro_call.def_id)
|
||||
),
|
||||
@ -74,9 +74,9 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants {
|
||||
cx,
|
||||
ASSERTIONS_ON_CONSTANTS,
|
||||
macro_call.span,
|
||||
&format!("`assert!(false{assert_arg})` should probably be replaced"),
|
||||
format!("`assert!(false{assert_arg})` should probably be replaced"),
|
||||
None,
|
||||
&format!("use `panic!({panic_arg})` or `unreachable!({panic_arg})`"),
|
||||
format!("use `panic!({panic_arg})` or `unreachable!({panic_arg})`"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ impl AssigningClones {
|
||||
impl_lint_pass!(AssigningClones => [ASSIGNING_CLONES]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for AssigningClones {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, assign_expr: &'tcx hir::Expr<'_>) {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, assign_expr: &'tcx Expr<'_>) {
|
||||
// Do not fire the lint in macros
|
||||
let expn_data = assign_expr.span().ctxt().outer_expn_data();
|
||||
match expn_data.kind {
|
||||
@ -181,6 +181,23 @@ fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallC
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the call expression is inside an impl block that contains the method invoked by the
|
||||
// call expression, we bail out to avoid suggesting something that could result in endless
|
||||
// recursion.
|
||||
if let Some(local_block_id) = impl_block.as_local()
|
||||
&& let Some(block) = cx.tcx.hir_node_by_def_id(local_block_id).as_owner()
|
||||
{
|
||||
let impl_block_owner = block.def_id();
|
||||
if cx
|
||||
.tcx
|
||||
.hir()
|
||||
.parent_id_iter(lhs.hir_id)
|
||||
.any(|parent| parent.owner == impl_block_owner)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the function for which we want to check that it is implemented.
|
||||
let provided_fn = match call.target {
|
||||
TargetTrait::Clone => cx.tcx.get_diagnostic_item(sym::Clone).and_then(|clone| {
|
||||
@ -205,14 +222,9 @@ fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallC
|
||||
implemented_fns.contains_key(&provided_fn.def_id)
|
||||
}
|
||||
|
||||
fn suggest<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
assign_expr: &hir::Expr<'tcx>,
|
||||
lhs: &hir::Expr<'tcx>,
|
||||
call: &CallCandidate<'tcx>,
|
||||
) {
|
||||
fn suggest<'tcx>(cx: &LateContext<'tcx>, assign_expr: &Expr<'tcx>, lhs: &Expr<'tcx>, call: &CallCandidate<'tcx>) {
|
||||
span_lint_and_then(cx, ASSIGNING_CLONES, assign_expr.span, call.message(), |diag| {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let mut applicability = Applicability::Unspecified;
|
||||
|
||||
diag.span_suggestion(
|
||||
assign_expr.span,
|
||||
@ -263,7 +275,7 @@ impl<'tcx> CallCandidate<'tcx> {
|
||||
fn suggested_replacement(
|
||||
&self,
|
||||
cx: &LateContext<'tcx>,
|
||||
lhs: &hir::Expr<'tcx>,
|
||||
lhs: &Expr<'tcx>,
|
||||
applicability: &mut Applicability,
|
||||
) -> String {
|
||||
match self.target {
|
||||
|
@ -30,7 +30,7 @@ pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[NestedMet
|
||||
cx,
|
||||
ALLOW_ATTRIBUTES_WITHOUT_REASON,
|
||||
attr.span,
|
||||
&format!("`{}` attribute without specifying a reason", name.as_str()),
|
||||
format!("`{}` attribute without specifying a reason", name.as_str()),
|
||||
None,
|
||||
"try adding a reason at the end with `, reason = \"..\"`",
|
||||
);
|
||||
|
@ -31,6 +31,9 @@ fn check_duplicated_attr(
|
||||
attr_paths: &mut FxHashMap<String, Span>,
|
||||
parent: &mut Vec<String>,
|
||||
) {
|
||||
if attr.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
let Some(ident) = attr.ident() else { return };
|
||||
let name = ident.name;
|
||||
if name == sym::doc || name == sym::cfg_attr {
|
||||
@ -38,6 +41,14 @@ fn check_duplicated_attr(
|
||||
// conditions are the same.
|
||||
return;
|
||||
}
|
||||
if let Some(direct_parent) = parent.last()
|
||||
&& ["cfg", "cfg_attr"].contains(&direct_parent.as_str())
|
||||
&& [sym::all, sym::not, sym::any].contains(&name)
|
||||
{
|
||||
// FIXME: We don't correctly check `cfg`s for now, so if it's more complex than just a one
|
||||
// level `cfg`, we leave.
|
||||
return;
|
||||
}
|
||||
if let Some(value) = attr.value_str() {
|
||||
emit_if_duplicated(cx, attr, attr_paths, format!("{}:{name}={value}", parent.join(":")));
|
||||
} else if let Some(sub_attrs) = attr.meta_item_list() {
|
||||
|
@ -21,7 +21,7 @@ pub(super) fn check(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Att
|
||||
cx,
|
||||
INLINE_ALWAYS,
|
||||
attr.span,
|
||||
&format!("you have declared `#[inline(always)]` on `{name}`. This is usually a bad idea"),
|
||||
format!("you have declared `#[inline(always)]` on `{name}`. This is usually a bad idea"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ fn check_nested_misused_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
|
||||
cx,
|
||||
MAYBE_MISUSED_CFG,
|
||||
meta.span,
|
||||
&format!("'test' may be misspelled as '{}'", ident.name.as_str()),
|
||||
format!("'test' may be misspelled as '{}'", ident.name.as_str()),
|
||||
"did you mean",
|
||||
"test".to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
|
@ -1,30 +1,85 @@
|
||||
use super::MIXED_ATTRIBUTES_STYLE;
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use rustc_ast::AttrStyle;
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_ast::{AttrKind, AttrStyle, Attribute};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{SourceFile, Span, Symbol};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
|
||||
let mut has_outer = false;
|
||||
let mut has_inner = false;
|
||||
#[derive(Hash, PartialEq, Eq)]
|
||||
enum SimpleAttrKind {
|
||||
Doc,
|
||||
/// A normal attribute, with its name symbols.
|
||||
Normal(Vec<Symbol>),
|
||||
}
|
||||
|
||||
for attr in &item.attrs {
|
||||
if attr.span.from_expansion() {
|
||||
impl From<&AttrKind> for SimpleAttrKind {
|
||||
fn from(value: &AttrKind) -> Self {
|
||||
match value {
|
||||
AttrKind::Normal(attr) => {
|
||||
let path_symbols = attr
|
||||
.item
|
||||
.path
|
||||
.segments
|
||||
.iter()
|
||||
.map(|seg| seg.ident.name)
|
||||
.collect::<Vec<_>>();
|
||||
Self::Normal(path_symbols)
|
||||
},
|
||||
AttrKind::DocComment(..) => Self::Doc,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute]) {
|
||||
let mut inner_attr_kind: FxHashSet<SimpleAttrKind> = FxHashSet::default();
|
||||
let mut outer_attr_kind: FxHashSet<SimpleAttrKind> = FxHashSet::default();
|
||||
|
||||
let source_map = cx.sess().source_map();
|
||||
let item_src = source_map.lookup_source_file(item_span.lo());
|
||||
|
||||
for attr in attrs {
|
||||
if attr.span.from_expansion() || !attr_in_same_src_as_item(source_map, &item_src, attr.span) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let kind: SimpleAttrKind = (&attr.kind).into();
|
||||
match attr.style {
|
||||
AttrStyle::Inner => has_inner = true,
|
||||
AttrStyle::Outer => has_outer = true,
|
||||
}
|
||||
AttrStyle::Inner => {
|
||||
if outer_attr_kind.contains(&kind) {
|
||||
lint_mixed_attrs(cx, attrs);
|
||||
return;
|
||||
}
|
||||
inner_attr_kind.insert(kind);
|
||||
},
|
||||
AttrStyle::Outer => {
|
||||
if inner_attr_kind.contains(&kind) {
|
||||
lint_mixed_attrs(cx, attrs);
|
||||
return;
|
||||
}
|
||||
outer_attr_kind.insert(kind);
|
||||
},
|
||||
};
|
||||
}
|
||||
if !has_outer || !has_inner {
|
||||
}
|
||||
|
||||
fn lint_mixed_attrs(cx: &LateContext<'_>, attrs: &[Attribute]) {
|
||||
let mut attrs_iter = attrs.iter().filter(|attr| !attr.span.from_expansion());
|
||||
let span = if let (Some(first), Some(last)) = (attrs_iter.next(), attrs_iter.last()) {
|
||||
first.span.with_hi(last.span.hi())
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
let mut attrs_iter = item.attrs.iter().filter(|attr| !attr.span.from_expansion());
|
||||
let span = attrs_iter.next().unwrap().span;
|
||||
};
|
||||
span_lint(
|
||||
cx,
|
||||
MIXED_ATTRIBUTES_STYLE,
|
||||
span.with_hi(attrs_iter.last().unwrap().span.hi()),
|
||||
span,
|
||||
"item has both inner and outer attributes",
|
||||
);
|
||||
}
|
||||
|
||||
fn attr_in_same_src_as_item(source_map: &SourceMap, item_src: &Arc<SourceFile>, attr_span: Span) -> bool {
|
||||
let attr_src = source_map.lookup_source_file(attr_span.lo());
|
||||
Arc::ptr_eq(item_src, &attr_src)
|
||||
}
|
||||
|
@ -465,10 +465,20 @@ declare_clippy_lint! {
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks that an item has only one kind of attributes.
|
||||
/// Checks for items that have the same kind of attributes with mixed styles (inner/outer).
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Having both kinds of attributes makes it more complicated to read code.
|
||||
/// Having both style of said attributes makes it more complicated to read code.
|
||||
///
|
||||
/// ### Known problems
|
||||
/// This lint currently has false-negatives when mixing same attributes
|
||||
/// but they have different path symbols, for example:
|
||||
/// ```ignore
|
||||
/// #[custom_attribute]
|
||||
/// pub fn foo() {
|
||||
/// #![my_crate::custom_attribute]
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ### Example
|
||||
/// ```no_run
|
||||
@ -486,7 +496,7 @@ declare_clippy_lint! {
|
||||
/// ```
|
||||
#[clippy::version = "1.78.0"]
|
||||
pub MIXED_ATTRIBUTES_STYLE,
|
||||
suspicious,
|
||||
style,
|
||||
"item has both inner and outer attributes"
|
||||
}
|
||||
|
||||
@ -523,6 +533,7 @@ declare_lint_pass!(Attributes => [
|
||||
USELESS_ATTRIBUTE,
|
||||
BLANKET_CLIPPY_RESTRICTION_LINTS,
|
||||
SHOULD_PANIC_WITHOUT_EXPECT,
|
||||
MIXED_ATTRIBUTES_STYLE,
|
||||
]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for Attributes {
|
||||
@ -566,6 +577,7 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
|
||||
ItemKind::ExternCrate(..) | ItemKind::Use(..) => useless_attribute::check(cx, item, attrs),
|
||||
_ => {},
|
||||
}
|
||||
mixed_attributes_style::check(cx, item.span, attrs);
|
||||
}
|
||||
|
||||
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
|
||||
@ -594,7 +606,6 @@ impl_lint_pass!(EarlyAttributes => [
|
||||
MAYBE_MISUSED_CFG,
|
||||
DEPRECATED_CLIPPY_CFG_ATTR,
|
||||
UNNECESSARY_CLIPPY_CFG,
|
||||
MIXED_ATTRIBUTES_STYLE,
|
||||
DUPLICATED_ATTRIBUTES,
|
||||
]);
|
||||
|
||||
@ -605,7 +616,6 @@ impl EarlyLintPass for EarlyAttributes {
|
||||
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
|
||||
empty_line_after::check(cx, item);
|
||||
mixed_attributes_style::check(cx, item);
|
||||
duplicated_attributes::check(cx, &item.attrs);
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ pub(super) fn check(
|
||||
clippy_lints,
|
||||
"no need to put clippy lints behind a `clippy` cfg",
|
||||
None,
|
||||
&format!(
|
||||
format!(
|
||||
"write instead: `#{}[{}({})]`",
|
||||
if attr.style == AttrStyle::Inner { "!" } else { "" },
|
||||
ident.name,
|
||||
|
@ -267,7 +267,7 @@ fn emit_invalid_type(cx: &LateContext<'_>, span: Span, disallowed: &DisallowedPa
|
||||
cx,
|
||||
AWAIT_HOLDING_INVALID_TYPE,
|
||||
span,
|
||||
&format!(
|
||||
format!(
|
||||
"`{}` may not be held across an `await` point per `clippy.toml`",
|
||||
disallowed.path()
|
||||
),
|
||||
|
@ -72,7 +72,7 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInConditions {
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let complex_block_message = &format!(
|
||||
let complex_block_message = format!(
|
||||
"in {desc}, avoid complex blocks or closures with blocks; \
|
||||
instead, move the block or closure higher and bind it with a `let`",
|
||||
);
|
||||
@ -141,7 +141,7 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInConditions {
|
||||
let ex = &body.value;
|
||||
if let ExprKind::Block(block, _) = ex.kind {
|
||||
if !body.value.span.from_expansion() && !block.stmts.is_empty() {
|
||||
span_lint(cx, BLOCKS_IN_CONDITIONS, ex.span, complex_block_message);
|
||||
span_lint(cx, BLOCKS_IN_CONDITIONS, ex.span, complex_block_message.clone());
|
||||
return ControlFlow::Continue(Descend::No);
|
||||
}
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ impl<'tcx> LateLintPass<'tcx> for BoolAssertComparison {
|
||||
cx,
|
||||
BOOL_ASSERT_COMPARISON,
|
||||
macro_call.span,
|
||||
&format!("used `{macro_name}!` with a literal bool"),
|
||||
format!("used `{macro_name}!` with a literal bool"),
|
||||
|diag| {
|
||||
// assert_eq!(...)
|
||||
// ^^^^^^^^^
|
||||
|
@ -392,13 +392,13 @@ fn simple_negate(b: Bool) -> Bool {
|
||||
t @ Term(_) => Not(Box::new(t)),
|
||||
And(mut v) => {
|
||||
for el in &mut v {
|
||||
*el = simple_negate(::std::mem::replace(el, True));
|
||||
*el = simple_negate(std::mem::replace(el, True));
|
||||
}
|
||||
Or(v)
|
||||
},
|
||||
Or(mut v) => {
|
||||
for el in &mut v {
|
||||
*el = simple_negate(::std::mem::replace(el, True));
|
||||
*el = simple_negate(std::mem::replace(el, True));
|
||||
}
|
||||
And(v)
|
||||
},
|
||||
|
@ -1,6 +1,5 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::macros::macro_backtrace;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::ty::expr_sig;
|
||||
use clippy_utils::{is_default_equivalent, path_def_id};
|
||||
use rustc_errors::Applicability;
|
||||
@ -9,20 +8,16 @@ use rustc_hir::intravisit::{walk_ty, Visitor};
|
||||
use rustc_hir::{Block, Expr, ExprKind, LetStmt, Node, QPath, Ty, TyKind};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::print::with_forced_trimmed_paths;
|
||||
use rustc_middle::ty::IsSuggestable;
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::sym;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// checks for `Box::new(T::default())`, which is better written as
|
||||
/// `Box::<T>::default()`.
|
||||
/// checks for `Box::new(Default::default())`, which can be written as
|
||||
/// `Box::default()`.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// First, it's more complex, involving two calls instead of one.
|
||||
/// Second, `Box::default()` can be faster
|
||||
/// [in certain cases](https://nnethercote.github.io/perf-book/standard-library-types.html#box).
|
||||
/// `Box::default()` is equivalent and more concise.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```no_run
|
||||
@ -34,7 +29,7 @@ declare_clippy_lint! {
|
||||
/// ```
|
||||
#[clippy::version = "1.66.0"]
|
||||
pub BOX_DEFAULT,
|
||||
perf,
|
||||
style,
|
||||
"Using Box::new(T::default()) instead of Box::default()"
|
||||
}
|
||||
|
||||
@ -53,14 +48,14 @@ impl LateLintPass<'_> for BoxDefault {
|
||||
&& path_def_id(cx, ty).map_or(false, |id| Some(id) == cx.tcx.lang_items().owned_box())
|
||||
// And the single argument to the call is another function call
|
||||
// This is the `T::default()` of `Box::new(T::default())`
|
||||
&& let ExprKind::Call(arg_path, inner_call_args) = arg.kind
|
||||
&& let ExprKind::Call(arg_path, _) = arg.kind
|
||||
// And we are not in a foreign crate's macro
|
||||
&& !in_external_macro(cx.sess(), expr.span)
|
||||
// And the argument expression has the same context as the outer call expression
|
||||
// or that we are inside a `vec!` macro expansion
|
||||
&& (expr.span.eq_ctxt(arg.span) || is_local_vec_expn(cx, arg, expr))
|
||||
// And the argument is equivalent to `Default::default()`
|
||||
&& is_default_equivalent(cx, arg)
|
||||
// And the argument is `Default::default()` or the type is specified
|
||||
&& (is_plain_default(cx, arg_path) || (given_type(cx, expr) && is_default_equivalent(cx, arg)))
|
||||
{
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
@ -68,25 +63,7 @@ impl LateLintPass<'_> for BoxDefault {
|
||||
expr.span,
|
||||
"`Box::new(_)` of default value",
|
||||
"try",
|
||||
if is_plain_default(cx, arg_path) || given_type(cx, expr) {
|
||||
"Box::default()".into()
|
||||
} else if let Some(arg_ty) =
|
||||
cx.typeck_results().expr_ty(arg).make_suggestable(cx.tcx, true, None)
|
||||
{
|
||||
// Check if we can copy from the source expression in the replacement.
|
||||
// We need the call to have no argument (see `explicit_default_type`).
|
||||
if inner_call_args.is_empty()
|
||||
&& let Some(ty) = explicit_default_type(arg_path)
|
||||
&& let Some(s) = snippet_opt(cx, ty.span)
|
||||
{
|
||||
format!("Box::<{s}>::default()")
|
||||
} else {
|
||||
// Otherwise, use the inferred type's formatting.
|
||||
with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()"))
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
},
|
||||
"Box::default()".into(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
@ -105,20 +82,6 @@ fn is_plain_default(cx: &LateContext<'_>, arg_path: &Expr<'_>) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
// Checks whether the call is of the form `A::B::f()`. Returns `A::B` if it is.
|
||||
//
|
||||
// In the event we have this kind of construct, it's easy to use `A::B` as a replacement in the
|
||||
// quickfix. `f` must however have no parameter. Should `f` have some, then some of the type of
|
||||
// `A::B` may be inferred from the arguments. This would be the case for `Vec::from([0; false])`,
|
||||
// where the argument to `from` allows inferring this is a `Vec<bool>`
|
||||
fn explicit_default_type<'a>(arg_path: &'a Expr<'_>) -> Option<&'a Ty<'a>> {
|
||||
if let ExprKind::Path(QPath::TypeRelative(ty, _)) = &arg_path.kind {
|
||||
Some(ty)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn is_local_vec_expn(cx: &LateContext<'_>, expr: &Expr<'_>, ref_expr: &Expr<'_>) -> bool {
|
||||
macro_backtrace(expr.span).next().map_or(false, |call| {
|
||||
cx.tcx.is_diagnostic_item(sym::vec_macro, call.def_id) && call.span.eq_ctxt(ref_expr.span)
|
||||
@ -129,7 +92,7 @@ fn is_local_vec_expn(cx: &LateContext<'_>, expr: &Expr<'_>, ref_expr: &Expr<'_>)
|
||||
struct InferVisitor(bool);
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for InferVisitor {
|
||||
fn visit_ty(&mut self, t: &rustc_hir::Ty<'_>) {
|
||||
fn visit_ty(&mut self, t: &Ty<'_>) {
|
||||
self.0 |= matches!(t.kind, TyKind::Infer | TyKind::OpaqueDef(..) | TyKind::TraitObject(..));
|
||||
if !self.0 {
|
||||
walk_ty(self, t);
|
||||
|
@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata, ignore_publish: b
|
||||
|
||||
fn missing_warning(cx: &LateContext<'_>, package: &cargo_metadata::Package, field: &str) {
|
||||
let message = format!("package `{}` is missing `{field}` metadata", package.name);
|
||||
span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, &message);
|
||||
span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, message);
|
||||
}
|
||||
|
||||
fn is_empty_str<T: AsRef<std::ffi::OsStr>>(value: &Option<T>) -> bool {
|
||||
|
@ -56,13 +56,13 @@ fn lint(cx: &LateContext<'_>, feature: &str, substring: &str, is_prefix: bool) {
|
||||
REDUNDANT_FEATURE_NAMES
|
||||
},
|
||||
DUMMY_SP,
|
||||
&format!(
|
||||
format!(
|
||||
"the \"{substring}\" {} in the feature name \"{feature}\" is {}",
|
||||
if is_prefix { "prefix" } else { "suffix" },
|
||||
if is_negative { "negative" } else { "redundant" }
|
||||
),
|
||||
None,
|
||||
&format!(
|
||||
format!(
|
||||
"consider renaming the feature to \"{}\"{}",
|
||||
if is_prefix {
|
||||
feature.strip_prefix(substring)
|
||||
|
@ -102,7 +102,7 @@ fn check_table(cx: &LateContext<'_>, table: LintTable, groups: &FxHashSet<&str>,
|
||||
cx,
|
||||
LINT_GROUPS_PRIORITY,
|
||||
toml_span(group.span(), file),
|
||||
&format!(
|
||||
format!(
|
||||
"lint group `{}` has the same priority ({priority}) as a lint",
|
||||
group.as_ref()
|
||||
),
|
||||
|
@ -241,7 +241,7 @@ impl LateLintPass<'_> for Cargo {
|
||||
},
|
||||
Err(e) => {
|
||||
for lint in NO_DEPS_LINTS {
|
||||
span_lint(cx, lint, DUMMY_SP, &format!("could not read cargo metadata: {e}"));
|
||||
span_lint(cx, lint, DUMMY_SP, format!("could not read cargo metadata: {e}"));
|
||||
}
|
||||
},
|
||||
}
|
||||
@ -257,7 +257,7 @@ impl LateLintPass<'_> for Cargo {
|
||||
},
|
||||
Err(e) => {
|
||||
for lint in WITH_DEPS_LINTS {
|
||||
span_lint(cx, lint, DUMMY_SP, &format!("could not read cargo metadata: {e}"));
|
||||
span_lint(cx, lint, DUMMY_SP, format!("could not read cargo metadata: {e}"));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata, allowed_duplicate
|
||||
cx,
|
||||
MULTIPLE_CRATE_VERSIONS,
|
||||
DUMMY_SP,
|
||||
&format!("multiple versions for dependency `{name}`: {versions}"),
|
||||
format!("multiple versions for dependency `{name}`: {versions}"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata) {
|
||||
cx,
|
||||
WILDCARD_DEPENDENCIES,
|
||||
DUMMY_SP,
|
||||
&format!("wildcard dependency for `{}`", dep.name),
|
||||
format!("wildcard dependency for `{}`", dep.name),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
|
||||
cx,
|
||||
AS_PTR_CAST_MUT,
|
||||
expr.span,
|
||||
&format!("casting the result of `as_ptr` to *mut {ptrty}"),
|
||||
format!("casting the result of `as_ptr` to *mut {ptrty}"),
|
||||
"replace with",
|
||||
format!("{recv}.as_mut_ptr()"),
|
||||
applicability,
|
||||
|
@ -34,7 +34,7 @@ pub(super) fn check(
|
||||
cx,
|
||||
CAST_ABS_TO_UNSIGNED,
|
||||
span,
|
||||
&format!("casting the result of `{cast_from}::abs()` to {cast_to}"),
|
||||
format!("casting the result of `{cast_from}::abs()` to {cast_to}"),
|
||||
"replace with",
|
||||
format!("{}.unsigned_abs()", Sugg::hir(cx, receiver, "..").maybe_par()),
|
||||
Applicability::MachineApplicable,
|
||||
|
@ -68,7 +68,7 @@ pub(super) fn check(
|
||||
cx,
|
||||
CAST_LOSSLESS,
|
||||
expr.span,
|
||||
&message,
|
||||
message,
|
||||
"try",
|
||||
format!("{cast_to_fmt}::from({sugg})"),
|
||||
app,
|
||||
|
@ -12,7 +12,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
|
||||
cx,
|
||||
CAST_NAN_TO_INT,
|
||||
expr.span,
|
||||
&format!("casting a known NaN to {to_ty}"),
|
||||
format!("casting a known NaN to {to_ty}"),
|
||||
None,
|
||||
"this always evaluates to 0",
|
||||
);
|
||||
|
@ -41,7 +41,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
|
||||
})
|
||||
},
|
||||
BinOpKind::Rem | BinOpKind::BitAnd => get_constant_bits(cx, right)
|
||||
.unwrap_or(u64::max_value())
|
||||
.unwrap_or(u64::MAX)
|
||||
.min(apply_reductions(cx, nbits, left, signed)),
|
||||
BinOpKind::Shr => apply_reductions(cx, nbits, left, signed)
|
||||
.saturating_sub(constant_int(cx, right).map_or(0, |s| u64::try_from(s).unwrap_or_default())),
|
||||
@ -56,7 +56,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
|
||||
} else {
|
||||
None
|
||||
};
|
||||
apply_reductions(cx, nbits, left, signed).min(max_bits.unwrap_or(u64::max_value()))
|
||||
apply_reductions(cx, nbits, left, signed).min(max_bits.unwrap_or(u64::MAX))
|
||||
},
|
||||
ExprKind::MethodCall(method, _, [lo, hi], _) => {
|
||||
if method.ident.as_str() == "clamp" {
|
||||
@ -142,7 +142,7 @@ pub(super) fn check(
|
||||
cx,
|
||||
CAST_ENUM_TRUNCATION,
|
||||
expr.span,
|
||||
&format!(
|
||||
format!(
|
||||
"casting `{cast_from}::{}` to `{cast_to}` will truncate the value{suffix}",
|
||||
variant.name,
|
||||
),
|
||||
@ -163,7 +163,7 @@ pub(super) fn check(
|
||||
_ => return,
|
||||
};
|
||||
|
||||
span_lint_and_then(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &msg, |diag| {
|
||||
span_lint_and_then(cx, CAST_POSSIBLE_TRUNCATION, expr.span, msg, |diag| {
|
||||
diag.help("if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...");
|
||||
if !cast_from.is_floating_point() {
|
||||
offer_suggestion(cx, expr, cast_expr, cast_to_span, diag);
|
||||
|
@ -79,7 +79,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, ca
|
||||
),
|
||||
};
|
||||
|
||||
span_lint_and_then(cx, CAST_POSSIBLE_WRAP, expr.span, &message, |diag| {
|
||||
span_lint_and_then(cx, CAST_POSSIBLE_WRAP, expr.span, message, |diag| {
|
||||
if let EmitState::LintOnPtrSize(16) = should_lint {
|
||||
diag
|
||||
.note("`usize` and `isize` may be as small as 16 bits on some platforms")
|
||||
|
@ -38,7 +38,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, ca
|
||||
cx,
|
||||
CAST_PRECISION_LOSS,
|
||||
expr.span,
|
||||
&format!(
|
||||
format!(
|
||||
"casting `{0}` to `{1}` causes a loss of precision {2}(`{0}` is {3} bits wide, \
|
||||
but `{1}`'s mantissa is only {4} bits wide)",
|
||||
cast_from,
|
||||
|
@ -48,7 +48,7 @@ fn lint_cast_ptr_alignment<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, cast_f
|
||||
cx,
|
||||
CAST_PTR_ALIGNMENT,
|
||||
expr.span,
|
||||
&format!(
|
||||
format!(
|
||||
"casting from `{cast_from}` to a more-strictly-aligned pointer (`{cast_to}`) ({} < {} bytes)",
|
||||
from_layout.align.abi.bytes(),
|
||||
to_layout.align.abi.bytes(),
|
||||
|
@ -47,7 +47,7 @@ pub(super) fn check<'cx>(
|
||||
cx,
|
||||
CAST_SIGN_LOSS,
|
||||
expr.span,
|
||||
&format!("casting `{cast_from}` to `{cast_to}` may lose the sign of the value"),
|
||||
format!("casting `{cast_from}` to `{cast_to}` may lose the sign of the value"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -118,7 +118,7 @@ enum Sign {
|
||||
Uncertain,
|
||||
}
|
||||
|
||||
fn expr_sign<'cx>(cx: &LateContext<'cx>, expr: &Expr<'_>, ty: impl Into<Option<Ty<'cx>>>) -> Sign {
|
||||
fn expr_sign<'cx, 'tcx>(cx: &LateContext<'cx>, mut expr: &'tcx Expr<'tcx>, ty: impl Into<Option<Ty<'cx>>>) -> Sign {
|
||||
// Try evaluate this expr first to see if it's positive
|
||||
if let Some(val) = get_const_signed_int_eval(cx, expr, ty) {
|
||||
return if val >= 0 { Sign::ZeroOrPositive } else { Sign::Negative };
|
||||
@ -134,11 +134,12 @@ fn expr_sign<'cx>(cx: &LateContext<'cx>, expr: &Expr<'_>, ty: impl Into<Option<T
|
||||
// Peel unwrap(), expect(), etc.
|
||||
while let Some(&found_name) = METHODS_UNWRAP.iter().find(|&name| &method_name == name)
|
||||
&& let Some(arglist) = method_chain_args(expr, &[found_name])
|
||||
&& let ExprKind::MethodCall(inner_path, ..) = &arglist[0].0.kind
|
||||
&& let ExprKind::MethodCall(inner_path, recv, ..) = &arglist[0].0.kind
|
||||
{
|
||||
// The original type has changed, but we can't use `ty` here anyway, because it has been
|
||||
// moved.
|
||||
method_name = inner_path.ident.name.as_str();
|
||||
expr = recv;
|
||||
}
|
||||
|
||||
if METHODS_POW.iter().any(|&name| method_name == name)
|
||||
|
@ -35,7 +35,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv
|
||||
cx,
|
||||
CAST_SLICE_DIFFERENT_SIZES,
|
||||
expr.span,
|
||||
&format!(
|
||||
format!(
|
||||
"casting between raw pointers to `[{}]` (element size {from_size}) and `[{}]` (element size {to_size}) does not adjust the count",
|
||||
start_ty.ty, end_ty.ty,
|
||||
),
|
||||
|
@ -46,7 +46,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
|
||||
cx,
|
||||
CAST_SLICE_FROM_RAW_PARTS,
|
||||
span,
|
||||
&format!("casting the result of `{func}` to {cast_to}"),
|
||||
format!("casting the result of `{func}` to {cast_to}"),
|
||||
"replace with",
|
||||
format!("core::ptr::slice_{func}({ptr}, {len})"),
|
||||
applicability,
|
||||
|
@ -25,7 +25,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
|
||||
cx,
|
||||
FN_TO_NUMERIC_CAST,
|
||||
expr.span,
|
||||
&format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
|
||||
format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
|
||||
"try",
|
||||
format!("{from_snippet} as usize"),
|
||||
applicability,
|
||||
|
@ -23,7 +23,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
|
||||
cx,
|
||||
FN_TO_NUMERIC_CAST_ANY,
|
||||
expr.span,
|
||||
&format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
|
||||
format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
|
||||
"did you mean to invoke the function?",
|
||||
format!("{from_snippet}() as {cast_to}"),
|
||||
applicability,
|
||||
|
@ -24,7 +24,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
|
||||
cx,
|
||||
FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
|
||||
expr.span,
|
||||
&format!("casting function pointer `{from_snippet}` to `{cast_to}`, which truncates the value"),
|
||||
format!("casting function pointer `{from_snippet}` to `{cast_to}`, which truncates the value"),
|
||||
"try",
|
||||
format!("{from_snippet} as usize"),
|
||||
applicability,
|
||||
|
@ -62,8 +62,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) {
|
||||
// we omit following `cast`:
|
||||
let omit_cast = if let ExprKind::Call(func, []) = cast_expr.kind
|
||||
&& let ExprKind::Path(ref qpath @ QPath::Resolved(None, path)) = func.kind
|
||||
&& let Some(method_defid) = path.res.opt_def_id()
|
||||
{
|
||||
let method_defid = path.res.def_id();
|
||||
if cx.tcx.is_diagnostic_item(sym::ptr_null, method_defid) {
|
||||
OmitFollowedCastReason::Null(qpath)
|
||||
} else if cx.tcx.is_diagnostic_item(sym::ptr_null_mut, method_defid) {
|
||||
|
@ -36,7 +36,7 @@ pub(super) fn check<'tcx>(
|
||||
PTR_CAST_CONSTNESS,
|
||||
expr.span,
|
||||
"`as` casting between raw pointers while changing only its constness",
|
||||
&format!("try `pointer::cast_{constness}`, a safer alternative"),
|
||||
format!("try `pointer::cast_{constness}`, a safer alternative"),
|
||||
format!("{}.cast_{constness}()", sugg.maybe_par()),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
|
@ -51,7 +51,7 @@ pub(super) fn check<'tcx>(
|
||||
cx,
|
||||
UNNECESSARY_CAST,
|
||||
expr.span,
|
||||
&format!(
|
||||
format!(
|
||||
"casting raw pointers to the same type and constness is unnecessary (`{cast_from}` -> `{cast_to}`)"
|
||||
),
|
||||
"try",
|
||||
@ -166,7 +166,7 @@ pub(super) fn check<'tcx>(
|
||||
cx,
|
||||
UNNECESSARY_CAST,
|
||||
expr.span,
|
||||
&format!("casting to the same type is unnecessary (`{cast_from}` -> `{cast_to}`)"),
|
||||
format!("casting to the same type is unnecessary (`{cast_from}` -> `{cast_to}`)"),
|
||||
"try",
|
||||
if needs_block {
|
||||
format!("{{ {cast_str} }}")
|
||||
@ -209,7 +209,7 @@ fn lint_unnecessary_cast(
|
||||
cx,
|
||||
UNNECESSARY_CAST,
|
||||
expr.span,
|
||||
&format!("casting {literal_kind_name} literal to `{cast_to}` is unnecessary"),
|
||||
format!("casting {literal_kind_name} literal to `{cast_to}` is unnecessary"),
|
||||
"try",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
|
@ -121,7 +121,7 @@ impl CognitiveComplexity {
|
||||
cx,
|
||||
COGNITIVE_COMPLEXITY,
|
||||
fn_span,
|
||||
&format!(
|
||||
format!(
|
||||
"the function has a cognitive complexity of ({cc}/{})",
|
||||
self.limit.limit()
|
||||
),
|
||||
|
@ -70,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead {
|
||||
}
|
||||
}
|
||||
|
||||
fn match_acceptable_type(cx: &LateContext<'_>, local: &LetStmt<'_>, collections: &[rustc_span::Symbol]) -> bool {
|
||||
fn match_acceptable_type(cx: &LateContext<'_>, local: &LetStmt<'_>, collections: &[Symbol]) -> bool {
|
||||
let ty = cx.typeck_results().pat_ty(local.pat);
|
||||
collections.iter().any(|&sym| is_type_diagnostic_item(cx, ty, sym))
|
||||
// String type is a lang item but not a diagnostic item for now so we need a separate check
|
||||
|
@ -254,6 +254,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
||||
crate::large_include_file::LARGE_INCLUDE_FILE_INFO,
|
||||
crate::large_stack_arrays::LARGE_STACK_ARRAYS_INFO,
|
||||
crate::large_stack_frames::LARGE_STACK_FRAMES_INFO,
|
||||
crate::legacy_numeric_constants::LEGACY_NUMERIC_CONSTANTS_INFO,
|
||||
crate::len_zero::COMPARISON_TO_EMPTY_INFO,
|
||||
crate::len_zero::LEN_WITHOUT_IS_EMPTY_INFO,
|
||||
crate::len_zero::LEN_ZERO_INFO,
|
||||
@ -678,6 +679,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
||||
crate::trait_bounds::TYPE_REPETITION_IN_BOUNDS_INFO,
|
||||
crate::transmute::CROSSPOINTER_TRANSMUTE_INFO,
|
||||
crate::transmute::EAGER_TRANSMUTE_INFO,
|
||||
crate::transmute::MISSING_TRANSMUTE_ANNOTATIONS_INFO,
|
||||
crate::transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS_INFO,
|
||||
crate::transmute::TRANSMUTE_BYTES_TO_STR_INFO,
|
||||
crate::transmute::TRANSMUTE_FLOAT_TO_INT_INFO,
|
||||
|
@ -100,7 +100,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
|
||||
cx,
|
||||
DEFAULT_TRAIT_ACCESS,
|
||||
expr.span,
|
||||
&format!("calling `{replacement}` is more clear than this expression"),
|
||||
format!("calling `{replacement}` is more clear than this expression"),
|
||||
"try",
|
||||
replacement,
|
||||
Applicability::Unspecified, // First resolve the TODO above
|
||||
@ -243,7 +243,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
|
||||
first_assign.unwrap().span,
|
||||
"field assignment outside of initializer for an instance created with Default::default()",
|
||||
Some(local.span),
|
||||
&format!("consider initializing the variable with `{sugg}` and removing relevant reassignments"),
|
||||
format!("consider initializing the variable with `{sugg}` and removing relevant reassignments"),
|
||||
);
|
||||
self.reassigned_linted.insert(span);
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ fn is_alias(ty: hir::Ty<'_>) -> bool {
|
||||
|
||||
impl LateLintPass<'_> for DefaultConstructedUnitStructs {
|
||||
fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
|
||||
if let hir::ExprKind::Call(fn_expr, &[]) = expr.kind
|
||||
if let ExprKind::Call(fn_expr, &[]) = expr.kind
|
||||
// make sure we have a call to `Default::default`
|
||||
&& let ExprKind::Path(ref qpath @ hir::QPath::TypeRelative(base, _)) = fn_expr.kind
|
||||
// make sure this isn't a type alias:
|
||||
|
@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultIterEmpty {
|
||||
cx,
|
||||
DEFAULT_INSTEAD_OF_ITER_EMPTY,
|
||||
expr.span,
|
||||
&format!("`{path}()` is the more idiomatic way"),
|
||||
format!("`{path}()` is the more idiomatic way"),
|
||||
"try",
|
||||
sugg,
|
||||
applicability,
|
||||
@ -60,7 +60,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultIterEmpty {
|
||||
|
||||
fn make_sugg(
|
||||
cx: &LateContext<'_>,
|
||||
ty_path: &rustc_hir::QPath<'_>,
|
||||
ty_path: &QPath<'_>,
|
||||
ctxt: SyntaxContext,
|
||||
applicability: &mut Applicability,
|
||||
path: &str,
|
||||
|
@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation {
|
||||
item.span,
|
||||
"this union has the default representation",
|
||||
None,
|
||||
&format!(
|
||||
format!(
|
||||
"consider annotating `{}` with `#[repr(C)]` to explicitly specify memory layout",
|
||||
cx.tcx.def_path_str(item.owner_id)
|
||||
),
|
||||
|
@ -79,7 +79,7 @@ fn is_path_self(e: &Expr<'_>) -> bool {
|
||||
fn contains_trait_object(ty: Ty<'_>) -> bool {
|
||||
match ty.kind() {
|
||||
ty::Ref(_, ty, _) => contains_trait_object(*ty),
|
||||
ty::Adt(def, args) => def.is_box() && args[0].as_type().map_or(false, contains_trait_object),
|
||||
Adt(def, args) => def.is_box() && args[0].as_type().map_or(false, contains_trait_object),
|
||||
ty::Dynamic(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
|
@ -11,8 +11,7 @@ use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::traits::Reveal;
|
||||
use rustc_middle::ty::{
|
||||
self, ClauseKind, GenericArgKind, GenericParamDefKind, ParamEnv, ToPredicate, TraitPredicate, Ty,
|
||||
TyCtxt,
|
||||
self, ClauseKind, GenericArgKind, GenericParamDefKind, ParamEnv, ToPredicate, TraitPredicate, Ty, TyCtxt,
|
||||
};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
|
@ -102,11 +102,11 @@ impl DisallowedMacros {
|
||||
DISALLOWED_MACROS,
|
||||
cx.tcx.local_def_id_to_hir_id(derive_src.def_id),
|
||||
mac.span,
|
||||
&msg,
|
||||
msg,
|
||||
add_note,
|
||||
);
|
||||
} else {
|
||||
span_lint_and_then(cx, DISALLOWED_MACROS, mac.span, &msg, add_note);
|
||||
span_lint_and_then(cx, DISALLOWED_MACROS, mac.span, msg, add_note);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedMethods {
|
||||
None => return,
|
||||
};
|
||||
let msg = format!("use of a disallowed method `{}`", conf.path());
|
||||
span_lint_and_then(cx, DISALLOWED_METHODS, expr.span, &msg, |diag| {
|
||||
span_lint_and_then(cx, DISALLOWED_METHODS, expr.span, msg, |diag| {
|
||||
if let Some(reason) = conf.reason() {
|
||||
diag.note(reason);
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedNames {
|
||||
cx,
|
||||
DISALLOWED_NAMES,
|
||||
ident.span,
|
||||
&format!("use of a disallowed/placeholder name `{}`", ident.name),
|
||||
format!("use of a disallowed/placeholder name `{}`", ident.name),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ impl EarlyLintPass for DisallowedScriptIdents {
|
||||
cx,
|
||||
DISALLOWED_SCRIPT_IDENTS,
|
||||
span,
|
||||
&format!(
|
||||
format!(
|
||||
"identifier `{symbol_str}` has a Unicode script that is not allowed by configuration: {}",
|
||||
script.full_name()
|
||||
),
|
||||
|
@ -127,7 +127,7 @@ fn emit(cx: &LateContext<'_>, name: &str, span: Span, conf: &DisallowedPath) {
|
||||
cx,
|
||||
DISALLOWED_TYPES,
|
||||
span,
|
||||
&format!("`{name}` is not allowed according to config"),
|
||||
format!("`{name}` is not allowed according to config"),
|
||||
|diag| {
|
||||
if let Some(reason) = conf.reason() {
|
||||
diag.note(reason);
|
||||
|
@ -129,9 +129,9 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
|
||||
cx,
|
||||
lint,
|
||||
expr.span,
|
||||
&msg,
|
||||
msg,
|
||||
note_span,
|
||||
&format!("argument has type `{arg_ty}`"),
|
||||
format!("argument has type `{arg_ty}`"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ impl EarlyLintPass for DuplicateMod {
|
||||
cx,
|
||||
DUPLICATE_MOD,
|
||||
multi_span,
|
||||
&format!("file is loaded as a module multiple times: `{}`", local_path.display()),
|
||||
format!("file is loaded as a module multiple times: `{}`", local_path.display()),
|
||||
None,
|
||||
"replace all but one `mod` item with `use` items",
|
||||
);
|
||||
|
@ -197,7 +197,7 @@ fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: Prefix
|
||||
cx,
|
||||
lint.as_lint(),
|
||||
expr.span,
|
||||
&format!(
|
||||
format!(
|
||||
"usage of the {}`{ty}::{}`{}",
|
||||
if prefix == Prefix::From { "function " } else { "" },
|
||||
lint.as_name(prefix),
|
||||
|
@ -186,7 +186,7 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
|
||||
cx,
|
||||
MAP_ENTRY,
|
||||
expr.span,
|
||||
&format!("usage of `contains_key` followed by `insert` on a `{}`", map_ty.name()),
|
||||
format!("usage of `contains_key` followed by `insert` on a `{}`", map_ty.name()),
|
||||
"try",
|
||||
sugg,
|
||||
app,
|
||||
|
@ -177,7 +177,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn fake_read(&mut self, _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
|
||||
fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> {
|
||||
|
@ -3,14 +3,14 @@ use clippy_utils::higher::VecArgs;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::ty::type_diagnostic_name;
|
||||
use clippy_utils::usage::{local_used_after_expr, local_used_in};
|
||||
use clippy_utils::{get_path_from_caller_to_method_type, higher, is_adjusted, path_to_local, path_to_local_id};
|
||||
use clippy_utils::{get_path_from_caller_to_method_type, is_adjusted, path_to_local, path_to_local_id};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BindingAnnotation, Expr, ExprKind, FnRetTy, Param, PatKind, QPath, TyKind, Unsafety};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::{
|
||||
self, Binder, ClosureArgs, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, RegionKind,
|
||||
Ty, TypeVisitableExt, TypeckResults,
|
||||
self, Binder, ClosureArgs, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, RegionKind, Ty,
|
||||
TypeVisitableExt, TypeckResults,
|
||||
};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::symbol::sym;
|
||||
@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
|
||||
|
||||
if body.value.span.from_expansion() {
|
||||
if body.params.is_empty() {
|
||||
if let Some(VecArgs::Vec(&[])) = higher::VecArgs::hir(cx, body.value) {
|
||||
if let Some(VecArgs::Vec(&[])) = VecArgs::hir(cx, body.value) {
|
||||
// replace `|| vec![]` with `Vec::new`
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
|
@ -120,7 +120,7 @@ impl ExcessiveBools {
|
||||
cx,
|
||||
FN_PARAMS_EXCESSIVE_BOOLS,
|
||||
span,
|
||||
&format!("more than {} bools in function parameters", self.max_fn_params_bools),
|
||||
format!("more than {} bools in function parameters", self.max_fn_params_bools),
|
||||
None,
|
||||
"consider refactoring bools into two-variant enums",
|
||||
);
|
||||
@ -145,7 +145,7 @@ impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
|
||||
cx,
|
||||
STRUCT_EXCESSIVE_BOOLS,
|
||||
item.span,
|
||||
&format!("more than {} bools in a struct", self.max_struct_bools),
|
||||
format!("more than {} bools in a struct", self.max_struct_bools),
|
||||
None,
|
||||
"consider using a state machine or refactoring bools into two-variant enums",
|
||||
);
|
||||
|
@ -38,7 +38,7 @@ declare_clippy_lint! {
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Warns on any exported `structs`s that are not tagged `#[non_exhaustive]`
|
||||
/// Warns on any exported `struct`s that are not tagged `#[non_exhaustive]`
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Exhaustive structs are typically fine, but a project which does
|
||||
|
@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
|
||||
cx,
|
||||
EXPLICIT_WRITE,
|
||||
expr.span,
|
||||
&format!("use of `{used}.unwrap()`"),
|
||||
format!("use of `{used}.unwrap()`"),
|
||||
"try",
|
||||
format!("{prefix}{sugg_mac}!({inputs_snippet})"),
|
||||
applicability,
|
||||
|
@ -110,11 +110,11 @@ impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> {
|
||||
.map_or(param.span, |bound_span| param.span.with_hi(bound_span.hi()))
|
||||
}
|
||||
|
||||
fn emit_help(&self, spans: Vec<Span>, msg: &str, help: &'static str) {
|
||||
fn emit_help(&self, spans: Vec<Span>, msg: String, help: &'static str) {
|
||||
span_lint_and_help(self.cx, EXTRA_UNUSED_TYPE_PARAMETERS, spans, msg, None, help);
|
||||
}
|
||||
|
||||
fn emit_sugg(&self, spans: Vec<Span>, msg: &str, help: &'static str) {
|
||||
fn emit_sugg(&self, spans: Vec<Span>, msg: String, help: &'static str) {
|
||||
let suggestions: Vec<(Span, String)> = spans.iter().copied().zip(std::iter::repeat(String::new())).collect();
|
||||
span_lint_and_then(self.cx, EXTRA_UNUSED_TYPE_PARAMETERS, spans, msg, |diag| {
|
||||
diag.multipart_suggestion(help, suggestions, Applicability::MachineApplicable);
|
||||
@ -167,7 +167,7 @@ impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> {
|
||||
.iter()
|
||||
.map(|(_, param)| self.get_bound_span(param))
|
||||
.collect::<Vec<_>>();
|
||||
self.emit_help(spans, &msg, help);
|
||||
self.emit_help(spans, msg, help);
|
||||
} else {
|
||||
let spans = if explicit_params.len() == extra_params.len() {
|
||||
vec![self.generics.span] // Remove the entire list of generics
|
||||
@ -196,7 +196,7 @@ impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> {
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
self.emit_sugg(spans, &msg, help);
|
||||
self.emit_sugg(spans, msg, help);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
|
||||
LitFloatType::Unsuffixed => None,
|
||||
};
|
||||
let (is_whole, is_inf, mut float_str) = match fty {
|
||||
FloatTy::F16 => {
|
||||
FloatTy::F16 | FloatTy::F128 => {
|
||||
// FIXME(f16_f128): do a check like the others when parsing is available
|
||||
return;
|
||||
},
|
||||
@ -97,10 +97,6 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
|
||||
|
||||
(value.fract() == 0.0, value.is_infinite(), formatter.format(value))
|
||||
},
|
||||
FloatTy::F128 => {
|
||||
// FIXME(f16_f128): do a check like the others when parsing is available
|
||||
return;
|
||||
},
|
||||
};
|
||||
|
||||
if is_inf {
|
||||
|
@ -552,9 +552,9 @@ fn is_testing_negative(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) -
|
||||
/// Returns true iff expr is some zero literal
|
||||
fn is_zero(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
match constant_simple(cx, cx.typeck_results(), expr) {
|
||||
Some(Constant::Int(i)) => i == 0,
|
||||
Some(Constant::F32(f)) => f == 0.0,
|
||||
Some(Constant::F64(f)) => f == 0.0,
|
||||
Some(Int(i)) => i == 0,
|
||||
Some(F32(f)) => f == 0.0,
|
||||
Some(F64(f)) => f == 0.0,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -401,7 +401,7 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> {
|
||||
self.cx,
|
||||
FORMAT_IN_FORMAT_ARGS,
|
||||
self.macro_call.span,
|
||||
&format!("`format!` in `{name}!` args"),
|
||||
format!("`format!` in `{name}!` args"),
|
||||
|diag| {
|
||||
diag.help(format!(
|
||||
"combine the `format!(..)` arguments with the outer `{name}!(..)` call"
|
||||
@ -431,7 +431,7 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> {
|
||||
cx,
|
||||
TO_STRING_IN_FORMAT_ARGS,
|
||||
to_string_span.with_lo(receiver.span.hi()),
|
||||
&format!("`to_string` applied to a type that implements `Display` in `{name}!` args"),
|
||||
format!("`to_string` applied to a type that implements `Display` in `{name}!` args"),
|
||||
"remove this",
|
||||
String::new(),
|
||||
Applicability::MachineApplicable,
|
||||
@ -441,7 +441,7 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> {
|
||||
cx,
|
||||
TO_STRING_IN_FORMAT_ARGS,
|
||||
value.span,
|
||||
&format!("`to_string` applied to a type that implements `Display` in `{name}!` args"),
|
||||
format!("`to_string` applied to a type that implements `Display` in `{name}!` args"),
|
||||
"use this",
|
||||
format!(
|
||||
"{}{:*>n_needed_derefs$}{receiver_snippet}",
|
||||
|
@ -214,7 +214,7 @@ impl<'a, 'tcx> FormatImplExpr<'a, 'tcx> {
|
||||
self.cx,
|
||||
RECURSIVE_FORMAT_IMPL,
|
||||
self.expr.span,
|
||||
&format!("using `self` as `{name}` in `impl {name}` will cause infinite recursion"),
|
||||
format!("using `self` as `{name}` in `impl {name}` will cause infinite recursion"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -235,7 +235,7 @@ impl<'a, 'tcx> FormatImplExpr<'a, 'tcx> {
|
||||
self.cx,
|
||||
PRINT_IN_FORMAT_IMPL,
|
||||
macro_call.span,
|
||||
&format!("use of `{name}!` in `{}` impl", self.format_trait_impl.name),
|
||||
format!("use of `{name}!` in `{}` impl", self.format_trait_impl.name),
|
||||
"replace with",
|
||||
if let Some(formatter_name) = self.format_trait_impl.formatter_name {
|
||||
format!("{replacement}!({formatter_name}, ..)")
|
||||
|
@ -151,12 +151,12 @@ fn check_assign(cx: &EarlyContext<'_>, expr: &Expr) {
|
||||
cx,
|
||||
SUSPICIOUS_ASSIGNMENT_FORMATTING,
|
||||
eqop_span,
|
||||
&format!(
|
||||
format!(
|
||||
"this looks like you are trying to use `.. {op}= ..`, but you \
|
||||
really are doing `.. = ({op} ..)`"
|
||||
),
|
||||
None,
|
||||
&format!("to remove this lint, use either `{op}=` or `= {op}`"),
|
||||
format!("to remove this lint, use either `{op}=` or `= {op}`"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -187,12 +187,12 @@ fn check_unop(cx: &EarlyContext<'_>, expr: &Expr) {
|
||||
cx,
|
||||
SUSPICIOUS_UNARY_OP_FORMATTING,
|
||||
eqop_span,
|
||||
&format!(
|
||||
format!(
|
||||
"by not having a space between `{binop_str}` and `{unop_str}` it looks like \
|
||||
`{binop_str}{unop_str}` is a single operator"
|
||||
),
|
||||
None,
|
||||
&format!("put a space between `{binop_str}` and `{unop_str}` and remove the space after `{unop_str}`"),
|
||||
format!("put a space between `{binop_str}` and `{unop_str}` and remove the space after `{unop_str}`"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -215,6 +215,7 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) {
|
||||
// it’s bad when there is a ‘\n’ after the “else”
|
||||
&& let Some(else_snippet) = snippet_opt(cx, else_span)
|
||||
&& let Some((pre_else, post_else)) = else_snippet.split_once("else")
|
||||
&& !else_snippet.contains('/')
|
||||
&& let Some((_, post_else_post_eol)) = post_else.split_once('\n')
|
||||
{
|
||||
// Allow allman style braces `} \n else \n {`
|
||||
@ -238,9 +239,9 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) {
|
||||
cx,
|
||||
SUSPICIOUS_ELSE_FORMATTING,
|
||||
else_span,
|
||||
&format!("this is an `else {else_desc}` but the formatting might hide it"),
|
||||
format!("this is an `else {else_desc}` but the formatting might hide it"),
|
||||
None,
|
||||
&format!(
|
||||
format!(
|
||||
"to remove this lint, remove the `else` or remove the new line between \
|
||||
`else` and `{else_desc}`",
|
||||
),
|
||||
@ -308,9 +309,9 @@ fn check_missing_else(cx: &EarlyContext<'_>, first: &Expr, second: &Expr) {
|
||||
cx,
|
||||
SUSPICIOUS_ELSE_FORMATTING,
|
||||
else_span,
|
||||
&format!("this looks like {looks_like} but the `else` is missing"),
|
||||
format!("this looks like {looks_like} but the `else` is missing"),
|
||||
None,
|
||||
&format!("to remove this lint, add the missing `else` or add a new line before {next_thing}",),
|
||||
format!("to remove this lint, add the missing `else` or add a new line before {next_thing}",),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ use clippy_utils::ty::is_c_void;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{Expr, ExprKind, QPath};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::{RawPtr};
|
||||
use rustc_middle::ty::RawPtr;
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::sym;
|
||||
|
||||
@ -52,7 +52,7 @@ impl LateLintPass<'_> for FromRawWithVoidPtr {
|
||||
cx,
|
||||
FROM_RAW_WITH_VOID_PTR,
|
||||
expr.span,
|
||||
&msg,
|
||||
msg,
|
||||
Some(arg.span),
|
||||
"cast this to a pointer of the appropriate type",
|
||||
);
|
||||
|
@ -142,7 +142,7 @@ fn check_must_use_candidate<'tcx>(
|
||||
item_span: Span,
|
||||
item_id: hir::OwnerId,
|
||||
fn_span: Span,
|
||||
msg: &str,
|
||||
msg: &'static str,
|
||||
) {
|
||||
if has_mutable_arg(cx, body)
|
||||
|| mutates_static(cx, body)
|
||||
@ -207,9 +207,7 @@ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, tys: &mut DefIdSet)
|
||||
},
|
||||
ty::Tuple(args) => args.iter().any(|ty| is_mutable_ty(cx, ty, tys)),
|
||||
ty::Array(ty, _) | ty::Slice(ty) => is_mutable_ty(cx, ty, tys),
|
||||
ty::RawPtr(ty, mutbl) | ty::Ref(_, ty, mutbl) => {
|
||||
mutbl == hir::Mutability::Mut || is_mutable_ty(cx, ty, tys)
|
||||
},
|
||||
ty::RawPtr(ty, mutbl) | ty::Ref(_, ty, mutbl) => mutbl == hir::Mutability::Mut || is_mutable_ty(cx, ty, tys),
|
||||
// calling something constitutes a side effect, so return true on all callables
|
||||
// also never calls need not be used, so return true for them, too
|
||||
_ => true,
|
||||
|
@ -2,7 +2,7 @@ use rustc_errors::Diag;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::{self, Adt, Ty};
|
||||
use rustc_middle::ty::{Adt, Ty};
|
||||
use rustc_span::{sym, Span};
|
||||
|
||||
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
|
||||
@ -25,7 +25,7 @@ fn result_err_ty<'tcx>(
|
||||
.tcx
|
||||
.instantiate_bound_regions_with_erased(cx.tcx.fn_sig(id).instantiate_identity().output())
|
||||
&& is_type_diagnostic_item(cx, ty, sym::Result)
|
||||
&& let ty::Adt(_, args) = ty.kind()
|
||||
&& let Adt(_, args) = ty.kind()
|
||||
{
|
||||
let err_ty = args.type_at(1);
|
||||
Some((hir_ty, err_ty))
|
||||
|
@ -59,7 +59,7 @@ fn check_arg_number(cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, fn_span: Span,
|
||||
cx,
|
||||
TOO_MANY_ARGUMENTS,
|
||||
fn_span,
|
||||
&format!("this function has too many arguments ({args}/{too_many_arguments_threshold})"),
|
||||
format!("this function has too many arguments ({args}/{too_many_arguments_threshold})"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ pub(super) fn check_fn(
|
||||
cx,
|
||||
TOO_MANY_LINES,
|
||||
span,
|
||||
&format!("this function has too many lines ({line_count}/{too_many_lines_threshold})"),
|
||||
format!("this function has too many lines ({line_count}/{too_many_lines_threshold})"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -117,9 +117,9 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
|
||||
cx,
|
||||
IF_THEN_SOME_ELSE_NONE,
|
||||
expr.span,
|
||||
&format!("this could be simplified with `bool::{method_name}`"),
|
||||
format!("this could be simplified with `bool::{method_name}`"),
|
||||
None,
|
||||
&help,
|
||||
help,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
|
||||
cx,
|
||||
IMPLICIT_HASHER,
|
||||
target.span(),
|
||||
&format!(
|
||||
format!(
|
||||
"impl for `{}` should be generalized over different hashers",
|
||||
target.type_name()
|
||||
),
|
||||
@ -187,7 +187,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
|
||||
cx,
|
||||
IMPLICIT_HASHER,
|
||||
target.span(),
|
||||
&format!(
|
||||
format!(
|
||||
"parameter of type `{}` should be generalized over different hashers",
|
||||
target.type_name()
|
||||
),
|
||||
|
@ -56,7 +56,7 @@ fn emit_lint(
|
||||
index: usize,
|
||||
// The bindings that were implied, used for suggestion purposes since removing a bound with associated types
|
||||
// means we might need to then move it to a different bound
|
||||
implied_bindings: &[rustc_hir::TypeBinding<'_>],
|
||||
implied_bindings: &[TypeBinding<'_>],
|
||||
bound: &ImplTraitBound<'_>,
|
||||
) {
|
||||
let implied_by = snippet(cx, bound.span, "..");
|
||||
@ -65,7 +65,7 @@ fn emit_lint(
|
||||
cx,
|
||||
IMPLIED_BOUNDS_IN_IMPLS,
|
||||
poly_trait.span,
|
||||
&format!("this bound is already specified as the supertrait of `{implied_by}`"),
|
||||
format!("this bound is already specified as the supertrait of `{implied_by}`"),
|
||||
|diag| {
|
||||
// If we suggest removing a bound, we may also need to extend the span
|
||||
// to include the `+` token that is ahead or behind,
|
||||
|
@ -33,7 +33,7 @@ declare_clippy_lint! {
|
||||
///
|
||||
/// To fix this problem, either increase your MSRV or use another item
|
||||
/// available in your current MSRV.
|
||||
#[clippy::version = "1.77.0"]
|
||||
#[clippy::version = "1.78.0"]
|
||||
pub INCOMPATIBLE_MSRV,
|
||||
suspicious,
|
||||
"ensures that all items used in the crate are available for the current MSRV"
|
||||
@ -104,7 +104,7 @@ impl IncompatibleMsrv {
|
||||
cx,
|
||||
INCOMPATIBLE_MSRV,
|
||||
span,
|
||||
&format!(
|
||||
format!(
|
||||
"current MSRV (Minimum Supported Rust Version) is `{}` but this item is stable since `{version}`",
|
||||
self.msrv
|
||||
),
|
||||
|
@ -132,20 +132,20 @@ fn show_lint(cx: &LateContext<'_>, item: &ImplItem<'_>) {
|
||||
cx,
|
||||
INHERENT_TO_STRING_SHADOW_DISPLAY,
|
||||
item.span,
|
||||
&format!(
|
||||
format!(
|
||||
"type `{self_type}` implements inherent method `to_string(&self) -> String` which shadows the implementation of `Display`"
|
||||
),
|
||||
None,
|
||||
&format!("remove the inherent method from type `{self_type}`"),
|
||||
format!("remove the inherent method from type `{self_type}`"),
|
||||
);
|
||||
} else {
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
INHERENT_TO_STRING,
|
||||
item.span,
|
||||
&format!("implementation of inherent method `to_string(&self) -> String` for type `{self_type}`"),
|
||||
format!("implementation of inherent method `to_string(&self) -> String` for type `{self_type}`"),
|
||||
None,
|
||||
&format!("implement trait `Display` for type `{self_type}` instead"),
|
||||
format!("implement trait `Display` for type `{self_type}` instead"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ fn check_attrs(cx: &LateContext<'_>, name: Symbol, attrs: &[Attribute]) {
|
||||
cx,
|
||||
INLINE_FN_WITHOUT_BODY,
|
||||
attr.span,
|
||||
&format!("use of `#[inline]` on trait method `{name}` which has no body"),
|
||||
format!("use of `#[inline]` on trait method `{name}` which has no body"),
|
||||
|diag| {
|
||||
diag.suggest_remove_item(cx, attr.span, "remove", Applicability::MachineApplicable);
|
||||
},
|
||||
|
@ -1,5 +1,5 @@
|
||||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_utils::diagnostics::{self, span_lint_and_sugg};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::ty;
|
||||
@ -149,7 +149,7 @@ fn print_unchecked_duration_subtraction_sugg(
|
||||
let left_expr = snippet_with_context(cx, left_expr.span, ctxt, "<instant>", &mut applicability).0;
|
||||
let right_expr = snippet_with_context(cx, right_expr.span, ctxt, "<duration>", &mut applicability).0;
|
||||
|
||||
diagnostics::span_lint_and_sugg(
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
UNCHECKED_DURATION_SUBTRACTION,
|
||||
expr.span,
|
||||
|
@ -43,7 +43,7 @@ impl LateLintPass<'_> for IntegerDivisionRemainderUsed {
|
||||
cx,
|
||||
INTEGER_DIVISION_REMAINDER_USED,
|
||||
expr.span.source_callsite(),
|
||||
&format!("use of {} has been disallowed in this context", op.node.as_str()),
|
||||
format!("use of {} has been disallowed in this context", op.node.as_str()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ fn err_upcast_comparison(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, alwa
|
||||
cx,
|
||||
INVALID_UPCAST_COMPARISONS,
|
||||
span,
|
||||
&format!(
|
||||
format!(
|
||||
"because of the numeric bounds on `{}` prior to casting, this expression is always {}",
|
||||
snippet(cx, cast_val.span, "the expression"),
|
||||
if always { "true" } else { "false" },
|
||||
@ -88,7 +88,7 @@ fn err_upcast_comparison(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, alwa
|
||||
fn upcast_comparison_bounds_err<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
span: Span,
|
||||
rel: comparisons::Rel,
|
||||
rel: Rel,
|
||||
lhs_bounds: Option<(FullInt, FullInt)>,
|
||||
lhs: &'tcx Expr<'_>,
|
||||
rhs: &'tcx Expr<'_>,
|
||||
|
@ -240,9 +240,9 @@ fn check_fields(cx: &LateContext<'_>, threshold: u64, item: &Item<'_>, fields: &
|
||||
cx,
|
||||
STRUCT_FIELD_NAMES,
|
||||
item.span,
|
||||
&format!("all fields have the same {what}fix: `{value}`"),
|
||||
format!("all fields have the same {what}fix: `{value}`"),
|
||||
None,
|
||||
&format!("remove the {what}fixes"),
|
||||
format!("remove the {what}fixes"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -370,9 +370,9 @@ fn check_variant(cx: &LateContext<'_>, threshold: u64, def: &EnumDef<'_>, item_n
|
||||
cx,
|
||||
ENUM_VARIANT_NAMES,
|
||||
span,
|
||||
&format!("all variants have the same {what}fix: `{value}`"),
|
||||
format!("all variants have the same {what}fix: `{value}`"),
|
||||
None,
|
||||
&format!(
|
||||
format!(
|
||||
"remove the {what}fixes and use full paths to \
|
||||
the variants instead of glob imports"
|
||||
),
|
||||
|
@ -84,7 +84,7 @@ fn check_sig(cx: &LateContext<'_>, name: &str, sig: &FnSig<'_>, fn_id: LocalDefI
|
||||
cx,
|
||||
ITER_NOT_RETURNING_ITERATOR,
|
||||
sig.span,
|
||||
&format!("this method is named `{name}` but its return type does not implement `Iterator`"),
|
||||
format!("this method is named `{name}` but its return type does not implement `Iterator`"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ impl LateLintPass<'_> for IterWithoutIntoIter {
|
||||
cx,
|
||||
INTO_ITER_WITHOUT_ITER,
|
||||
item.span,
|
||||
&format!("`IntoIterator` implemented for a reference type without an `{expected_method_name}` method"),
|
||||
format!("`IntoIterator` implemented for a reference type without an `{expected_method_name}` method"),
|
||||
|diag| {
|
||||
// The suggestion forwards to the `IntoIterator` impl and uses a form of UFCS
|
||||
// to avoid name ambiguities, as there might be an inherent into_iter method
|
||||
@ -258,7 +258,7 @@ impl {self_ty_without_ref} {{
|
||||
cx,
|
||||
ITER_WITHOUT_INTO_ITER,
|
||||
item.span,
|
||||
&format!(
|
||||
format!(
|
||||
"`{}` method without an `IntoIterator` impl for `{self_ty_snippet}`",
|
||||
item.ident
|
||||
),
|
||||
|
@ -71,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeFuture {
|
||||
cx,
|
||||
LARGE_FUTURES,
|
||||
expr.span,
|
||||
&format!("large future with a size of {} bytes", size.bytes()),
|
||||
format!("large future with a size of {} bytes", size.bytes()),
|
||||
"consider `Box::pin` on it",
|
||||
format!("Box::pin({})", snippet(cx, expr.span, "..")),
|
||||
Applicability::Unspecified,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user