Skip to content

Commit e2d923a

Browse files
committed
Store all generic bounds as where predicates.
1 parent 67241bb commit e2d923a

File tree

3 files changed

+41
-43
lines changed

3 files changed

+41
-43
lines changed

clippy_lints/src/lifetimes.rs

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -139,28 +139,35 @@ fn check_fn_inner<'tcx>(
139139
.iter()
140140
.filter(|param| matches!(param.kind, GenericParamKind::Type { .. }));
141141
for typ in types {
142-
for bound in typ.bounds {
143-
let mut visitor = RefVisitor::new(cx);
144-
walk_param_bound(&mut visitor, bound);
145-
if visitor.lts.iter().any(|lt| matches!(lt, RefLt::Named(_))) {
146-
return;
142+
for pred in generics.bounds_for_param(cx.tcx.hir().local_def_id(typ.hir_id)) {
143+
if pred.in_where_clause {
144+
// has_where_lifetimes checked that this predicate contains no lifetime.
145+
continue;
147146
}
148-
if let GenericBound::Trait(ref trait_ref, _) = *bound {
149-
let params = &trait_ref
150-
.trait_ref
151-
.path
152-
.segments
153-
.last()
154-
.expect("a path must have at least one segment")
155-
.args;
156-
if let Some(params) = *params {
157-
let lifetimes = params.args.iter().filter_map(|arg| match arg {
158-
GenericArg::Lifetime(lt) => Some(lt),
159-
_ => None,
160-
});
161-
for bound in lifetimes {
162-
if bound.name != LifetimeName::Static && !bound.is_elided() {
163-
return;
147+
148+
for bound in pred.bounds {
149+
let mut visitor = RefVisitor::new(cx);
150+
walk_param_bound(&mut visitor, bound);
151+
if visitor.lts.iter().any(|lt| matches!(lt, RefLt::Named(_))) {
152+
return;
153+
}
154+
if let GenericBound::Trait(ref trait_ref, _) = *bound {
155+
let params = &trait_ref
156+
.trait_ref
157+
.path
158+
.segments
159+
.last()
160+
.expect("a path must have at least one segment")
161+
.args;
162+
if let Some(params) = *params {
163+
let lifetimes = params.args.iter().filter_map(|arg| match arg {
164+
GenericArg::Lifetime(lt) => Some(lt),
165+
_ => None,
166+
});
167+
for bound in lifetimes {
168+
if bound.name != LifetimeName::Static && !bound.is_elided() {
169+
return;
170+
}
164171
}
165172
}
166173
}
@@ -322,9 +329,7 @@ fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxHashSet<RefLt> {
322329
let mut allowed_lts = FxHashSet::default();
323330
for par in named_generics.iter() {
324331
if let GenericParamKind::Lifetime { .. } = par.kind {
325-
if par.bounds.is_empty() {
326-
allowed_lts.insert(RefLt::Named(par.name.ident().name));
327-
}
332+
allowed_lts.insert(RefLt::Named(par.name.ident().name));
328333
}
329334
}
330335
allowed_lts.insert(RefLt::Unnamed);

clippy_lints/src/trait_bounds.rs

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ use rustc_data_structures::unhash::UnhashMap;
88
use rustc_errors::Applicability;
99
use rustc_hir::def::Res;
1010
use rustc_hir::{
11-
GenericBound, Generics, Item, ItemKind, Node, ParamName, Path, PathSegment, QPath, TraitItem, Ty, TyKind,
12-
WherePredicate,
11+
GenericBound, Generics, Item, ItemKind, Node, Path, PathSegment, QPath, TraitItem, Ty, TyKind, WherePredicate,
1312
};
1413
use rustc_lint::{LateContext, LateLintPass};
1514
use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -219,30 +218,19 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
219218
return;
220219
}
221220

222-
let mut map = FxHashMap::default();
223-
for param in gen.params {
224-
if let ParamName::Plain(ref ident) = param.name {
225-
let res = param
226-
.bounds
227-
.iter()
228-
.filter_map(get_trait_info_from_bound)
229-
.collect::<Vec<_>>();
230-
map.insert(*ident, res);
231-
}
232-
}
233-
221+
let mut map = FxHashMap::<_, Vec<_>>::default();
234222
for predicate in gen.predicates {
235223
if_chain! {
236224
if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate;
237225
if !bound_predicate.span.from_expansion();
238226
if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind;
239227
if let Some(segment) = segments.first();
240-
if let Some(trait_resolutions_direct) = map.get(&segment.ident);
241228
then {
242-
for (res_where, _, _) in bound_predicate.bounds.iter().filter_map(get_trait_info_from_bound) {
243-
if let Some((_, _, span_direct)) = trait_resolutions_direct
229+
for (res_where, _, span_where) in bound_predicate.bounds.iter().filter_map(get_trait_info_from_bound) {
230+
let trait_resolutions_direct = map.entry(segment.ident).or_default();
231+
if let Some((_, span_direct)) = trait_resolutions_direct
244232
.iter()
245-
.find(|(res_direct, _, _)| *res_direct == res_where) {
233+
.find(|(res_direct, _)| *res_direct == res_where) {
246234
span_lint_and_help(
247235
cx,
248236
TRAIT_DUPLICATION_IN_BOUNDS,
@@ -252,6 +240,9 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
252240
"consider removing this trait bound",
253241
);
254242
}
243+
else {
244+
trait_resolutions_direct.push((res_where, span_where))
245+
}
255246
}
256247
}
257248
}

clippy_lints/src/types/borrowed_box.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,10 @@ fn get_bounds_if_impl_trait<'tcx>(cx: &LateContext<'tcx>, qpath: &QPath<'_>, id:
104104
if let Some(Node::GenericParam(generic_param)) = cx.tcx.hir().get_if_local(did);
105105
if let GenericParamKind::Type { synthetic, .. } = generic_param.kind;
106106
if synthetic;
107+
if let Some(generics) = cx.tcx.hir().get_generics(id.owner);
108+
if let Some(pred) = generics.bounds_for_param(did.expect_local()).next();
107109
then {
108-
Some(generic_param.bounds)
110+
Some(pred.bounds)
109111
} else {
110112
None
111113
}

0 commit comments

Comments
 (0)