Auto merge of #96770 - flip1995:fix-trait-type-in-bounds, r=cjgillot

Track if a where bound comes from a impl Trait desugar

With https://github.com/rust-lang/rust/pull/93803 `impl Trait` function arguments get desugared to hidden where bounds. However, Clippy needs to know if a bound was originally a `impl Trait` or an actual bound. This adds a field to the `WhereBoundPredicate` struct to keep track of this information during AST->HIR lowering.

r? `@cjgillot`

cc `@estebank` (as the reviewer of #93803)
This commit is contained in:
bors 2022-05-08 14:10:12 +00:00
commit 1d018ce47c
6 changed files with 14 additions and 26 deletions

View File

@ -29,8 +29,6 @@ store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
LintId::of(strings::STRING_LIT_AS_BYTES), LintId::of(strings::STRING_LIT_AS_BYTES),
LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS), LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
LintId::of(trailing_empty_array::TRAILING_EMPTY_ARRAY), LintId::of(trailing_empty_array::TRAILING_EMPTY_ARRAY),
LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS),
LintId::of(trait_bounds::TYPE_REPETITION_IN_BOUNDS),
LintId::of(transmute::TRANSMUTE_UNDEFINED_REPR), LintId::of(transmute::TRANSMUTE_UNDEFINED_REPR),
LintId::of(transmute::USELESS_TRANSMUTE), LintId::of(transmute::USELESS_TRANSMUTE),
LintId::of(use_self::USE_SELF), LintId::of(use_self::USE_SELF),

View File

@ -84,6 +84,8 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED), LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED),
LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE), LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE),
LintId::of(strings::STRING_ADD_ASSIGN), LintId::of(strings::STRING_ADD_ASSIGN),
LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS),
LintId::of(trait_bounds::TYPE_REPETITION_IN_BOUNDS),
LintId::of(transmute::TRANSMUTE_PTR_TO_PTR), LintId::of(transmute::TRANSMUTE_PTR_TO_PTR),
LintId::of(types::LINKEDLIST), LintId::of(types::LINKEDLIST),
LintId::of(types::OPTION_OPTION), LintId::of(types::OPTION_OPTION),

View File

@ -9,8 +9,8 @@ use rustc_hir::intravisit::{
use rustc_hir::FnRetTy::Return; use rustc_hir::FnRetTy::Return;
use rustc_hir::{ use rustc_hir::{
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem, BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, ParamName, PolyTraitRef, TraitBoundModifier, ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, ParamName, PolyTraitRef, PredicateOrigin,
TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate, TraitBoundModifier, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
}; };
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter as middle_nested_filter; use rustc_middle::hir::nested_filter as middle_nested_filter;
@ -145,7 +145,7 @@ fn check_fn_inner<'tcx>(
.filter(|param| matches!(param.kind, GenericParamKind::Type { .. })); .filter(|param| matches!(param.kind, GenericParamKind::Type { .. }));
for typ in types { for typ in types {
for pred in generics.bounds_for_param(cx.tcx.hir().local_def_id(typ.hir_id)) { for pred in generics.bounds_for_param(cx.tcx.hir().local_def_id(typ.hir_id)) {
if pred.in_where_clause { if pred.origin == PredicateOrigin::WhereClause {
// has_where_lifetimes checked that this predicate contains no lifetime. // has_where_lifetimes checked that this predicate contains no lifetime.
continue; continue;
} }

View File

@ -8,7 +8,8 @@ use rustc_data_structures::unhash::UnhashMap;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::def::Res; use rustc_hir::def::Res;
use rustc_hir::{ use rustc_hir::{
GenericBound, Generics, Item, ItemKind, Node, Path, PathSegment, QPath, TraitItem, Ty, TyKind, WherePredicate, GenericBound, Generics, Item, ItemKind, Node, Path, PathSegment, PredicateOrigin, QPath, TraitItem, Ty, TyKind,
WherePredicate,
}; };
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
@ -35,7 +36,7 @@ declare_clippy_lint! {
/// ``` /// ```
#[clippy::version = "1.38.0"] #[clippy::version = "1.38.0"]
pub TYPE_REPETITION_IN_BOUNDS, pub TYPE_REPETITION_IN_BOUNDS,
nursery, pedantic,
"Types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`" "Types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`"
} }
@ -65,7 +66,7 @@ declare_clippy_lint! {
/// ``` /// ```
#[clippy::version = "1.47.0"] #[clippy::version = "1.47.0"]
pub TRAIT_DUPLICATION_IN_BOUNDS, pub TRAIT_DUPLICATION_IN_BOUNDS,
nursery, pedantic,
"Check if the same trait bounds are specified twice during a function declaration" "Check if the same trait bounds are specified twice during a function declaration"
} }
@ -95,6 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
for predicate in item.generics.predicates { for predicate in item.generics.predicates {
if_chain! { if_chain! {
if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate; if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate;
if bound_predicate.origin != PredicateOrigin::ImplTrait;
if !bound_predicate.span.from_expansion(); if !bound_predicate.span.from_expansion();
if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind; if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind;
if let Some(PathSegment { if let Some(PathSegment {
@ -168,6 +170,7 @@ impl TraitBounds {
for bound in gen.predicates { for bound in gen.predicates {
if_chain! { if_chain! {
if let WherePredicate::BoundPredicate(ref p) = bound; if let WherePredicate::BoundPredicate(ref p) = bound;
if p.origin != PredicateOrigin::ImplTrait;
if p.bounds.len() as u64 <= self.max_trait_bounds; if p.bounds.len() as u64 <= self.max_trait_bounds;
if !p.span.from_expansion(); if !p.span.from_expansion();
if let Some(ref v) = map.insert( if let Some(ref v) = map.insert(
@ -223,6 +226,7 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
for predicate in gen.predicates { for predicate in gen.predicates {
if_chain! { if_chain! {
if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate; if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate;
if bound_predicate.origin != PredicateOrigin::ImplTrait;
if !bound_predicate.span.from_expansion(); if !bound_predicate.span.from_expansion();
if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind; if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind;
if let Some(segment) = segments.first(); if let Some(segment) = segments.first();

View File

@ -67,13 +67,5 @@ LL | Self: Iterator<Item = Foo>,
| |
= help: consider removing this trait bound = help: consider removing this trait bound
error: this trait bound is already specified in the where clause error: aborting due to 8 previous errors
--> $DIR/trait_duplication_in_bounds.rs:99:23
|
LL | fn impl_trait(_: impl AsRef<str>, _: impl AsRef<str>) {}
| ^^^^^^^^^^
|
= help: consider removing this trait bound
error: aborting due to 9 previous errors

View File

@ -19,13 +19,5 @@ LL | Self: Copy + Default + Ord,
| |
= help: consider combining the bounds: `Self: Clone + Copy + Default + Ord` = help: consider combining the bounds: `Self: Clone + Copy + Default + Ord`
error: this type has already been used as a bound predicate error: aborting due to 2 previous errors
--> $DIR/type_repetition_in_bounds.rs:83:43
|
LL | fn impl_trait(_: impl AsRef<str>, _: impl AsRef<str>) {}
| ^^^^^^^^^^
|
= help: consider combining the bounds: `impl AsRef<str>: AsRef<str> + AsRef<str>`
error: aborting due to 3 previous errors