`use_self` does not notice Self with lifetimes
Summary
Types where a lifetime is involved don't get noticed by use_self. Generics are no issue. Cow<'a, B> with both lifetime and generic are also not noticed.
clippy::return_self_not_must_use finds these cases.
Lint Name
clippy::use_self
Reproducer
I tried this code:
#![warn(clippy::use_self)]
use std::borrow::Cow;
trait Foo {
type Item;
fn bar(&self) -> Self::Item;
}
#[derive(Clone)]
struct Data<'a> {
value: &'a str,
}
impl<'a> Data<'a> {
pub const fn new(value: &'a str) -> Data<'a> {
Data {value}
}
}
impl<'a> Foo for Data<'a> {
type Item = Data<'a>;
fn bar(&self) -> Self::Item {
self.clone()
}
}
impl<'a, T: ToOwned> Foo for Cow<'a, T> {
type Item = Cow<'a, T>;
fn bar(&self) -> Self::Item {
self.clone()
}
}
struct Something<T> {
value: T,
}
impl<T> Something<T> {
pub const fn new(value: T) -> Something<T> {
Something { value }
}
}
impl<T: Clone> Foo for Something<T> {
type Item = Something<T>;
fn bar(&self) -> Self::Item {
Something { value: self.value.clone() }
}
}
fn main() {
let data = Data::new("Hello");
let first = data.bar().value;
let something = Something::new("world");
let second = something.bar().value;
println!("{first}, {second}!");
}
I expected to see this happen:
Data<'a> should be replaced by Self for type Item = , Data {…} and -> Data<'a>.
Instead, this happened:
Only Something<T> is noticed.
Version
Both current stable and current nightly.
$ rustc -Vv
rustc 1.76.0 (07dca489a 2024-02-04)
binary: rustc
commit-hash: 07dca489ac2d933c78d3c5158e3f43beefeb02ce
commit-date: 2024-02-04
host: x86_64-unknown-linux-gnu
release: 1.76.0
LLVM version: 17.0.6
rustc 1.78.0-nightly (ef324565d 2024-02-27)
binary: rustc
commit-hash: ef324565d071c6d7e2477a195648549e33d6a465
commit-date: 2024-02-27
host: x86_64-unknown-linux-gnu
release: 1.78.0-nightly
LLVM version: 18.1.0
@rustbot claim Forgot about that
@Ethiraric This is not fully solved.
Reviewers of the PR: @GuillaumeGomez @blyxyas
Should this be reopened or a new issue created?
pub struct Data<'a> {
pub value: &'a str,
}
impl<'a> Data<'a> {
pub const fn new(value: &'a str) -> Data<'a> {
Data { value }
}
}
While -> Data<'a> is suggested to be replaced now Data { value } is still not suggested.
I know not whether it is best to re-open this or file another issue. I had a quick glance at the problem you mention. It's in an area of the code I did not change.
It appears to not be detected because this check fails:
cx.typeck_results().expr_ty(expr) == cx.tcx.type_of(impl_id).instantiate_identity()
which debugs to
cx.typeck_results().expr_ty(expr) = Data<'{erased}>
cx.tcx.type_of(impl_id).instantiate_identity() = Data<DefId(0:7 ~ f[d7bf]::{impl#0}::'a)_'a/#0>
I do not understand what this check does, nor what the difference between the 2 really means.
It's in an area of the code I did not change.
Just want to make sure it was not understood as criticism. :innocent: I just noticed earlier today that it is only partly solved so it shouldn't have been closed yet. (Thank your for your part! It was awesome to see my issue being picked up as fast as it did!)
Oh no offense taken don't worry. I was mostly commenting my findings.
The thing is that I changed types while Data { value } is an expression.
cx.typeck_results().expr_ty(expr) == cx.tcx.type_of(impl_id).instantiate_identity()
This is the commit that adds it d1b087f (#8580)
Some other commits after that modified the exact methods used.