Skip to content

Commit 7142a59

Browse files
committed
Auto merge of #9132 - hellow554:maybe_trait_bound_on_type_repetition, r=Manishearth
Maybe trait bound on type repetition *Please write a short comment explaining your change (or "none" for internal only changes)* changelog: fix maybe trait on [`type_repetition_in_bounds`] lint I simplified the two for loops, which did exactly the same. Only downside is, that I need a `copied`, but that's to convert from `&&` to `&`, to that should be a noop? One more thing: I only handle [`TraitBoundModifier::Maybe`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/enum.TraitBoundModifier.html#variant.Maybe). Can anyone give me an example (and testcase) for [`TraitBoundModifier::MaybeConst`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/enum.TraitBoundModifier.html#variant.MaybeConst)? closes #8770
2 parents afb34eb + ead2c4f commit 7142a59

File tree

3 files changed

+55
-30
lines changed

3 files changed

+55
-30
lines changed

clippy_lints/src/trait_bounds.rs

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ use clippy_utils::source::{snippet, snippet_with_applicability};
33
use clippy_utils::{SpanlessEq, SpanlessHash};
44
use core::hash::{Hash, Hasher};
55
use if_chain::if_chain;
6+
use itertools::Itertools;
67
use rustc_data_structures::fx::FxHashMap;
78
use rustc_data_structures::unhash::UnhashMap;
89
use rustc_errors::Applicability;
910
use rustc_hir::def::Res;
1011
use rustc_hir::{
11-
GenericBound, Generics, Item, ItemKind, Node, Path, PathSegment, PredicateOrigin, QPath, TraitItem, Ty, TyKind,
12-
WherePredicate,
12+
GenericBound, Generics, Item, ItemKind, Node, Path, PathSegment, PredicateOrigin, QPath, TraitBoundModifier,
13+
TraitItem, Ty, TyKind, WherePredicate,
1314
};
1415
use rustc_lint::{LateContext, LateLintPass};
1516
use rustc_session::{declare_tool_lint, impl_lint_pass};
16-
use rustc_span::Span;
17-
use std::fmt::Write as _;
17+
use rustc_span::{BytePos, Span};
1818

1919
declare_clippy_lint! {
2020
/// ### What it does
@@ -178,30 +178,18 @@ impl TraitBounds {
178178
);
179179

180180
then {
181-
let mut hint_string = format!(
182-
"consider combining the bounds: `{}:",
183-
snippet(cx, p.bounded_ty.span, "_")
181+
let trait_bounds = v
182+
.iter()
183+
.copied()
184+
.chain(p.bounds.iter())
185+
.filter_map(get_trait_info_from_bound)
186+
.map(|(_, _, span)| snippet_with_applicability(cx, span, "..", &mut applicability))
187+
.join(" + ");
188+
let hint_string = format!(
189+
"consider combining the bounds: `{}: {}`",
190+
snippet(cx, p.bounded_ty.span, "_"),
191+
trait_bounds,
184192
);
185-
for b in v.iter() {
186-
if let GenericBound::Trait(ref poly_trait_ref, _) = b {
187-
let path = &poly_trait_ref.trait_ref.path;
188-
let _ = write!(hint_string,
189-
" {} +",
190-
snippet_with_applicability(cx, path.span, "..", &mut applicability)
191-
);
192-
}
193-
}
194-
for b in p.bounds.iter() {
195-
if let GenericBound::Trait(ref poly_trait_ref, _) = b {
196-
let path = &poly_trait_ref.trait_ref.path;
197-
let _ = write!(hint_string,
198-
" {} +",
199-
snippet_with_applicability(cx, path.span, "..", &mut applicability)
200-
);
201-
}
202-
}
203-
hint_string.truncate(hint_string.len() - 2);
204-
hint_string.push('`');
205193
span_lint_and_help(
206194
cx,
207195
TYPE_REPETITION_IN_BOUNDS,
@@ -254,8 +242,17 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
254242
}
255243

256244
fn get_trait_info_from_bound<'a>(bound: &'a GenericBound<'_>) -> Option<(Res, &'a [PathSegment<'a>], Span)> {
257-
if let GenericBound::Trait(t, _) = bound {
258-
Some((t.trait_ref.path.res, t.trait_ref.path.segments, t.span))
245+
if let GenericBound::Trait(t, tbm) = bound {
246+
let trait_path = t.trait_ref.path;
247+
let trait_span = {
248+
let path_span = trait_path.span;
249+
if let TraitBoundModifier::Maybe = tbm {
250+
path_span.with_lo(path_span.lo() - BytePos(1)) // include the `?`
251+
} else {
252+
path_span
253+
}
254+
};
255+
Some((trait_path.res, trait_path.segments, trait_span))
259256
} else {
260257
None
261258
}

tests/ui/type_repetition_in_bounds.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,18 @@ where
7979
u: U,
8080
}
8181

82+
// Check for the `?` in `?Sized`
83+
pub fn f<T: ?Sized>()
84+
where
85+
T: Clone,
86+
{
87+
}
88+
pub fn g<T: Clone>()
89+
where
90+
T: ?Sized,
91+
{
92+
}
93+
8294
// This should not lint
8395
fn impl_trait(_: impl AsRef<str>, _: impl AsRef<str>) {}
8496

tests/ui/type_repetition_in_bounds.stderr

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,21 @@ LL | Self: Copy + Default + Ord,
1919
|
2020
= help: consider combining the bounds: `Self: Clone + Copy + Default + Ord`
2121

22-
error: aborting due to 2 previous errors
22+
error: this type has already been used as a bound predicate
23+
--> $DIR/type_repetition_in_bounds.rs:85:5
24+
|
25+
LL | T: Clone,
26+
| ^^^^^^^^
27+
|
28+
= help: consider combining the bounds: `T: ?Sized + Clone`
29+
30+
error: this type has already been used as a bound predicate
31+
--> $DIR/type_repetition_in_bounds.rs:90:5
32+
|
33+
LL | T: ?Sized,
34+
| ^^^^^^^^^
35+
|
36+
= help: consider combining the bounds: `T: Clone + ?Sized`
37+
38+
error: aborting due to 4 previous errors
2339

0 commit comments

Comments
 (0)