1
Fork 0

Auto merge of #13157 - flip1995:rustup, r=flip1995

Rustup

r? `@ghost`

changelog: none
This commit is contained in:
bors 2024-07-25 16:25:19 +00:00
commit 37f4fbb929
26 changed files with 112 additions and 76 deletions

View file

@ -1,6 +1,6 @@
[package] [package]
name = "clippy" name = "clippy"
version = "0.1.81" version = "0.1.82"
description = "A bunch of helpful lints to avoid common pitfalls in Rust" description = "A bunch of helpful lints to avoid common pitfalls in Rust"
repository = "https://github.com/rust-lang/rust-clippy" repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md" readme = "README.md"

View file

@ -1,6 +1,6 @@
[package] [package]
name = "clippy_config" name = "clippy_config"
version = "0.1.81" version = "0.1.82"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -1,6 +1,6 @@
[package] [package]
name = "clippy_lints" name = "clippy_lints"
version = "0.1.81" version = "0.1.82"
description = "A bunch of helpful lints to avoid common pitfalls in Rust" description = "A bunch of helpful lints to avoid common pitfalls in Rust"
repository = "https://github.com/rust-lang/rust-clippy" repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md" readme = "README.md"

View file

@ -15,7 +15,7 @@ use rustc_middle::ty::{
use rustc_session::declare_lint_pass; use rustc_session::declare_lint_pass;
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use rustc_trait_selection::error_reporting::traits::InferCtxtExt as _; use rustc_trait_selection::error_reporting::InferCtxtErrorExt as _;
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
@ -178,7 +178,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
// 'cuz currently nothing changes after deleting this check. // 'cuz currently nothing changes after deleting this check.
local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr) local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr)
}) { }) {
match cx.tcx.infer_ctxt().build().type_implements_fn_trait( match cx.tcx.infer_ctxt().build().err_ctxt().type_implements_fn_trait(
cx.param_env, cx.param_env,
Binder::bind_with_vars(callee_ty_adjusted, List::empty()), Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
ty::PredicatePolarity::Positive, ty::PredicatePolarity::Positive,

View file

@ -16,6 +16,7 @@ use clippy_utils::source::snippet_opt;
use clippy_utils::ty::is_must_use_ty; use clippy_utils::ty::is_must_use_ty;
use clippy_utils::visitors::for_each_expr_without_closures; use clippy_utils::visitors::for_each_expr_without_closures;
use clippy_utils::{return_ty, trait_ref_of_method}; use clippy_utils::{return_ty, trait_ref_of_method};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use core::ops::ControlFlow; use core::ops::ControlFlow;
@ -117,11 +118,11 @@ fn check_needless_must_use(
// Ignore async functions unless Future::Output type is a must_use type // Ignore async functions unless Future::Output type is a must_use type
if sig.header.is_async() { if sig.header.is_async() {
let infcx = cx.tcx.infer_ctxt().build(); let infcx = cx.tcx.infer_ctxt().build();
if let Some(future_ty) = infcx.get_impl_future_output_ty(return_ty(cx, item_id)) if let Some(future_ty) = infcx.err_ctxt().get_impl_future_output_ty(return_ty(cx, item_id))
&& !is_must_use_ty(cx, future_ty) && !is_must_use_ty(cx, future_ty)
{ {
return; return;
} };
} }
span_lint_and_help( span_lint_and_help(

View file

@ -9,7 +9,7 @@ use rustc_middle::ty::{self, AliasTy, ClauseKind, PredicateKind};
use rustc_session::declare_lint_pass; use rustc_session::declare_lint_pass;
use rustc_span::def_id::LocalDefId; use rustc_span::def_id::LocalDefId;
use rustc_span::{sym, Span}; use rustc_span::{sym, Span};
use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt; use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCtxt}; use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCtxt};
declare_clippy_lint! { declare_clippy_lint! {

View file

@ -56,19 +56,18 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl {
let Ok(impls) = cx.tcx.crate_inherent_impls(()) else { let Ok(impls) = cx.tcx.crate_inherent_impls(()) else {
return; return;
}; };
let inherent_impls = cx
.tcx
.with_stable_hashing_context(|hcx| impls.inherent_impls.to_sorted(&hcx, true));
for (_, impl_ids) in inherent_impls.into_iter().filter(|(&id, impls)| { for (&id, impl_ids) in &impls.inherent_impls {
impls.len() > 1 if impl_ids.len() < 2
// Check for `#[allow]` on the type definition // Check for `#[allow]` on the type definition
&& !is_lint_allowed( || is_lint_allowed(
cx, cx,
MULTIPLE_INHERENT_IMPL, MULTIPLE_INHERENT_IMPL,
cx.tcx.local_def_id_to_hir_id(id), cx.tcx.local_def_id_to_hir_id(id),
) ) {
}) { continue;
}
for impl_id in impl_ids.iter().map(|id| id.expect_local()) { for impl_id in impl_ids.iter().map(|id| id.expect_local()) {
let impl_ty = cx.tcx.type_of(impl_id).instantiate_identity(); let impl_ty = cx.tcx.type_of(impl_id).instantiate_identity();
match type_map.entry(impl_ty) { match type_map.entry(impl_ty) {

View file

@ -106,13 +106,12 @@ fn might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool {
/// ///
/// This is a fail-safe to a case where even the `is_from_proc_macro` is unable to determain the /// This is a fail-safe to a case where even the `is_from_proc_macro` is unable to determain the
/// correct result. /// correct result.
fn repeat_expr_might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool { fn repeat_expr_might_be_expanded(expr: &Expr<'_>) -> bool {
let ExprKind::Repeat(_, ArrayLen::Body(anon_const)) = expr.kind else { let ExprKind::Repeat(_, ArrayLen::Body(len_ct)) = expr.kind else {
return false; return false;
}; };
let len_span = cx.tcx.def_span(anon_const.def_id); !expr.span.contains(len_ct.span())
!expr.span.contains(len_span)
} }
expr.span.from_expansion() || is_from_proc_macro(cx, expr) || repeat_expr_might_be_expanded(cx, expr) expr.span.from_expansion() || is_from_proc_macro(cx, expr) || repeat_expr_might_be_expanded(expr)
} }

View file

@ -139,11 +139,11 @@ impl Visitor<'_> for IdentVisitor<'_, '_> {
return; return;
} }
// `struct Awa<T>(T)` // `struct Array<T, const N: usize>([T; N])`
// ^ // ^ ^
if let Node::PathSegment(path) = node { if let Node::PathSegment(path) = node {
if let Res::Def(def_kind, ..) = path.res if let Res::Def(def_kind, ..) = path.res
&& let DefKind::TyParam = def_kind && let DefKind::TyParam | DefKind::ConstParam = def_kind
{ {
return; return;
} }

View file

@ -364,8 +364,8 @@ declare_lint_pass!(MiscEarlyLints => [
]); ]);
impl EarlyLintPass for MiscEarlyLints { impl EarlyLintPass for MiscEarlyLints {
fn check_generics(&mut self, cx: &EarlyContext<'_>, gen: &Generics) { fn check_generics(&mut self, cx: &EarlyContext<'_>, generics: &Generics) {
for param in &gen.params { for param in &generics.params {
builtin_type_shadow::check(cx, param); builtin_type_shadow::check(cx, param);
} }
} }

View file

@ -15,6 +15,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro; use rustc_middle::lint::in_external_macro;
use rustc_session::impl_lint_pass; use rustc_session::impl_lint_pass;
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use std::ops::Deref; use std::ops::Deref;
declare_clippy_lint! { declare_clippy_lint! {
@ -159,7 +160,7 @@ impl NoEffect {
// Remove `impl Future<Output = T>` to get `T` // Remove `impl Future<Output = T>` to get `T`
if cx.tcx.ty_is_opaque_future(ret_ty) if cx.tcx.ty_is_opaque_future(ret_ty)
&& let Some(true_ret_ty) = && let Some(true_ret_ty) =
cx.tcx.infer_ctxt().build().get_impl_future_output_ty(ret_ty) cx.tcx.infer_ctxt().build().err_ctxt().get_impl_future_output_ty(ret_ty)
{ {
ret_ty = true_ret_ty; ret_ty = true_ret_ty;
} }

View file

@ -234,7 +234,7 @@ impl<'tcx> NonCopyConst<'tcx> {
fn is_value_unfrozen_raw( fn is_value_unfrozen_raw(
cx: &LateContext<'tcx>, cx: &LateContext<'tcx>,
result: Result<Option<ty::ValTree<'tcx>>, ErrorHandled>, result: Result<Result<ty::ValTree<'tcx>, Ty<'tcx>>, ErrorHandled>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
) -> bool { ) -> bool {
result.map_or_else( result.map_or_else(

View file

@ -394,8 +394,8 @@ fn check_final_expr<'tcx>(
// Returns may be used to turn an expression into a statement in rustc's AST. // Returns may be used to turn an expression into a statement in rustc's AST.
// This allows the addition of attributes, like `#[allow]` (See: clippy#9361) // This allows the addition of attributes, like `#[allow]` (See: clippy#9361)
// `#[expect(clippy::needless_return)]` needs to be handled separately to // `#[expect(clippy::needless_return)]` needs to be handled separatly to
// actually fulfill the expectation (clippy::#12998) // actually fullfil the expectation (clippy::#12998)
match cx.tcx.hir().attrs(expr.hir_id) { match cx.tcx.hir().attrs(expr.hir_id) {
[] => {}, [] => {},
[attr] => { [attr] => {

View file

@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::has_repr_attr; use clippy_utils::has_repr_attr;
use rustc_hir::{Item, ItemKind}; use rustc_hir::{Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::Const; use rustc_middle::ty::{Const, FeedConstTy};
use rustc_session::declare_lint_pass; use rustc_session::declare_lint_pass;
declare_clippy_lint! { declare_clippy_lint! {
@ -53,14 +53,14 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray {
} }
} }
fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'_>, item: &Item<'_>) -> bool { fn is_struct_with_trailing_zero_sized_array<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool {
if let ItemKind::Struct(data, _) = &item.kind if let ItemKind::Struct(data, _) = &item.kind
// First check if last field is an array // First check if last field is an array
&& let Some(last_field) = data.fields().last() && let Some(last_field) = data.fields().last()
&& let rustc_hir::TyKind::Array(_, rustc_hir::ArrayLen::Body(length)) = last_field.ty.kind && let rustc_hir::TyKind::Array(_, rustc_hir::ArrayLen::Body(length)) = last_field.ty.kind
// Then check if that array is zero-sized // Then check if that array is zero-sized
&& let length = Const::from_anon_const(cx.tcx, length.def_id) && let length = Const::from_const_arg(cx.tcx, length, FeedConstTy::No)
&& let length = length.try_eval_target_usize(cx.tcx, cx.param_env) && let length = length.try_eval_target_usize(cx.tcx, cx.param_env)
&& let Some(length) = length && let Some(length) = length
{ {

View file

@ -104,9 +104,9 @@ impl TraitBounds {
impl_lint_pass!(TraitBounds => [TYPE_REPETITION_IN_BOUNDS, TRAIT_DUPLICATION_IN_BOUNDS]); impl_lint_pass!(TraitBounds => [TYPE_REPETITION_IN_BOUNDS, TRAIT_DUPLICATION_IN_BOUNDS]);
impl<'tcx> LateLintPass<'tcx> for TraitBounds { impl<'tcx> LateLintPass<'tcx> for TraitBounds {
fn check_generics(&mut self, cx: &LateContext<'tcx>, gen: &'tcx Generics<'_>) { fn check_generics(&mut self, cx: &LateContext<'tcx>, generics: &'tcx Generics<'_>) {
self.check_type_repetition(cx, gen); self.check_type_repetition(cx, generics);
check_trait_bound_duplication(cx, gen); check_trait_bound_duplication(cx, generics);
} }
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
@ -240,7 +240,7 @@ impl TraitBounds {
} }
#[allow(clippy::mutable_key_type)] #[allow(clippy::mutable_key_type)]
fn check_type_repetition<'tcx>(&self, cx: &LateContext<'tcx>, gen: &'tcx Generics<'_>) { fn check_type_repetition<'tcx>(&self, cx: &LateContext<'tcx>, generics: &'tcx Generics<'_>) {
struct SpanlessTy<'cx, 'tcx> { struct SpanlessTy<'cx, 'tcx> {
ty: &'tcx Ty<'tcx>, ty: &'tcx Ty<'tcx>,
cx: &'cx LateContext<'tcx>, cx: &'cx LateContext<'tcx>,
@ -260,12 +260,12 @@ impl TraitBounds {
} }
impl Eq for SpanlessTy<'_, '_> {} impl Eq for SpanlessTy<'_, '_> {}
if gen.span.from_expansion() { if generics.span.from_expansion() {
return; return;
} }
let mut map: UnhashMap<SpanlessTy<'_, '_>, Vec<&GenericBound<'_>>> = UnhashMap::default(); let mut map: UnhashMap<SpanlessTy<'_, '_>, Vec<&GenericBound<'_>>> = UnhashMap::default();
let mut applicability = Applicability::MaybeIncorrect; let mut applicability = Applicability::MaybeIncorrect;
for bound in gen.predicates { for bound in generics.predicates {
if let WherePredicate::BoundPredicate(ref p) = bound if let WherePredicate::BoundPredicate(ref p) = bound
&& p.origin != PredicateOrigin::ImplTrait && p.origin != PredicateOrigin::ImplTrait
&& p.bounds.len() as u64 <= self.max_trait_bounds && p.bounds.len() as u64 <= self.max_trait_bounds
@ -303,8 +303,8 @@ impl TraitBounds {
} }
} }
fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) { fn check_trait_bound_duplication(cx: &LateContext<'_>, generics: &'_ Generics<'_>) {
if gen.span.from_expansion() { if generics.span.from_expansion() {
return; return;
} }
@ -315,7 +315,7 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
// | // |
// collects each of these where clauses into a set keyed by generic name and comparable trait // collects each of these where clauses into a set keyed by generic name and comparable trait
// eg. (T, Clone) // eg. (T, Clone)
let where_predicates = gen let where_predicates = generics
.predicates .predicates
.iter() .iter()
.filter_map(|pred| { .filter_map(|pred| {
@ -344,7 +344,7 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
// | // |
// compare trait bounds keyed by generic name and comparable trait to collected where // compare trait bounds keyed by generic name and comparable trait to collected where
// predicates eg. (T, Clone) // predicates eg. (T, Clone)
for predicate in gen.predicates.iter().filter(|pred| !pred.in_where_clause()) { for predicate in generics.predicates.iter().filter(|pred| !pred.in_where_clause()) {
if let WherePredicate::BoundPredicate(bound_predicate) = predicate if let WherePredicate::BoundPredicate(bound_predicate) = predicate
&& bound_predicate.origin != PredicateOrigin::ImplTrait && bound_predicate.origin != PredicateOrigin::ImplTrait
&& !bound_predicate.span.from_expansion() && !bound_predicate.span.from_expansion()

View file

@ -57,7 +57,7 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
bound bound
.bound_generic_params .bound_generic_params
.iter() .iter()
.any(|gen| matches!(gen.kind, GenericParamKind::Lifetime { .. })) .any(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
}); });
if has_lifetime_parameters { if has_lifetime_parameters {
// complex trait bounds like A<'a, 'b> // complex trait bounds like A<'a, 'b>

View file

@ -123,7 +123,7 @@ fn remove_all_parens(pat: &mut P<Pat>) {
struct Visitor; struct Visitor;
impl MutVisitor for Visitor { impl MutVisitor for Visitor {
fn visit_pat(&mut self, pat: &mut P<Pat>) { fn visit_pat(&mut self, pat: &mut P<Pat>) {
noop_visit_pat(pat, self); walk_pat(self, pat);
let inner = match &mut pat.kind { let inner = match &mut pat.kind {
Paren(i) => mem::replace(&mut i.kind, Wild), Paren(i) => mem::replace(&mut i.kind, Wild),
_ => return, _ => return,
@ -140,7 +140,7 @@ fn insert_necessary_parens(pat: &mut P<Pat>) {
impl MutVisitor for Visitor { impl MutVisitor for Visitor {
fn visit_pat(&mut self, pat: &mut P<Pat>) { fn visit_pat(&mut self, pat: &mut P<Pat>) {
use ast::BindingMode; use ast::BindingMode;
noop_visit_pat(pat, self); walk_pat(self, pat);
let target = match &mut pat.kind { let target = match &mut pat.kind {
// `i @ a | b`, `box a | b`, and `& mut? a | b`. // `i @ a | b`, `box a | b`, and `& mut? a | b`.
Ident(.., Some(p)) | Box(p) | Ref(p, _) if matches!(&p.kind, Or(ps) if ps.len() > 1) => p, Ident(.., Some(p)) | Box(p) | Ref(p, _) if matches!(&p.kind, Or(ps) if ps.len() > 1) => p,
@ -162,7 +162,7 @@ fn unnest_or_patterns(pat: &mut P<Pat>) -> bool {
impl MutVisitor for Visitor { impl MutVisitor for Visitor {
fn visit_pat(&mut self, p: &mut P<Pat>) { fn visit_pat(&mut self, p: &mut P<Pat>) {
// This is a bottom up transformation, so recurse first. // This is a bottom up transformation, so recurse first.
noop_visit_pat(p, self); walk_pat(self, p);
// Don't have an or-pattern? Just quit early on. // Don't have an or-pattern? Just quit early on.
let Or(alternatives) = &mut p.kind else { return }; let Or(alternatives) = &mut p.kind else { return };
@ -191,7 +191,7 @@ fn unnest_or_patterns(pat: &mut P<Pat>) -> bool {
// Deal with `Some(Some(0)) | Some(Some(1))`. // Deal with `Some(Some(0)) | Some(Some(1))`.
if this_level_changed { if this_level_changed {
noop_visit_pat(p, self); walk_pat(self, p);
} }
} }
} }

View file

@ -5,10 +5,9 @@ use clippy_utils::{get_attr, higher};
use rustc_ast::ast::{LitFloatType, LitKind}; use rustc_ast::ast::{LitFloatType, LitKind};
use rustc_ast::LitIntType; use rustc_ast::LitIntType;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
use rustc_hir::{ use rustc_hir::{
ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, CoroutineKind, ExprKind, FnRetTy, HirId, Lit, PatKind, self as hir, ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind,
QPath, StmtKind, TyKind, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind,
}; };
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::declare_lint_pass; use rustc_session::declare_lint_pass;
@ -270,6 +269,21 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
} }
} }
fn const_arg(&self, const_arg: &Binding<&ConstArg<'_>>) {
match const_arg.value.kind {
ConstArgKind::Path(ref qpath) => {
bind!(self, qpath);
chain!(self, "let ConstArgKind::Path(ref {qpath}) = {const_arg}.kind");
self.qpath(qpath);
},
ConstArgKind::Anon(anon_const) => {
bind!(self, anon_const);
chain!(self, "let ConstArgKind::Anon({anon_const}) = {const_arg}.kind");
self.body(field!(anon_const.body));
},
}
}
fn lit(&self, lit: &Binding<&Lit>) { fn lit(&self, lit: &Binding<&Lit>) {
let kind = |kind| chain!(self, "let LitKind::{kind} = {lit}.node"); let kind = |kind| chain!(self, "let LitKind::{kind} = {lit}.node");
macro_rules! kind { macro_rules! kind {
@ -602,10 +616,10 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
self.expr(value); self.expr(value);
match length.value { match length.value {
ArrayLen::Infer(..) => chain!(self, "let ArrayLen::Infer(..) = length"), ArrayLen::Infer(..) => chain!(self, "let ArrayLen::Infer(..) = length"),
ArrayLen::Body(anon_const) => { ArrayLen::Body(const_arg) => {
bind!(self, anon_const); bind!(self, const_arg);
chain!(self, "let ArrayLen::Body({anon_const}) = {length}"); chain!(self, "let ArrayLen::Body({const_arg}) = {length}");
self.body(field!(anon_const.body)); self.const_arg(const_arg);
}, },
} }
}, },

View file

@ -5,7 +5,7 @@ use clippy_utils::visitors::for_each_expr_without_closures;
use rustc_ast::LitKind; use rustc_ast::LitKind;
use rustc_data_structures::packed::Pu128; use rustc_data_structures::packed::Pu128;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{ArrayLen, ExprKind, Node}; use rustc_hir::{ArrayLen, ConstArgKind, ExprKind, Node};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::Ty; use rustc_middle::ty::Ty;
use rustc_session::declare_lint_pass; use rustc_session::declare_lint_pass;
@ -61,7 +61,8 @@ impl LateLintPass<'_> for ZeroRepeatSideEffects {
// the const item depends on `#[cfg]s` and has different values in different compilation // the const item depends on `#[cfg]s` and has different values in different compilation
// sessions). // sessions).
else if let ExprKind::Repeat(inner_expr, length) = expr.kind else if let ExprKind::Repeat(inner_expr, length) = expr.kind
&& let ArrayLen::Body(anon_const) = length && let ArrayLen::Body(const_arg) = length
&& let ConstArgKind::Anon(anon_const) = const_arg.kind
&& let length_expr = hir_map.body(anon_const.body).value && let length_expr = hir_map.body(anon_const.body).value
&& !length_expr.span.from_expansion() && !length_expr.span.from_expansion()
&& let ExprKind::Lit(literal) = length_expr.kind && let ExprKind::Lit(literal) = length_expr.kind

View file

@ -1,6 +1,6 @@
[package] [package]
name = "clippy_utils" name = "clippy_utils"
version = "0.1.81" version = "0.1.82"
edition = "2021" edition = "2021"
publish = false publish = false

View file

@ -7,9 +7,9 @@ use rustc_data_structures::fx::FxHasher;
use rustc_hir::def::Res; use rustc_hir::def::Res;
use rustc_hir::MatchSource::TryDesugar; use rustc_hir::MatchSource::TryDesugar;
use rustc_hir::{ use rustc_hir::{
ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr,
GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName, Pat, PatField, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime,
PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind,
}; };
use rustc_lexer::{tokenize, TokenKind}; use rustc_lexer::{tokenize, TokenKind};
use rustc_lint::LateContext; use rustc_lint::LateContext;
@ -227,7 +227,7 @@ impl HirEqInterExpr<'_, '_, '_> {
pub fn eq_array_length(&mut self, left: ArrayLen<'_>, right: ArrayLen<'_>) -> bool { pub fn eq_array_length(&mut self, left: ArrayLen<'_>, right: ArrayLen<'_>) -> bool {
match (left, right) { match (left, right) {
(ArrayLen::Infer(..), ArrayLen::Infer(..)) => true, (ArrayLen::Infer(..), ArrayLen::Infer(..)) => true,
(ArrayLen::Body(l_ct), ArrayLen::Body(r_ct)) => self.eq_body(l_ct.body, r_ct.body), (ArrayLen::Body(l_ct), ArrayLen::Body(r_ct)) => self.eq_const_arg(l_ct, r_ct),
(_, _) => false, (_, _) => false,
} }
} }
@ -411,7 +411,7 @@ impl HirEqInterExpr<'_, '_, '_> {
fn eq_generic_arg(&mut self, left: &GenericArg<'_>, right: &GenericArg<'_>) -> bool { fn eq_generic_arg(&mut self, left: &GenericArg<'_>, right: &GenericArg<'_>) -> bool {
match (left, right) { match (left, right) {
(GenericArg::Const(l), GenericArg::Const(r)) => self.eq_body(l.value.body, r.value.body), (GenericArg::Const(l), GenericArg::Const(r)) => self.eq_const_arg(l, r),
(GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => Self::eq_lifetime(l_lt, r_lt), (GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => Self::eq_lifetime(l_lt, r_lt),
(GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty, r_ty), (GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty, r_ty),
(GenericArg::Infer(l_inf), GenericArg::Infer(r_inf)) => self.eq_ty(&l_inf.to_ty(), &r_inf.to_ty()), (GenericArg::Infer(l_inf), GenericArg::Infer(r_inf)) => self.eq_ty(&l_inf.to_ty(), &r_inf.to_ty()),
@ -419,6 +419,17 @@ impl HirEqInterExpr<'_, '_, '_> {
} }
} }
fn eq_const_arg(&mut self, left: &ConstArg<'_>, right: &ConstArg<'_>) -> bool {
match (&left.kind, &right.kind) {
(ConstArgKind::Path(l_p), ConstArgKind::Path(r_p)) => self.eq_qpath(l_p, r_p),
(ConstArgKind::Anon(l_an), ConstArgKind::Anon(r_an)) => self.eq_body(l_an.body, r_an.body),
// Use explicit match for now since ConstArg is undergoing flux.
(ConstArgKind::Path(..), ConstArgKind::Anon(..)) | (ConstArgKind::Anon(..), ConstArgKind::Path(..)) => {
false
},
}
}
fn eq_lifetime(left: &Lifetime, right: &Lifetime) -> bool { fn eq_lifetime(left: &Lifetime, right: &Lifetime) -> bool {
left.res == right.res left.res == right.res
} }
@ -1123,7 +1134,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
pub fn hash_array_length(&mut self, length: ArrayLen<'_>) { pub fn hash_array_length(&mut self, length: ArrayLen<'_>) {
match length { match length {
ArrayLen::Infer(..) => {}, ArrayLen::Infer(..) => {},
ArrayLen::Body(anon_const) => self.hash_body(anon_const.body), ArrayLen::Body(ct) => self.hash_const_arg(ct),
} }
} }
@ -1134,12 +1145,19 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
self.maybe_typeck_results = old_maybe_typeck_results; self.maybe_typeck_results = old_maybe_typeck_results;
} }
fn hash_const_arg(&mut self, const_arg: &ConstArg<'_>) {
match &const_arg.kind {
ConstArgKind::Path(path) => self.hash_qpath(path),
ConstArgKind::Anon(anon) => self.hash_body(anon.body),
}
}
fn hash_generic_args(&mut self, arg_list: &[GenericArg<'_>]) { fn hash_generic_args(&mut self, arg_list: &[GenericArg<'_>]) {
for arg in arg_list { for arg in arg_list {
match *arg { match *arg {
GenericArg::Lifetime(l) => self.hash_lifetime(l), GenericArg::Lifetime(l) => self.hash_lifetime(l),
GenericArg::Type(ty) => self.hash_ty(ty), GenericArg::Type(ty) => self.hash_ty(ty),
GenericArg::Const(ref ca) => self.hash_body(ca.value.body), GenericArg::Const(ca) => self.hash_const_arg(ca),
GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()), GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()),
} }
} }

View file

@ -102,11 +102,11 @@ use rustc_hir::hir_id::{HirIdMap, HirIdSet};
use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
use rustc_hir::{ use rustc_hir::{
self as hir, def, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstContext, self as hir, def, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind,
Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, ConstContext, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem,
ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat, ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode,
PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef,
TyKind, UnOp, TraitRef, TyKind, UnOp,
}; };
use rustc_lexer::{tokenize, TokenKind}; use rustc_lexer::{tokenize, TokenKind};
use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_lint::{LateContext, Level, Lint, LintContext};
@ -914,7 +914,8 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
}, },
ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)), ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)),
ExprKind::Repeat(x, ArrayLen::Body(len)) => { ExprKind::Repeat(x, ArrayLen::Body(len)) => {
if let ExprKind::Lit(const_lit) = cx.tcx.hir().body(len.body).value.kind if let ConstArgKind::Anon(anon_const) = len.kind
&& let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
&& let LitKind::Int(v, _) = const_lit.node && let LitKind::Int(v, _) = const_lit.node
&& v <= 32 && v <= 32
&& is_default_equivalent(cx, x) && is_default_equivalent(cx, x)
@ -943,7 +944,8 @@ fn is_default_equivalent_from(cx: &LateContext<'_>, from_func: &Expr<'_>, arg: &
}) => return sym.is_empty() && is_path_lang_item(cx, ty, LangItem::String), }) => return sym.is_empty() && is_path_lang_item(cx, ty, LangItem::String),
ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec), ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec),
ExprKind::Repeat(_, ArrayLen::Body(len)) => { ExprKind::Repeat(_, ArrayLen::Body(len)) => {
if let ExprKind::Lit(const_lit) = cx.tcx.hir().body(len.body).value.kind if let ConstArgKind::Anon(anon_const) = len.kind
&& let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
&& let LitKind::Int(v, _) = const_lit.node && let LitKind::Int(v, _) = const_lit.node
{ {
return v == 0 && is_path_diagnostic_item(cx, ty, sym::Vec); return v == 0 && is_path_diagnostic_item(cx, ty, sym::Vec);

View file

@ -1,6 +1,6 @@
[package] [package]
name = "declare_clippy_lint" name = "declare_clippy_lint"
version = "0.1.81" version = "0.1.82"
edition = "2021" edition = "2021"
publish = false publish = false

View file

@ -1,4 +1,4 @@
[toolchain] [toolchain]
channel = "nightly-2024-07-11" channel = "nightly-2024-07-25"
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
profile = "minimal" profile = "minimal"

View file

@ -1,7 +1,8 @@
if let ExprKind::Repeat(value, length) = expr.kind if let ExprKind::Repeat(value, length) = expr.kind
&& let ExprKind::Lit(ref lit) = value.kind && let ExprKind::Lit(ref lit) = value.kind
&& let LitKind::Int(1, LitIntType::Unsigned(UintTy::U8)) = lit.node && let LitKind::Int(1, LitIntType::Unsigned(UintTy::U8)) = lit.node
&& let ArrayLen::Body(anon_const) = length && let ArrayLen::Body(const_arg) = length
&& let ConstArgKind::Anon(anon_const) = const_arg.kind
&& expr1 = &cx.tcx.hir().body(anon_const.body).value && expr1 = &cx.tcx.hir().body(anon_const.body).value
&& let ExprKind::Lit(ref lit1) = expr1.kind && let ExprKind::Lit(ref lit1) = expr1.kind
&& let LitKind::Int(5, LitIntType::Unsuffixed) = lit1.node && let LitKind::Int(5, LitIntType::Unsuffixed) = lit1.node

View file

@ -3,7 +3,7 @@ error[E0308]: mismatched types
| |
LL | const S: A = B; LL | const S: A = B;
| ^ expected `A`, found `B` | ^ expected `A`, found `B`
-Ztrack-diagnostics: created at compiler/rustc_infer/src/infer/error_reporting/mod.rs:LL:CC -Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs:LL:CC
error: aborting due to 1 previous error error: aborting due to 1 previous error