mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-12 16:45:37 +00:00
Add needless_maybe_sized
lint
This commit is contained in:
parent
832fdb6d30
commit
cf0b55eb62
@ -5523,6 +5523,7 @@ Released 2018-09-13
|
||||
[`needless_late_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_late_init
|
||||
[`needless_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
|
||||
[`needless_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_match
|
||||
[`needless_maybe_sized`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_maybe_sized
|
||||
[`needless_option_as_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_as_deref
|
||||
[`needless_option_take`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_take
|
||||
[`needless_parens_on_range_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_parens_on_range_literals
|
||||
|
@ -527,6 +527,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
||||
crate::needless_for_each::NEEDLESS_FOR_EACH_INFO,
|
||||
crate::needless_if::NEEDLESS_IF_INFO,
|
||||
crate::needless_late_init::NEEDLESS_LATE_INIT_INFO,
|
||||
crate::needless_maybe_sized::NEEDLESS_MAYBE_SIZED_INFO,
|
||||
crate::needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS_INFO,
|
||||
crate::needless_pass_by_ref_mut::NEEDLESS_PASS_BY_REF_MUT_INFO,
|
||||
crate::needless_pass_by_value::NEEDLESS_PASS_BY_VALUE_INFO,
|
||||
|
@ -254,6 +254,7 @@ mod needless_else;
|
||||
mod needless_for_each;
|
||||
mod needless_if;
|
||||
mod needless_late_init;
|
||||
mod needless_maybe_sized;
|
||||
mod needless_parens_on_range_literals;
|
||||
mod needless_pass_by_ref_mut;
|
||||
mod needless_pass_by_value;
|
||||
@ -1032,6 +1033,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
|
||||
store.register_late_pass(|_| Box::new(no_mangle_with_rust_abi::NoMangleWithRustAbi));
|
||||
store.register_late_pass(|_| Box::new(collection_is_never_read::CollectionIsNeverRead));
|
||||
store.register_late_pass(|_| Box::new(missing_assert_message::MissingAssertMessage));
|
||||
store.register_late_pass(|_| Box::new(needless_maybe_sized::NeedlessMaybeSized));
|
||||
store.register_late_pass(|_| Box::new(redundant_async_block::RedundantAsyncBlock));
|
||||
store.register_late_pass(|_| Box::new(let_with_type_underscore::UnderscoreTyped));
|
||||
store.register_late_pass(|_| Box::new(allow_attributes::AllowAttribute));
|
||||
|
164
clippy_lints/src/needless_maybe_sized.rs
Normal file
164
clippy_lints/src/needless_maybe_sized.rs
Normal file
@ -0,0 +1,164 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def_id::{DefId, DefIdMap};
|
||||
use rustc_hir::{GenericBound, Generics, PolyTraitRef, TraitBoundModifier, WherePredicate};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::{ClauseKind, PredicatePolarity};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::symbol::Ident;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Lints `?Sized` bounds applied to type parameters that cannot be unsized
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// The `?Sized` bound is misleading because it cannot be satisfied by an
|
||||
/// unsized type
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
/// // `T` cannot be unsized because `Clone` requires it to be `Sized`
|
||||
/// fn f<T: Clone + ?Sized>(t: &T) {}
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// fn f<T: Clone>(t: &T) {}
|
||||
///
|
||||
/// // or choose alternative bounds for `T` so that it can be unsized
|
||||
/// ```
|
||||
#[clippy::version = "1.79.0"]
|
||||
pub NEEDLESS_MAYBE_SIZED,
|
||||
suspicious,
|
||||
"a `?Sized` bound that is unusable due to a `Sized` requirement"
|
||||
}
|
||||
declare_lint_pass!(NeedlessMaybeSized => [NEEDLESS_MAYBE_SIZED]);
|
||||
|
||||
#[allow(clippy::struct_field_names)]
|
||||
struct Bound<'tcx> {
|
||||
/// The [`DefId`] of the type parameter the bound refers to
|
||||
param: DefId,
|
||||
ident: Ident,
|
||||
|
||||
trait_bound: &'tcx PolyTraitRef<'tcx>,
|
||||
modifier: TraitBoundModifier,
|
||||
|
||||
predicate_pos: usize,
|
||||
bound_pos: usize,
|
||||
}
|
||||
|
||||
/// Finds all of the [`Bound`]s that refer to a type parameter and are not from a macro expansion
|
||||
fn type_param_bounds<'tcx>(generics: &'tcx Generics<'tcx>) -> impl Iterator<Item = Bound<'tcx>> {
|
||||
generics
|
||||
.predicates
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(predicate_pos, predicate)| {
|
||||
let WherePredicate::BoundPredicate(bound_predicate) = predicate else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let (param, ident) = bound_predicate.bounded_ty.as_generic_param()?;
|
||||
|
||||
Some(
|
||||
bound_predicate
|
||||
.bounds
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(move |(bound_pos, bound)| match bound {
|
||||
&GenericBound::Trait(ref trait_bound, modifier) => Some(Bound {
|
||||
param,
|
||||
ident,
|
||||
trait_bound,
|
||||
modifier,
|
||||
predicate_pos,
|
||||
bound_pos,
|
||||
}),
|
||||
GenericBound::Outlives(_) => None,
|
||||
})
|
||||
.filter(|bound| !bound.trait_bound.span.from_expansion()),
|
||||
)
|
||||
})
|
||||
.flatten()
|
||||
}
|
||||
|
||||
/// Searches the supertraits of the trait referred to by `trait_bound` recursively, returning the
|
||||
/// path taken to find a `Sized` bound if one is found
|
||||
fn path_to_sized_bound(cx: &LateContext<'_>, trait_bound: &PolyTraitRef<'_>) -> Option<Vec<DefId>> {
|
||||
fn search(cx: &LateContext<'_>, path: &mut Vec<DefId>) -> bool {
|
||||
let trait_def_id = *path.last().unwrap();
|
||||
|
||||
if Some(trait_def_id) == cx.tcx.lang_items().sized_trait() {
|
||||
return true;
|
||||
}
|
||||
|
||||
for &(predicate, _) in cx.tcx.super_predicates_of(trait_def_id).predicates {
|
||||
if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder()
|
||||
&& trait_predicate.polarity == PredicatePolarity::Positive
|
||||
&& !path.contains(&trait_predicate.def_id())
|
||||
{
|
||||
path.push(trait_predicate.def_id());
|
||||
if search(cx, path) {
|
||||
return true;
|
||||
}
|
||||
path.pop();
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
let mut path = vec![trait_bound.trait_ref.trait_def_id()?];
|
||||
search(cx, &mut path).then_some(path)
|
||||
}
|
||||
|
||||
impl LateLintPass<'_> for NeedlessMaybeSized {
|
||||
fn check_generics(&mut self, cx: &LateContext<'_>, generics: &Generics<'_>) {
|
||||
let Some(sized_trait) = cx.tcx.lang_items().sized_trait() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let maybe_sized_params: DefIdMap<_> = type_param_bounds(generics)
|
||||
.filter(|bound| {
|
||||
bound.trait_bound.trait_ref.trait_def_id() == Some(sized_trait)
|
||||
&& bound.modifier == TraitBoundModifier::Maybe
|
||||
})
|
||||
.map(|bound| (bound.param, bound))
|
||||
.collect();
|
||||
|
||||
for bound in type_param_bounds(generics) {
|
||||
if bound.modifier == TraitBoundModifier::None
|
||||
&& let Some(sized_bound) = maybe_sized_params.get(&bound.param)
|
||||
&& let Some(path) = path_to_sized_bound(cx, bound.trait_bound)
|
||||
{
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
NEEDLESS_MAYBE_SIZED,
|
||||
sized_bound.trait_bound.span,
|
||||
"`?Sized` bound is ignored because of a `Sized` requirement",
|
||||
|diag| {
|
||||
let ty_param = sized_bound.ident;
|
||||
diag.span_note(
|
||||
bound.trait_bound.span,
|
||||
format!("`{ty_param}` cannot be unsized because of the bound"),
|
||||
);
|
||||
|
||||
for &[current_id, next_id] in path.array_windows() {
|
||||
let current = cx.tcx.item_name(current_id);
|
||||
let next = cx.tcx.item_name(next_id);
|
||||
diag.note(format!("...because `{current}` has the bound `{next}`"));
|
||||
}
|
||||
|
||||
diag.span_suggestion_verbose(
|
||||
generics.span_for_bound_removal(sized_bound.predicate_pos, sized_bound.bound_pos),
|
||||
"change the bounds that require `Sized`, or remove the `?Sized` bound",
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
#![allow(clippy::needless_maybe_sized)]
|
||||
#![warn(clippy::type_repetition_in_bounds)]
|
||||
|
||||
fn f<T>()
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: this type has already been used as a bound predicate
|
||||
--> tests/ui-toml/type_repetition_in_bounds/main.rs:13:5
|
||||
--> tests/ui-toml/type_repetition_in_bounds/main.rs:14:5
|
||||
|
|
||||
LL | T: Unpin + PartialEq,
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -57,7 +57,7 @@ fn group_with_span(delimiter: Delimiter, stream: TokenStream, span: Span) -> Gro
|
||||
const ESCAPE_CHAR: char = '$';
|
||||
|
||||
/// Takes a single token followed by a sequence of tokens. Returns the sequence of tokens with their
|
||||
/// span set to that of the first token. Tokens may be escaped with either `#ident` or `#(tokens)`.
|
||||
/// span set to that of the first token. Tokens may be escaped with either `$ident` or `$(tokens)`.
|
||||
#[proc_macro]
|
||||
pub fn with_span(input: TokenStream) -> TokenStream {
|
||||
let mut iter = input.into_iter();
|
||||
@ -71,7 +71,7 @@ pub fn with_span(input: TokenStream) -> TokenStream {
|
||||
}
|
||||
|
||||
/// Takes a sequence of tokens and return the tokens with the span set such that they appear to be
|
||||
/// from an external macro. Tokens may be escaped with either `#ident` or `#(tokens)`.
|
||||
/// from an external macro. Tokens may be escaped with either `$ident` or `$(tokens)`.
|
||||
#[proc_macro]
|
||||
pub fn external(input: TokenStream) -> TokenStream {
|
||||
let mut res = TokenStream::new();
|
||||
@ -83,7 +83,7 @@ pub fn external(input: TokenStream) -> TokenStream {
|
||||
}
|
||||
|
||||
/// Copies all the tokens, replacing all their spans with the given span. Tokens can be escaped
|
||||
/// either by `#ident` or `#(tokens)`.
|
||||
/// either by `$ident` or `$(tokens)`.
|
||||
fn write_with_span(s: Span, mut input: IntoIter, out: &mut TokenStream) -> Result<()> {
|
||||
while let Some(tt) = input.next() {
|
||||
match tt {
|
||||
|
116
tests/ui/needless_maybe_sized.fixed
Normal file
116
tests/ui/needless_maybe_sized.fixed
Normal file
@ -0,0 +1,116 @@
|
||||
//@aux-build:proc_macros.rs
|
||||
|
||||
#![allow(unused, clippy::multiple_bound_locations)]
|
||||
#![warn(clippy::needless_maybe_sized)]
|
||||
|
||||
extern crate proc_macros;
|
||||
use proc_macros::external;
|
||||
|
||||
fn directly<T: Sized>(t: &T) {}
|
||||
|
||||
trait A: Sized {}
|
||||
trait B: A {}
|
||||
|
||||
fn depth_1<T: A>(t: &T) {}
|
||||
fn depth_2<T: B>(t: &T) {}
|
||||
|
||||
// We only need to show one
|
||||
fn multiple_paths<T: A + B>(t: &T) {}
|
||||
|
||||
fn in_where<T>(t: &T)
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
}
|
||||
|
||||
fn mixed_1<T: Sized>(t: &T)
|
||||
{
|
||||
}
|
||||
|
||||
fn mixed_2<T>(t: &T)
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
}
|
||||
|
||||
fn mixed_3<T>(t: &T)
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
}
|
||||
|
||||
struct Struct<T: Sized>(T);
|
||||
|
||||
impl<T: Sized> Struct<T> {
|
||||
fn method<U: Sized>(&self) {}
|
||||
}
|
||||
|
||||
enum Enum<T: Sized + 'static> {
|
||||
Variant(&'static T),
|
||||
}
|
||||
|
||||
union Union<'a, T: Sized> {
|
||||
a: &'a T,
|
||||
}
|
||||
|
||||
trait Trait<T: Sized> {
|
||||
fn trait_method<U: Sized>() {}
|
||||
|
||||
type GAT<U: Sized>;
|
||||
|
||||
type Assoc: Sized + ?Sized; // False negative
|
||||
}
|
||||
|
||||
trait SecondInTrait: Send + Sized {}
|
||||
fn second_in_trait<T: SecondInTrait>() {}
|
||||
|
||||
fn impl_trait(_: &(impl Sized)) {}
|
||||
|
||||
trait GenericTrait<T>: Sized {}
|
||||
fn in_generic_trait<T: GenericTrait<U>, U>() {}
|
||||
|
||||
mod larger_graph {
|
||||
// C1 C2 Sized
|
||||
// \ /\ /
|
||||
// B1 B2
|
||||
// \ /
|
||||
// A1
|
||||
|
||||
trait C1 {}
|
||||
trait C2 {}
|
||||
trait B1: C1 + C2 {}
|
||||
trait B2: C2 + Sized {}
|
||||
trait A1: B1 + B2 {}
|
||||
|
||||
fn larger_graph<T: A1>() {}
|
||||
}
|
||||
|
||||
// Should not lint
|
||||
|
||||
fn sized<T: Sized>() {}
|
||||
fn maybe_sized<T: ?Sized>() {}
|
||||
|
||||
struct SeparateBounds<T: ?Sized>(T);
|
||||
impl<T: Sized> SeparateBounds<T> {}
|
||||
|
||||
trait P {}
|
||||
trait Q: P {}
|
||||
|
||||
fn ok_depth_1<T: P + ?Sized>() {}
|
||||
fn ok_depth_2<T: Q + ?Sized>() {}
|
||||
|
||||
external! {
|
||||
fn in_macro<T: Clone + ?Sized>(t: &T) {}
|
||||
|
||||
fn with_local_clone<T: $Clone + ?Sized>(t: &T) {}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct InDerive<T: ?Sized> {
|
||||
t: T,
|
||||
}
|
||||
|
||||
struct Refined<T: ?Sized>(T);
|
||||
impl<T: Sized> Refined<T> {}
|
||||
|
||||
fn main() {}
|
119
tests/ui/needless_maybe_sized.rs
Normal file
119
tests/ui/needless_maybe_sized.rs
Normal file
@ -0,0 +1,119 @@
|
||||
//@aux-build:proc_macros.rs
|
||||
|
||||
#![allow(unused, clippy::multiple_bound_locations)]
|
||||
#![warn(clippy::needless_maybe_sized)]
|
||||
|
||||
extern crate proc_macros;
|
||||
use proc_macros::external;
|
||||
|
||||
fn directly<T: Sized + ?Sized>(t: &T) {}
|
||||
|
||||
trait A: Sized {}
|
||||
trait B: A {}
|
||||
|
||||
fn depth_1<T: A + ?Sized>(t: &T) {}
|
||||
fn depth_2<T: B + ?Sized>(t: &T) {}
|
||||
|
||||
// We only need to show one
|
||||
fn multiple_paths<T: A + B + ?Sized>(t: &T) {}
|
||||
|
||||
fn in_where<T>(t: &T)
|
||||
where
|
||||
T: Sized + ?Sized,
|
||||
{
|
||||
}
|
||||
|
||||
fn mixed_1<T: Sized>(t: &T)
|
||||
where
|
||||
T: ?Sized,
|
||||
{
|
||||
}
|
||||
|
||||
fn mixed_2<T: ?Sized>(t: &T)
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
}
|
||||
|
||||
fn mixed_3<T>(t: &T)
|
||||
where
|
||||
T: Sized,
|
||||
T: ?Sized,
|
||||
{
|
||||
}
|
||||
|
||||
struct Struct<T: Sized + ?Sized>(T);
|
||||
|
||||
impl<T: Sized + ?Sized> Struct<T> {
|
||||
fn method<U: Sized + ?Sized>(&self) {}
|
||||
}
|
||||
|
||||
enum Enum<T: Sized + ?Sized + 'static> {
|
||||
Variant(&'static T),
|
||||
}
|
||||
|
||||
union Union<'a, T: Sized + ?Sized> {
|
||||
a: &'a T,
|
||||
}
|
||||
|
||||
trait Trait<T: Sized + ?Sized> {
|
||||
fn trait_method<U: Sized + ?Sized>() {}
|
||||
|
||||
type GAT<U: Sized + ?Sized>;
|
||||
|
||||
type Assoc: Sized + ?Sized; // False negative
|
||||
}
|
||||
|
||||
trait SecondInTrait: Send + Sized {}
|
||||
fn second_in_trait<T: ?Sized + SecondInTrait>() {}
|
||||
|
||||
fn impl_trait(_: &(impl Sized + ?Sized)) {}
|
||||
|
||||
trait GenericTrait<T>: Sized {}
|
||||
fn in_generic_trait<T: GenericTrait<U> + ?Sized, U>() {}
|
||||
|
||||
mod larger_graph {
|
||||
// C1 C2 Sized
|
||||
// \ /\ /
|
||||
// B1 B2
|
||||
// \ /
|
||||
// A1
|
||||
|
||||
trait C1 {}
|
||||
trait C2 {}
|
||||
trait B1: C1 + C2 {}
|
||||
trait B2: C2 + Sized {}
|
||||
trait A1: B1 + B2 {}
|
||||
|
||||
fn larger_graph<T: A1 + ?Sized>() {}
|
||||
}
|
||||
|
||||
// Should not lint
|
||||
|
||||
fn sized<T: Sized>() {}
|
||||
fn maybe_sized<T: ?Sized>() {}
|
||||
|
||||
struct SeparateBounds<T: ?Sized>(T);
|
||||
impl<T: Sized> SeparateBounds<T> {}
|
||||
|
||||
trait P {}
|
||||
trait Q: P {}
|
||||
|
||||
fn ok_depth_1<T: P + ?Sized>() {}
|
||||
fn ok_depth_2<T: Q + ?Sized>() {}
|
||||
|
||||
external! {
|
||||
fn in_macro<T: Clone + ?Sized>(t: &T) {}
|
||||
|
||||
fn with_local_clone<T: $Clone + ?Sized>(t: &T) {}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct InDerive<T: ?Sized> {
|
||||
t: T,
|
||||
}
|
||||
|
||||
struct Refined<T: ?Sized>(T);
|
||||
impl<T: Sized> Refined<T> {}
|
||||
|
||||
fn main() {}
|
353
tests/ui/needless_maybe_sized.stderr
Normal file
353
tests/ui/needless_maybe_sized.stderr
Normal file
@ -0,0 +1,353 @@
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:9:24
|
||||
|
|
||||
LL | fn directly<T: Sized + ?Sized>(t: &T) {}
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `T` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:9:16
|
||||
|
|
||||
LL | fn directly<T: Sized + ?Sized>(t: &T) {}
|
||||
| ^^^^^
|
||||
= note: `-D clippy::needless-maybe-sized` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::needless_maybe_sized)]`
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - fn directly<T: Sized + ?Sized>(t: &T) {}
|
||||
LL + fn directly<T: Sized>(t: &T) {}
|
||||
|
|
||||
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:14:19
|
||||
|
|
||||
LL | fn depth_1<T: A + ?Sized>(t: &T) {}
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `T` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:14:15
|
||||
|
|
||||
LL | fn depth_1<T: A + ?Sized>(t: &T) {}
|
||||
| ^
|
||||
= note: ...because `A` has the bound `Sized`
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - fn depth_1<T: A + ?Sized>(t: &T) {}
|
||||
LL + fn depth_1<T: A>(t: &T) {}
|
||||
|
|
||||
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:15:19
|
||||
|
|
||||
LL | fn depth_2<T: B + ?Sized>(t: &T) {}
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `T` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:15:15
|
||||
|
|
||||
LL | fn depth_2<T: B + ?Sized>(t: &T) {}
|
||||
| ^
|
||||
= note: ...because `B` has the bound `A`
|
||||
= note: ...because `A` has the bound `Sized`
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - fn depth_2<T: B + ?Sized>(t: &T) {}
|
||||
LL + fn depth_2<T: B>(t: &T) {}
|
||||
|
|
||||
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:18:30
|
||||
|
|
||||
LL | fn multiple_paths<T: A + B + ?Sized>(t: &T) {}
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `T` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:18:22
|
||||
|
|
||||
LL | fn multiple_paths<T: A + B + ?Sized>(t: &T) {}
|
||||
| ^
|
||||
= note: ...because `A` has the bound `Sized`
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - fn multiple_paths<T: A + B + ?Sized>(t: &T) {}
|
||||
LL + fn multiple_paths<T: A + B>(t: &T) {}
|
||||
|
|
||||
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:22:16
|
||||
|
|
||||
LL | T: Sized + ?Sized,
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `T` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:22:8
|
||||
|
|
||||
LL | T: Sized + ?Sized,
|
||||
| ^^^^^
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - T: Sized + ?Sized,
|
||||
LL + T: Sized,
|
||||
|
|
||||
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:28:8
|
||||
|
|
||||
LL | T: ?Sized,
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `T` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:26:15
|
||||
|
|
||||
LL | fn mixed_1<T: Sized>(t: &T)
|
||||
| ^^^^^
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - where
|
||||
LL - T: ?Sized,
|
||||
|
|
||||
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:32:15
|
||||
|
|
||||
LL | fn mixed_2<T: ?Sized>(t: &T)
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `T` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:34:8
|
||||
|
|
||||
LL | T: Sized,
|
||||
| ^^^^^
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - fn mixed_2<T: ?Sized>(t: &T)
|
||||
LL + fn mixed_2<T>(t: &T)
|
||||
|
|
||||
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:41:8
|
||||
|
|
||||
LL | T: ?Sized,
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `T` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:40:8
|
||||
|
|
||||
LL | T: Sized,
|
||||
| ^^^^^
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - T: Sized,
|
||||
LL - T: ?Sized,
|
||||
LL + T: Sized,
|
||||
|
|
||||
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:45:26
|
||||
|
|
||||
LL | struct Struct<T: Sized + ?Sized>(T);
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `T` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:45:18
|
||||
|
|
||||
LL | struct Struct<T: Sized + ?Sized>(T);
|
||||
| ^^^^^
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - struct Struct<T: Sized + ?Sized>(T);
|
||||
LL + struct Struct<T: Sized>(T);
|
||||
|
|
||||
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:47:17
|
||||
|
|
||||
LL | impl<T: Sized + ?Sized> Struct<T> {
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `T` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:47:9
|
||||
|
|
||||
LL | impl<T: Sized + ?Sized> Struct<T> {
|
||||
| ^^^^^
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - impl<T: Sized + ?Sized> Struct<T> {
|
||||
LL + impl<T: Sized> Struct<T> {
|
||||
|
|
||||
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:48:26
|
||||
|
|
||||
LL | fn method<U: Sized + ?Sized>(&self) {}
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `U` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:48:18
|
||||
|
|
||||
LL | fn method<U: Sized + ?Sized>(&self) {}
|
||||
| ^^^^^
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - fn method<U: Sized + ?Sized>(&self) {}
|
||||
LL + fn method<U: Sized>(&self) {}
|
||||
|
|
||||
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:51:22
|
||||
|
|
||||
LL | enum Enum<T: Sized + ?Sized + 'static> {
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `T` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:51:14
|
||||
|
|
||||
LL | enum Enum<T: Sized + ?Sized + 'static> {
|
||||
| ^^^^^
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - enum Enum<T: Sized + ?Sized + 'static> {
|
||||
LL + enum Enum<T: Sized + 'static> {
|
||||
|
|
||||
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:55:28
|
||||
|
|
||||
LL | union Union<'a, T: Sized + ?Sized> {
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `T` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:55:20
|
||||
|
|
||||
LL | union Union<'a, T: Sized + ?Sized> {
|
||||
| ^^^^^
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - union Union<'a, T: Sized + ?Sized> {
|
||||
LL + union Union<'a, T: Sized> {
|
||||
|
|
||||
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:59:24
|
||||
|
|
||||
LL | trait Trait<T: Sized + ?Sized> {
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `T` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:59:16
|
||||
|
|
||||
LL | trait Trait<T: Sized + ?Sized> {
|
||||
| ^^^^^
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - trait Trait<T: Sized + ?Sized> {
|
||||
LL + trait Trait<T: Sized> {
|
||||
|
|
||||
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:60:32
|
||||
|
|
||||
LL | fn trait_method<U: Sized + ?Sized>() {}
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `U` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:60:24
|
||||
|
|
||||
LL | fn trait_method<U: Sized + ?Sized>() {}
|
||||
| ^^^^^
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - fn trait_method<U: Sized + ?Sized>() {}
|
||||
LL + fn trait_method<U: Sized>() {}
|
||||
|
|
||||
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:62:25
|
||||
|
|
||||
LL | type GAT<U: Sized + ?Sized>;
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `U` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:62:17
|
||||
|
|
||||
LL | type GAT<U: Sized + ?Sized>;
|
||||
| ^^^^^
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - type GAT<U: Sized + ?Sized>;
|
||||
LL + type GAT<U: Sized>;
|
||||
|
|
||||
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:68:23
|
||||
|
|
||||
LL | fn second_in_trait<T: ?Sized + SecondInTrait>() {}
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `T` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:68:32
|
||||
|
|
||||
LL | fn second_in_trait<T: ?Sized + SecondInTrait>() {}
|
||||
| ^^^^^^^^^^^^^
|
||||
= note: ...because `SecondInTrait` has the bound `Sized`
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - fn second_in_trait<T: ?Sized + SecondInTrait>() {}
|
||||
LL + fn second_in_trait<T: SecondInTrait>() {}
|
||||
|
|
||||
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:70:33
|
||||
|
|
||||
LL | fn impl_trait(_: &(impl Sized + ?Sized)) {}
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `impl Sized + ?Sized` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:70:25
|
||||
|
|
||||
LL | fn impl_trait(_: &(impl Sized + ?Sized)) {}
|
||||
| ^^^^^
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - fn impl_trait(_: &(impl Sized + ?Sized)) {}
|
||||
LL + fn impl_trait(_: &(impl Sized)) {}
|
||||
|
|
||||
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:73:42
|
||||
|
|
||||
LL | fn in_generic_trait<T: GenericTrait<U> + ?Sized, U>() {}
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `T` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:73:24
|
||||
|
|
||||
LL | fn in_generic_trait<T: GenericTrait<U> + ?Sized, U>() {}
|
||||
| ^^^^^^^^^^^^^^^
|
||||
= note: ...because `GenericTrait` has the bound `Sized`
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - fn in_generic_trait<T: GenericTrait<U> + ?Sized, U>() {}
|
||||
LL + fn in_generic_trait<T: GenericTrait<U>, U>() {}
|
||||
|
|
||||
|
||||
error: `?Sized` bound is ignored because of a `Sized` requirement
|
||||
--> tests/ui/needless_maybe_sized.rs:88:29
|
||||
|
|
||||
LL | fn larger_graph<T: A1 + ?Sized>() {}
|
||||
| ^^^^^^
|
||||
|
|
||||
note: `T` cannot be unsized because of the bound
|
||||
--> tests/ui/needless_maybe_sized.rs:88:24
|
||||
|
|
||||
LL | fn larger_graph<T: A1 + ?Sized>() {}
|
||||
| ^^
|
||||
= note: ...because `A1` has the bound `B2`
|
||||
= note: ...because `B2` has the bound `Sized`
|
||||
help: change the bounds that require `Sized`, or remove the `?Sized` bound
|
||||
|
|
||||
LL - fn larger_graph<T: A1 + ?Sized>() {}
|
||||
LL + fn larger_graph<T: A1>() {}
|
||||
|
|
||||
|
||||
error: aborting due to 20 previous errors
|
||||
|
@ -1,5 +1,9 @@
|
||||
#![deny(clippy::type_repetition_in_bounds)]
|
||||
#![allow(clippy::extra_unused_type_parameters, clippy::multiple_bound_locations)]
|
||||
#![allow(
|
||||
clippy::extra_unused_type_parameters,
|
||||
clippy::multiple_bound_locations,
|
||||
clippy::needless_maybe_sized
|
||||
)]
|
||||
|
||||
use serde::Deserialize;
|
||||
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: this type has already been used as a bound predicate
|
||||
--> tests/ui/type_repetition_in_bounds.rs:10:5
|
||||
--> tests/ui/type_repetition_in_bounds.rs:14:5
|
||||
|
|
||||
LL | T: Clone,
|
||||
| ^^^^^^^^
|
||||
@ -12,7 +12,7 @@ LL | #![deny(clippy::type_repetition_in_bounds)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: this type has already been used as a bound predicate
|
||||
--> tests/ui/type_repetition_in_bounds.rs:28:5
|
||||
--> tests/ui/type_repetition_in_bounds.rs:32:5
|
||||
|
|
||||
LL | Self: Copy + Default + Ord,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -20,7 +20,7 @@ LL | Self: Copy + Default + Ord,
|
||||
= help: consider combining the bounds: `Self: Clone + Copy + Default + Ord`
|
||||
|
||||
error: this type has already been used as a bound predicate
|
||||
--> tests/ui/type_repetition_in_bounds.rs:103:5
|
||||
--> tests/ui/type_repetition_in_bounds.rs:107:5
|
||||
|
|
||||
LL | T: Clone,
|
||||
| ^^^^^^^^
|
||||
@ -28,7 +28,7 @@ LL | T: Clone,
|
||||
= help: consider combining the bounds: `T: ?Sized + Clone`
|
||||
|
||||
error: this type has already been used as a bound predicate
|
||||
--> tests/ui/type_repetition_in_bounds.rs:109:5
|
||||
--> tests/ui/type_repetition_in_bounds.rs:113:5
|
||||
|
|
||||
LL | T: ?Sized,
|
||||
| ^^^^^^^^^
|
||||
@ -36,7 +36,7 @@ LL | T: ?Sized,
|
||||
= help: consider combining the bounds: `T: Clone + ?Sized`
|
||||
|
||||
error: this type has already been used as a bound predicate
|
||||
--> tests/ui/type_repetition_in_bounds.rs:135:9
|
||||
--> tests/ui/type_repetition_in_bounds.rs:139:9
|
||||
|
|
||||
LL | T: Trait<Option<usize>, Box<[String]>, bool> + 'static,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
Loading…
Reference in New Issue
Block a user