1
Fork 0

Track if a where bound comes from a impl Trait desugar

With #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
HIR lowering.
This commit is contained in:
flip1995 2022-05-05 15:50:11 +01:00 committed by flip1995
parent f47d2b3ad6
commit dd1ff405e3
No known key found for this signature in database
GPG key ID: 2CEFCDB27ED0BE79
7 changed files with 34 additions and 12 deletions

View file

@ -11,6 +11,7 @@ use rustc_errors::struct_span_err;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
use rustc_hir::PredicateOrigin;
use rustc_index::vec::{Idx, IndexVec}; use rustc_index::vec::{Idx, IndexVec};
use rustc_session::utils::NtToTokenstream; use rustc_session::utils::NtToTokenstream;
use rustc_session::Session; use rustc_session::Session;
@ -1346,7 +1347,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
let mut predicates = SmallVec::new(); let mut predicates = SmallVec::new();
predicates.extend(generics.params.iter().filter_map(|param| { predicates.extend(generics.params.iter().filter_map(|param| {
let bounds = self.lower_param_bounds(&param.bounds, itctx.reborrow()); let bounds = self.lower_param_bounds(&param.bounds, itctx.reborrow());
self.lower_generic_bound_predicate(param.ident, param.id, &param.kind, bounds) self.lower_generic_bound_predicate(
param.ident,
param.id,
&param.kind,
bounds,
PredicateOrigin::GenericParam,
)
})); }));
predicates.extend( predicates.extend(
generics generics
@ -1380,6 +1387,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
id: NodeId, id: NodeId,
kind: &GenericParamKind, kind: &GenericParamKind,
bounds: &'hir [hir::GenericBound<'hir>], bounds: &'hir [hir::GenericBound<'hir>],
origin: PredicateOrigin,
) -> Option<hir::WherePredicate<'hir>> { ) -> Option<hir::WherePredicate<'hir>> {
// Do not create a clause if we do not have anything inside it. // Do not create a clause if we do not have anything inside it.
if bounds.is_empty() { if bounds.is_empty() {
@ -1419,7 +1427,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
bounds, bounds,
span, span,
bound_generic_params: &[], bound_generic_params: &[],
in_where_clause: false, origin,
})) }))
} }
GenericParamKind::Lifetime => { GenericParamKind::Lifetime => {
@ -1458,7 +1466,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
) )
})), })),
span: self.lower_span(span), span: self.lower_span(span),
in_where_clause: true, origin: PredicateOrigin::WhereClause,
}), }),
WherePredicate::RegionPredicate(WhereRegionPredicate { WherePredicate::RegionPredicate(WhereRegionPredicate {
ref lifetime, ref lifetime,

View file

@ -1298,6 +1298,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
def_node_id, def_node_id,
&GenericParamKind::Type { default: None }, &GenericParamKind::Type { default: None },
hir_bounds, hir_bounds,
hir::PredicateOrigin::ImplTrait,
) { ) {
in_band_ty_bounds.push(preds) in_band_ty_bounds.push(preds)
} }

View file

@ -706,7 +706,7 @@ impl<'hir> WherePredicate<'hir> {
pub fn in_where_clause(&self) -> bool { pub fn in_where_clause(&self) -> bool {
match self { match self {
WherePredicate::BoundPredicate(p) => p.in_where_clause, WherePredicate::BoundPredicate(p) => p.origin == PredicateOrigin::WhereClause,
WherePredicate::RegionPredicate(p) => p.in_where_clause, WherePredicate::RegionPredicate(p) => p.in_where_clause,
WherePredicate::EqPredicate(_) => false, WherePredicate::EqPredicate(_) => false,
} }
@ -721,11 +721,19 @@ impl<'hir> WherePredicate<'hir> {
} }
} }
#[derive(Debug, HashStable_Generic, PartialEq, Eq)]
pub enum PredicateOrigin {
WhereClause,
GenericParam,
ImplTrait,
}
/// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`). /// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`).
#[derive(Debug, HashStable_Generic)] #[derive(Debug, HashStable_Generic)]
pub struct WhereBoundPredicate<'hir> { pub struct WhereBoundPredicate<'hir> {
pub span: Span, pub span: Span,
pub in_where_clause: bool, /// Origin of the predicate.
pub origin: PredicateOrigin,
/// Any generics from a `for` binding. /// Any generics from a `for` binding.
pub bound_generic_params: &'hir [GenericParam<'hir>], pub bound_generic_params: &'hir [GenericParam<'hir>],
/// The type being bounded. /// The type being bounded.

View file

@ -36,7 +36,7 @@ use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, Gate
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID}; use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
use rustc_hir::{ForeignItemKind, GenericParamKind, HirId, PatKind}; use rustc_hir::{ForeignItemKind, GenericParamKind, HirId, PatKind, PredicateOrigin};
use rustc_index::vec::Idx; use rustc_index::vec::Idx;
use rustc_middle::lint::LintDiagnosticBuilder; use rustc_middle::lint::LintDiagnosticBuilder;
use rustc_middle::ty::layout::{LayoutError, LayoutOf}; use rustc_middle::ty::layout::{LayoutError, LayoutOf};
@ -2226,7 +2226,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
Self::lifetimes_outliving_type(inferred_outlives, index), Self::lifetimes_outliving_type(inferred_outlives, index),
&predicate.bounds, &predicate.bounds,
predicate.span, predicate.span,
predicate.in_where_clause, predicate.origin == PredicateOrigin::WhereClause,
) )
} }
_ => { _ => {

View file

@ -16,6 +16,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::PredicateOrigin;
use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
use rustc_middle::middle::resolve_lifetime as rl; use rustc_middle::middle::resolve_lifetime as rl;
use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::fold::TypeFolder;
@ -493,7 +494,7 @@ fn clean_generic_param(
let bounds = if let Some(generics) = generics { let bounds = if let Some(generics) = generics {
generics generics
.bounds_for_param(did) .bounds_for_param(did)
.filter(|bp| !bp.in_where_clause) .filter(|bp| bp.origin != PredicateOrigin::WhereClause)
.flat_map(|bp| bp.bounds) .flat_map(|bp| bp.bounds)
.filter_map(|x| x.clean(cx)) .filter_map(|x| x.clean(cx))
.collect() .collect()

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};
@ -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();