Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into rustup
Browse files Browse the repository at this point in the history
  • Loading branch information
flip1995 committed Aug 14, 2023
2 parents f730a26 + b5bfd11 commit 442af5d
Show file tree
Hide file tree
Showing 1,282 changed files with 7,423 additions and 6,288 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ tempfile = { version = "3.2", optional = true }
termize = "0.1"

[dev-dependencies]
ui_test = "0.11.5"
ui_test = "0.17.0"
tester = "0.9"
regex = "1.5"
toml = "0.7.3"
Expand Down
4 changes: 2 additions & 2 deletions book/src/development/adding_lints.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ The process of generating the `.stderr` file is the same, and prepending the
## Rustfix tests

If the lint you are working on is making use of structured suggestions, the test
file should include a `//@run-rustfix` comment at the top. This will
additionally run [rustfix] for that test. Rustfix will apply the suggestions
will create a `.fixed` file by running [rustfix] for that test.
Rustfix will apply the suggestions
from the lint to the code of the test file and compare that to the contents of a
`.fixed` file.

Expand Down
8 changes: 2 additions & 6 deletions book/src/development/speedtest.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,12 @@ accessed by the `SPEEDTEST` (and `SPEEDTEST_*`) environment variables.
To do a simple speed test of a lint (e.g. `allow_attributes`), use this command.

```sh
$ SPEEDTEST=ui TESTNAME="allow_attributes" cargo uitest -- --nocapture
$ SPEEDTEST=ui TESTNAME="allow_attributes" cargo uitest
```

This will test all `ui` tests (`SPEEDTEST=ui`) whose names start with `allow_attributes`. By default, `SPEEDTEST` will
iterate your test 1000 times. But you can change this with `SPEEDTEST_ITERATIONS`.

```sh
$ SPEEDTEST=toml SPEEDTEST_ITERATIONS=100 TESTNAME="semicolon_block" cargo uitest -- --nocapture
$ SPEEDTEST=toml SPEEDTEST_ITERATIONS=100 TESTNAME="semicolon_block" cargo uitest
```

