mirror of
https://github.com/rust-lang/rust-clippy
synced 2025-02-17 06:28:42 +00:00
[type_repetition_in_bounds
]: respect msrv for combining maybe bounds
This commit is contained in:
parent
8fd021f504
commit
87c28b9463
5 changed files with 59 additions and 11 deletions
|
@ -792,7 +792,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
store.register_late_pass(|_| Box::new(assertions_on_result_states::AssertionsOnResultStates));
|
||||
store.register_late_pass(|_| Box::new(inherent_to_string::InherentToString));
|
||||
let max_trait_bounds = conf.max_trait_bounds;
|
||||
store.register_late_pass(move |_| Box::new(trait_bounds::TraitBounds::new(max_trait_bounds)));
|
||||
store.register_late_pass(move |_| Box::new(trait_bounds::TraitBounds::new(max_trait_bounds, msrv())));
|
||||
store.register_late_pass(|_| Box::new(comparison_chain::ComparisonChain));
|
||||
let ignore_interior_mutability = conf.ignore_interior_mutability.clone();
|
||||
store.register_late_pass(move |_| Box::new(mut_key::MutableKeyType::new(ignore_interior_mutability.clone())));
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
|
||||
use clippy_utils::{is_from_proc_macro, SpanlessEq, SpanlessHash};
|
||||
use core::hash::{Hash, Hasher};
|
||||
|
@ -9,7 +10,7 @@ use rustc_data_structures::unhash::UnhashMap;
|
|||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::{
|
||||
GenericArg, GenericBound, Generics, Item, ItemKind, Node, Path, PathSegment, PredicateOrigin, QPath,
|
||||
GenericArg, GenericBound, Generics, Item, ItemKind, LangItem, Node, Path, PathSegment, PredicateOrigin, QPath,
|
||||
TraitBoundModifier, TraitItem, TraitRef, Ty, TyKind, WherePredicate,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
|
@ -86,15 +87,16 @@ declare_clippy_lint! {
|
|||
"check if the same trait bounds are specified more than once during a generic declaration"
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct TraitBounds {
|
||||
max_trait_bounds: u64,
|
||||
msrv: Msrv,
|
||||
}
|
||||
|
||||
impl TraitBounds {
|
||||
#[must_use]
|
||||
pub fn new(max_trait_bounds: u64) -> Self {
|
||||
Self { max_trait_bounds }
|
||||
pub fn new(max_trait_bounds: u64, msrv: Msrv) -> Self {
|
||||
Self { max_trait_bounds, msrv }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,10 +224,24 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
extract_msrv_attr!(LateContext);
|
||||
}
|
||||
|
||||
impl TraitBounds {
|
||||
fn check_type_repetition<'tcx>(self, cx: &LateContext<'tcx>, gen: &'tcx Generics<'_>) {
|
||||
/// Is the given bound a `?Sized` bound, and is combining it (i.e. `T: X + ?Sized`) an error on
|
||||
/// this MSRV? See https://github.com/rust-lang/rust-clippy/issues/8772 for details.
|
||||
fn cannot_combine_maybe_bound(&self, cx: &LateContext<'_>, bound: &GenericBound<'_>) -> bool {
|
||||
if !self.msrv.meets(msrvs::COMBINED_MAYBE_BOUND)
|
||||
&& let GenericBound::Trait(tr, TraitBoundModifier::Maybe) = bound
|
||||
{
|
||||
cx.tcx.lang_items().get(LangItem::Sized) == tr.trait_ref.path.res.opt_def_id()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn check_type_repetition<'tcx>(&self, cx: &LateContext<'tcx>, gen: &'tcx Generics<'_>) {
|
||||
struct SpanlessTy<'cx, 'tcx> {
|
||||
ty: &'tcx Ty<'tcx>,
|
||||
cx: &'cx LateContext<'tcx>,
|
||||
|
@ -256,10 +272,9 @@ impl TraitBounds {
|
|||
if p.origin != PredicateOrigin::ImplTrait;
|
||||
if p.bounds.len() as u64 <= self.max_trait_bounds;
|
||||
if !p.span.from_expansion();
|
||||
if let Some(ref v) = map.insert(
|
||||
SpanlessTy { ty: p.bounded_ty, cx },
|
||||
p.bounds.iter().collect::<Vec<_>>()
|
||||
);
|
||||
let bounds = p.bounds.iter().filter(|b| !self.cannot_combine_maybe_bound(cx, b)).collect::<Vec<_>>();
|
||||
if !bounds.is_empty();
|
||||
if let Some(ref v) = map.insert(SpanlessTy { ty: p.bounded_ty, cx }, bounds);
|
||||
if !is_from_proc_macro(cx, p.bounded_ty);
|
||||
then {
|
||||
let trait_bounds = v
|
||||
|
|
|
@ -47,6 +47,7 @@ msrv_aliases! {
|
|||
1,18,0 { HASH_MAP_RETAIN, HASH_SET_RETAIN }
|
||||
1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST, EXPECT_ERR }
|
||||
1,16,0 { STR_REPEAT }
|
||||
1,15,0 { COMBINED_MAYBE_BOUND }
|
||||
}
|
||||
|
||||
fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<RustcVersion> {
|
||||
|
|
|
@ -110,4 +110,28 @@ where
|
|||
// This should not lint
|
||||
fn impl_trait(_: impl AsRef<str>, _: impl AsRef<str>) {}
|
||||
|
||||
#[clippy::msrv = "1.14.0"]
|
||||
mod issue8772_fail {
|
||||
pub trait Trait<X, Y, Z> {}
|
||||
|
||||
pub fn f<T: ?Sized, U>(arg: usize)
|
||||
where
|
||||
T: Trait<Option<usize>, Box<[String]>, bool> + 'static,
|
||||
U: Clone + Sync + 'static,
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#[clippy::msrv = "1.15.0"]
|
||||
mod issue8772_pass {
|
||||
pub trait Trait<X, Y, Z> {}
|
||||
|
||||
pub fn f<T: ?Sized, U>(arg: usize)
|
||||
where
|
||||
T: Trait<Option<usize>, Box<[String]>, bool> + 'static,
|
||||
U: Clone + Sync + 'static,
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -35,5 +35,13 @@ LL | T: ?Sized,
|
|||
|
|
||||
= help: consider combining the bounds: `T: Clone + ?Sized`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: this type has already been used as a bound predicate
|
||||
--> $DIR/type_repetition_in_bounds.rs:131:9
|
||||
|
|
||||
LL | T: Trait<Option<usize>, Box<[String]>, bool> + 'static,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider combining the bounds: `T: ?Sized + Trait<Option<usize>, Box<[String]>, bool>`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue