rust-clippy icon indicating copy to clipboard operation
rust-clippy copied to clipboard

`use_self` does not notice Self with lifetimes

Open EdJoPaTo opened this issue 1 year ago • 6 comments

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

EdJoPaTo avatar Feb 28 '24 21:02 EdJoPaTo

@rustbot claim Forgot about that

Ethiraric avatar Mar 01 '24 13:03 Ethiraric

@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.

EdJoPaTo avatar Apr 16 '24 12:04 EdJoPaTo

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.

Ethiraric avatar Apr 16 '24 13:04 Ethiraric

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!)

EdJoPaTo avatar Apr 16 '24 15:04 EdJoPaTo

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.

Ethiraric avatar Apr 16 '24 17:04 Ethiraric

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.

blyxyas avatar Apr 16 '24 23:04 blyxyas