Closed
Description
As far as I can tell, the use_self
is incorrectly ignoring generic parameters when implementing traits for some types with generics.
Here's my example:
pub trait PhaseTransform<T>: Sized {
fn transform_from(v: T) -> Self;
}
pub struct IntermediatePhase;
pub struct FinalPhase;
impl PhaseTransform<Vec<IntermediatePhase>> for Vec<FinalPhase> {
fn transform_from(_: Vec<IntermediatePhase>) -> Self {
unimplemented!()
}
}
impl<T> PhaseTransform<Vec<IntermediatePhase>> for Vec<T>
where
T: PhaseTransform<FinalPhase>,
{
fn transform_from(intermediates: Vec<IntermediatePhase>) -> Self {
<Vec<FinalPhase>>::transform_from(intermediates)
.into_iter()
.map(PhaseTransform::transform_from)
.collect()
}
}
This, as far as I can tell, uses Self
as much as possible. But with -W clippy::pedantic
, clippy warns of three more places where it thinks I should be able to use Self
:
$ cargo clippy -- -W clippy::pedantic
Checking clippy-false-positive-test v0.1.0 (/home/daboross/clippy-false-positive-test)
warning: unnecessary structure name repetition
--> src/lib.rs:10:26
|
10 | fn transform_from(_: Vec<IntermediatePhase>) -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
|
= note: `-W clippy::use-self` implied by `-W clippy::pedantic`
= help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/v0.0.212/index.html#use_self
warning: unnecessary structure name repetition
--> src/lib.rs:19:38
|
19 | fn transform_from(intermediates: Vec<IntermediatePhase>) -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
|
= help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/v0.0.212/index.html#use_self
warning: unnecessary structure name repetition
--> src/lib.rs:20:10
|
20 | <Vec<FinalPhase>>::transform_from(intermediates)
| ^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
|
= help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/v0.0.212/index.html#use_self
Finished dev [unoptimized + debuginfo] target(s) in 0.21s
There are two mistakes: it's treating Vec<IntermediatePhase>
as Vec<FinalPhase>
, and it's treating Vec<FinalPhase>
as Vec<T>
.
Hope the example is minimal enough - my original trigger was with a custom trait like this, and it seemed hard to come up with any other reasonable use case which caused this situation.
Clippy version:
$ cargo clippy -V
clippy 0.0.212 (b1d0343 2018-10-19)
Related to #1993.
Activity
ghost commentedon Nov 7, 2018
Here is a another example that doesn't involve traits.
Playground
The problem is that the code checks if two paths refer to the same type by comparing the
def
s but this doesn't account for generics.https://github.com/rust-lang-nursery/rust-clippy/blob/4c3408c61d1042bf0585de440041ee7edfc5b350/clippy_lints/src/use_self.rs#L221
I couldn't find a way to get the actual type including type parameters for a general path. Maybe someone has a suggestion.
I can see how to handle this for types in function signatures though. I'll submit a PR for that later.
use_self
false positive #3423Merge #3423
zroug commentedon Nov 13, 2018
Not involving generics but another false positive:
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=b33a49bdb926b36be6c2fbad5defe205
With generics, the error also happens with associated types:
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=42f001263b6139a9333c08290ccd188c
(Both warnings are wrong.)
zroug commentedon Nov 13, 2018
I don't know how to do that but there is a pull request #1997. There was no activity for a long time but there is a bit of discussion.
eddyb commentedon Apr 7, 2020
IMO clippy should just use
hir_ty_to_ty
until a query alternative is provided.This should be considered an essential operation and clippy should make use of it as much as possible.
It's unnecessary to compare
hir::Ty
s in intricate manners when you can just get aTy
and==
it.rust-lang#3410: add missing false positive case in uitests
tnielens commentedon Apr 23, 2020
I started working on this based on the recommendation and example committed by @eddyb .
rust-lang#3410: add missing false positive case in uitests
4 remaining items
rework use_self impl based on ty::Ty comparison rust-lang#3410
rework use_self impl based on ty::Ty comparison rust-lang#3410
rework use_self impl based on ty::Ty comparison rust-lang#3410
rework use_self impl based on ty::Ty comparison rust-lang#3410
rework use_self impl based on ty::Ty comparison rust-lang#3410
Auto merge of #5531 - montrivo:bugfix/3410-use_self_generic_false_pos…
Auto merge of #6179 - flip1995:rewrite_use_self, r=phansch
kawogi commentedon Jan 26, 2021
I think this is the same problem in a slightly different shape:
The false positive gets triggered twice: once somewhere in the macro (match by accident) and once in the declaration.
CAD97 commentedon Jan 26, 2021
I think that one's different. You could say
let positive: Self = false
, but that's also probably not better. This lint should probably not fire for primitive types.E.g. even in the body of an impl for
!
, it's probably better to refer to!
thanSelf
. ForuN
you could make a case to useSelf
(using the same impl for multipleuN
), but primitives are much more likely to be mentioned when it doesn't matter that they'reSelf
, just that they're the primitive type.Auto merge of #6179 - flip1995:rewrite_use_self, r=<try>
Auto merge of #6179 - flip1995:rewrite_use_self, r=phansch