> **WARNING**: Be sure to use `-- --nocapture` at the end of the command to see the average test time. If you don't
> use `-- --nocapture` (e.g. `SPEEDTEST=ui` `TESTNAME="let_underscore_untyped" cargo uitest -- --nocapture`), this
> will not show up.
1 change: 0 additions & 1 deletion clippy_dev/src/update_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,6 @@ fn gen_deprecated_lints_test(lints: &[DeprecatedLint]) -> String {
fn gen_renamed_lints_test(lints: &[RenamedLint]) -> String {
let mut seen_lints = HashSet::new();
let mut res: String = GENERATED_FILE_COMMENT.into();
res.push_str("//@run-rustfix\n\n");
for lint in lints {
if seen_lints.insert(&lint.new_name) {
writeln!(res, "#![allow({})]", lint.new_name).unwrap();
Expand Down
10 changes: 3 additions & 7 deletions clippy_lints/src/incorrect_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use clippy_utils::{get_parent_node, is_res_lang_ctor, last_path_segment, match_d
use rustc_errors::Applicability;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::{Expr, ExprKind, ImplItem, ImplItemKind, ItemKind, LangItem, Node, UnOp};
use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::EarlyBinder;
use rustc_session::{declare_lint_pass, declare_tool_lint};
Expand Down Expand Up @@ -125,7 +126,7 @@ impl LateLintPass<'_> for IncorrectImpls {
if cx.tcx.is_automatically_derived(item.owner_id.to_def_id()) {
return;
}
let ItemKind::Impl(_) = item.kind else {
let ItemKind::Impl(imp) = item.kind else {
return;
};
let ImplItemKind::Fn(_, impl_item_id) = cx.tcx.hir().impl_item(impl_item.impl_item_id()).kind else {
Expand Down Expand Up @@ -188,12 +189,7 @@ impl LateLintPass<'_> for IncorrectImpls {
.diagnostic_items(trait_impl.def_id.krate)
.name_to_id
.get(&sym::Ord)
&& implements_trait(
cx,
trait_impl.self_ty(),
*ord_def_id,
&[],
)
&& implements_trait(cx, hir_ty_to_ty(cx.tcx, imp.self_ty), *ord_def_id, &[])
{
// If the `cmp` call likely needs to be fully qualified in the suggestion
// (like `std::cmp::Ord::cmp`). It's unfortunate we must put this here but we can't
Expand Down
3 changes: 2 additions & 1 deletion clippy_lints/src/macro_use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ struct PathAndSpan {
span: Span,
}

/// `MacroRefData` includes the name of the macro.
/// `MacroRefData` includes the name of the macro
/// and the path from `SourceMap::span_to_filename`.
#[derive(Debug, Clone)]
pub struct MacroRefData {
name: String,
Expand Down
6 changes: 4 additions & 2 deletions clippy_lints/src/manual_retain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::sym;

const ACCEPTABLE_METHODS: [&[&str]; 4] = [
const ACCEPTABLE_METHODS: [&[&str]; 5] = [
&paths::BINARYHEAP_ITER,
&paths::HASHSET_ITER,
&paths::BTREESET_ITER,
&paths::SLICE_INTO,
&paths::VEC_DEQUE_ITER,
];
const ACCEPTABLE_TYPES: [(rustc_span::Symbol, Option<RustcVersion>); 6] = [
const ACCEPTABLE_TYPES: [(rustc_span::Symbol, Option<RustcVersion>); 7] = [
(sym::BinaryHeap, Some(msrvs::BINARY_HEAP_RETAIN)),
(sym::BTreeSet, Some(msrvs::BTREE_SET_RETAIN)),
(sym::BTreeMap, Some(msrvs::BTREE_MAP_RETAIN)),
(sym::HashSet, Some(msrvs::HASH_SET_RETAIN)),
Expand Down
53 changes: 42 additions & 11 deletions clippy_lints/src/methods/iter_overeager_cloned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,36 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{implements_trait, is_copy};
use rustc_errors::Applicability;
use rustc_hir::Expr;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_span::sym;

use super::ITER_OVEREAGER_CLONED;
use crate::redundant_clone::REDUNDANT_CLONE;

#[derive(Clone, Copy)]
pub(super) enum Op<'a> {
// rm `.cloned()`
// e.g. `count`
RmCloned,

// later `.cloned()`
// and add `&` to the parameter of closure parameter
// e.g. `find` `filter`
FixClosure(&'a str, &'a Expr<'a>),

// later `.cloned()`
// e.g. `skip` `take`
LaterCloned,
}

pub(super) fn check<'tcx>(
cx: &LateContext<'tcx>,
expr: &'tcx Expr<'_>,
cloned_call: &'tcx Expr<'_>,
cloned_recv: &'tcx Expr<'_>,
is_count: bool,
op: Op<'tcx>,
needs_into_iter: bool,
) {
let typeck = cx.typeck_results();
Expand All @@ -35,10 +51,9 @@ pub(super) fn check<'tcx>(
return;
}

let (lint, msg, trailing_clone) = if is_count {
(REDUNDANT_CLONE, "unneeded cloning of iterator items", "")
} else {
(ITER_OVEREAGER_CLONED, "unnecessarily eager cloning of iterator items", ".cloned()")
let (lint, msg, trailing_clone) = match op {
Op::RmCloned => (REDUNDANT_CLONE, "unneeded cloning of iterator items", ""),
Op::LaterCloned | Op::FixClosure(_, _) => (ITER_OVEREAGER_CLONED, "unnecessarily eager cloning of iterator items", ".cloned()"),
};

span_lint_and_then(
Expand All @@ -47,11 +62,27 @@ pub(super) fn check<'tcx>(
expr.span,
msg,
|diag| {
let method_span = expr.span.with_lo(cloned_call.span.hi());
if let Some(mut snip) = snippet_opt(cx, method_span) {
snip.push_str(trailing_clone);
let replace_span = expr.span.with_lo(cloned_recv.span.hi());
diag.span_suggestion(replace_span, "try", snip, Applicability::MachineApplicable);
match op {
Op::RmCloned | Op::LaterCloned => {
let method_span = expr.span.with_lo(cloned_call.span.hi());
if let Some(mut snip) = snippet_opt(cx, method_span) {
snip.push_str(trailing_clone);
let replace_span = expr.span.with_lo(cloned_recv.span.hi());
diag.span_suggestion(replace_span, "try", snip, Applicability::MachineApplicable);
}
}
Op::FixClosure(name, predicate_expr) => {
if let Some(predicate) = snippet_opt(cx, predicate_expr.span) {
let new_closure = if let ExprKind::Closure(_) = predicate_expr.kind {
predicate.replacen('|', "|&", 1)
} else {
format!("|&x| {predicate}(x)")
};
let snip = format!(".{name}({new_closure}).cloned()" );
let replace_span = expr.span.with_lo(cloned_recv.span.hi());
diag.span_suggestion(replace_span, "try", snip, Applicability::MachineApplicable);
}
}
}
}
);
Expand Down
24 changes: 17 additions & 7 deletions clippy_lints/src/methods/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3919,7 +3919,7 @@ impl Methods {
}
},
("count", []) if is_trait_method(cx, expr, sym::Iterator) => match method_call(recv) {
Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, true, false),
Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, iter_overeager_cloned::Op::RmCloned , false),
Some((name2 @ ("into_iter" | "iter" | "iter_mut"), recv2, [], _, _)) => {
iter_count::check(cx, expr, recv2, name2);
},
Expand Down Expand Up @@ -3973,6 +3973,13 @@ impl Methods {
string_extend_chars::check(cx, expr, recv, arg);
extend_with_drain::check(cx, expr, recv, arg);
},
(name @ ( "filter" | "find" ) , [arg]) => {
if let Some(("cloned", recv2, [], _span2, _)) = method_call(recv) {
// if `arg` has side-effect, the semantic will change
iter_overeager_cloned::check(cx, expr, recv, recv2,
iter_overeager_cloned::Op::FixClosure(name, arg), false);
}
}
("filter_map", [arg]) => {
unnecessary_filter_map::check(cx, expr, arg, name);
filter_map_bool_then::check(cx, expr, arg, call_span);
Expand All @@ -3987,7 +3994,7 @@ impl Methods {
},
("flatten", []) => match method_call(recv) {
Some(("map", recv, [map_arg], map_span, _)) => map_flatten::check(cx, expr, recv, map_arg, map_span),
Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, true),
Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, iter_overeager_cloned::Op::LaterCloned , true),
_ => {},
},
("fold", [init, acc]) => {
Expand Down Expand Up @@ -4021,7 +4028,8 @@ impl Methods {
},
("last", []) => {
if let Some(("cloned", recv2, [], _span2, _)) = method_call(recv) {
iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
iter_overeager_cloned::check(cx, expr, recv, recv2,
iter_overeager_cloned::Op::LaterCloned , false);
}
},
("lock", []) => {
Expand Down Expand Up @@ -4058,7 +4066,7 @@ impl Methods {
("next", []) => {
if let Some((name2, recv2, args2, _, _)) = method_call(recv) {
match (name2, args2) {
("cloned", []) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false),
("cloned", []) => iter_overeager_cloned::check(cx, expr, recv, recv2, iter_overeager_cloned::Op::LaterCloned, false),
("filter", [arg]) => filter_next::check(cx, expr, recv2, arg),
("filter_map", [arg]) => filter_map_next::check(cx, expr, recv2, arg, &self.msrv),
("iter", []) => iter_next_slice::check(cx, expr, recv2),
Expand All @@ -4071,7 +4079,7 @@ impl Methods {
},
("nth", [n_arg]) => match method_call(recv) {
Some(("bytes", recv2, [], _, _)) => bytes_nth::check(cx, expr, recv2, n_arg),
Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false),
Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, iter_overeager_cloned::Op::LaterCloned , false),
Some(("iter", recv2, [], _, _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, false),
Some(("iter_mut", recv2, [], _, _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, true),
_ => iter_nth_zero::check(cx, expr, recv, n_arg),
Expand Down Expand Up @@ -4126,7 +4134,8 @@ impl Methods {
iter_skip_zero::check(cx, expr, arg);

if let Some(("cloned", recv2, [], _span2, _)) = method_call(recv) {
iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
iter_overeager_cloned::check(cx, expr, recv, recv2,
iter_overeager_cloned::Op::LaterCloned , false);
}
}
("sort", []) => {
Expand All @@ -4152,7 +4161,8 @@ impl Methods {
("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg),
("take", [_arg]) => {
if let Some(("cloned", recv2, [], _span2, _)) = method_call(recv) {
iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
iter_overeager_cloned::check(cx, expr, recv, recv2,
iter_overeager_cloned::Op::LaterCloned, false);
}
},
("take", []) => needless_option_take::check(cx, expr, recv),
Expand Down
3 changes: 2 additions & 1 deletion clippy_lints/src/methods/unnecessary_sort_by.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Closure, Expr, ExprKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QPath};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, GenericArgKind};
use rustc_middle::ty;
use rustc_middle::ty::GenericArgKind;
use rustc_span::sym;
use rustc_span::symbol::Ident;
use std::iter;
Expand Down
1 change: 1 addition & 0 deletions clippy_lints/src/missing_inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ fn is_executable_or_proc_macro(cx: &LateContext<'_>) -> bool {
use rustc_session::config::CrateType;

cx.tcx
.sess
.crate_types()
.iter()
.any(|t: &CrateType| matches!(t, CrateType::Executable | CrateType::ProcMacro))
Expand Down
4 changes: 0 additions & 4 deletions clippy_lints/src/mutable_debug_assertion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,6 @@ impl<'a, 'tcx> Visitor<'tcx> for MutArgVisitor<'a, 'tcx> {
self.found = true;
return;
},
ExprKind::If(..) => {
self.found = true;
return;
},
ExprKind::Path(_) => {
if let Some(adj) = self.cx.typeck_results().adjustments().get(expr.hir_id) {
if adj
Expand Down
16 changes: 3 additions & 13 deletions clippy_lints/src/redundant_locals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ use clippy_utils::is_from_proc_macro;
use clippy_utils::ty::needs_ordered_drop;
use rustc_ast::Mutability;
use rustc_hir::def::Res;
use rustc_hir::{
BindingAnnotation, ByRef, Expr, ExprKind, HirId, Local, Node, Pat, PatKind, QPath,
};
use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, HirId, Local, Node, Pat, PatKind, QPath};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::{in_external_macro, is_from_async_await};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::Ident;
use rustc_span::DesugaringKind;
Expand Down Expand Up @@ -72,9 +70,6 @@ impl<'tcx> LateLintPass<'tcx> for RedundantLocals {
// the local is user-controlled
if !in_external_macro(cx.sess(), local.span);
if !is_from_proc_macro(cx, expr);
// Async function parameters are lowered into the closure body, so we can't lint them.
// see `lower_maybe_async_body` in `rust_ast_lowering`
if !is_from_async_await(local.span);
then {
span_lint_and_help(
cx,
Expand Down Expand Up @@ -111,12 +106,7 @@ fn affects_assignments(cx: &LateContext<'_>, mutability: Mutability, bind: HirId
}

/// Check if a rebinding of a local affects the code's drop behavior.
fn affects_drop_behavior<'tcx>(
cx: &LateContext<'tcx>,
bind: HirId,
rebind: HirId,
rebind_expr: &Expr<'tcx>,
) -> bool {
fn affects_drop_behavior<'tcx>(cx: &LateContext<'tcx>, bind: HirId, rebind: HirId, rebind_expr: &Expr<'tcx>) -> bool {
let hir = cx.tcx.hir();

// the rebinding is in a different scope than the original binding
Expand Down
10 changes: 5 additions & 5 deletions clippy_lints/src/same_name_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
if matches!(cx.tcx.def_kind(id.owner_id), DefKind::Impl { .. })
&& let item = cx.tcx.hir().item(id)
&& let ItemKind::Impl(Impl {
items,
of_trait,
self_ty,
..
}) = &item.kind
items,
of_trait,
self_ty,
..
}) = &item.kind
&& let TyKind::Path(QPath::Resolved(_, Path { res, .. })) = self_ty.kind
{
if !map.contains_key(res) {
Expand Down
4 changes: 2 additions & 2 deletions clippy_utils/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ pub fn span_lint_and_help<T: LintContext>(
cx.struct_span_lint(lint, span, msg.to_string(), |diag| {
let help = help.to_string();
if let Some(help_span) = help_span {
diag.span_help(help_span, help.to_string());
diag.span_help(help_span, help);
} else {
diag.help(help.to_string());
diag.help(help);
}
docs_link(diag, lint);
diag
Expand Down
2 changes: 1 addition & 1 deletion clippy_utils/src/msrvs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ macro_rules! msrv_aliases {
// names may refer to stabilized feature flags or library items
msrv_aliases! {
1,71,0 { TUPLE_ARRAY_CONVERSIONS }
1,70,0 { OPTION_IS_SOME_AND }
1,70,0 { OPTION_IS_SOME_AND, BINARY_HEAP_RETAIN }
1,68,0 { PATH_MAIN_SEPARATOR_STR }
1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS }
1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE }
Expand Down
1 change: 1 addition & 0 deletions clippy_utils/src/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [
];
#[cfg(feature = "internal")]
pub const DIAGNOSTIC_BUILDER: [&str; 3] = ["rustc_errors", "diagnostic_builder", "DiagnosticBuilder"];
pub const BINARYHEAP_ITER: [&str; 5] = ["alloc", "collections", "binary_heap", "BinaryHeap", "iter"];
pub const BTREEMAP_CONTAINS_KEY: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "contains_key"];
pub const BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"];
pub const BTREESET_ITER: [&str; 6] = ["alloc", "collections", "btree", "set", "BTreeSet", "iter"];
Expand Down
Loading

0 comments on commit 442af5d

Please sign in to comment.