Skip to content

Commit

Permalink
[use_self] fix suggestion when full path to struct was given
Browse files Browse the repository at this point in the history
Previously the following wrong suggestion was given

```rust
impl Error for std::fmt::Error {
    fn custom<T: std::fmt::Display>(_msg: T) -> Self {
-        std::fmt::Error // Should lint
+        Self::Error // Should lint
    }
}
```

Also remove known problem line related to rust-lang#4140 since it's been closed, and refactor the lint
  • Loading branch information
kraktus committed Oct 26, 2022
1 parent e86e810 commit 1909a6a
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 33 deletions.
38 changes: 14 additions & 24 deletions clippy_lints/src/use_self.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ declare_clippy_lint! {
///
/// ### Known problems
/// - Unaddressed false negative in fn bodies of trait implementations
/// - False positive with associated types in traits (#4140)
///
/// ### Example
/// ```rust
Expand Down Expand Up @@ -235,24 +234,13 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
then {} else { return; }
}
match expr.kind {
ExprKind::Struct(QPath::Resolved(_, path), ..) => match path.res {
Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => (),
Res::Def(DefKind::Variant, _) => lint_path_to_variant(cx, path),
_ => span_lint(cx, path.span),
},
// tuple struct instantiation (`Foo(arg)` or `Enum::Foo(arg)`)
ExprKind::Struct(QPath::Resolved(_, path), ..) => check_path(cx, path),
ExprKind::Call(fun, _) => {
if let ExprKind::Path(QPath::Resolved(_, path)) = fun.kind {
if let Res::Def(DefKind::Ctor(ctor_of, _), ..) = path.res {
match ctor_of {
CtorOf::Variant => lint_path_to_variant(cx, path),
CtorOf::Struct => span_lint(cx, path.span),
}
}
check_path(cx, path);
}
},
// unit enum variants (`Enum::A`)
ExprKind::Path(QPath::Resolved(_, path)) => lint_path_to_variant(cx, path),
ExprKind::Path(QPath::Resolved(_, path)) => check_path(cx, path),
_ => (),
}
}
Expand All @@ -268,15 +256,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
| PatKind::Struct(QPath::Resolved(_, path), _, _) = pat.kind;
if cx.typeck_results().pat_ty(pat) == cx.tcx.type_of(impl_id);
then {
match path.res {
Res::Def(DefKind::Ctor(ctor_of, _), ..) => match ctor_of {
CtorOf::Variant => lint_path_to_variant(cx, path),
CtorOf::Struct => span_lint(cx, path.span),
},
Res::Def(DefKind::Variant, ..) => lint_path_to_variant(cx, path),
Res::Def(DefKind::Struct, ..) => span_lint(cx, path.span),
_ => ()
}
check_path(cx, path);
}
}
}
Expand Down Expand Up @@ -314,6 +294,16 @@ fn span_lint(cx: &LateContext<'_>, span: Span) {
);
}

fn check_path(cx: &LateContext<'_>, path: &Path<'_>) {
match path.res {
Res::Def(DefKind::Ctor(CtorOf::Variant, _) | DefKind::Variant, ..) => {
lint_path_to_variant(cx, path);
},
Res::Def(DefKind::Ctor(CtorOf::Struct, _) | DefKind::Struct, ..) => span_lint(cx, path.span),
_ => (),
}
}

fn lint_path_to_variant(cx: &LateContext<'_>, path: &Path<'_>) {
if let [.., self_seg, _variant] = path.segments {
let span = path
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,11 @@ note: the lint level is defined here
LL | #![deny(clippy::use_self)]
| ^^^^^^^^^^^^^^^^

error: aborting due to previous error; 1 warning emitted
error: unnecessary structure name repetition
--> $DIR/main.rs:7:9
|
LL | Foo
| ^^^ help: use the applicable keyword: `Self`

error: aborting due to 2 previous errors; 1 warning emitted

Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@ note: the lint level is defined here
LL | #![deny(clippy::use_self)]
| ^^^^^^^^^^^^^^^^

error: aborting due to previous error
error: unnecessary structure name repetition
--> $DIR/main.rs:7:9
|
LL | Foo
| ^^^ help: use the applicable keyword: `Self`

error: aborting due to 2 previous errors

8 changes: 7 additions & 1 deletion tests/ui-cargo/cargo_rust_version/fail_cargo/src/main.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@ note: the lint level is defined here
LL | #![deny(clippy::use_self)]
| ^^^^^^^^^^^^^^^^

error: aborting due to previous error
error: unnecessary structure name repetition
--> $DIR/main.rs:7:9
|
LL | Foo
| ^^^ help: use the applicable keyword: `Self`

error: aborting due to 2 previous errors

Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@ note: the lint level is defined here
LL | #![deny(clippy::use_self)]
| ^^^^^^^^^^^^^^^^

error: aborting due to previous error
error: unnecessary structure name repetition
--> $DIR/main.rs:7:9
|
LL | Foo
| ^^^ help: use the applicable keyword: `Self`

error: aborting due to 2 previous errors

Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@ note: the lint level is defined here
LL | #![deny(clippy::use_self)]
| ^^^^^^^^^^^^^^^^

error: aborting due to previous error
error: unnecessary structure name repetition
--> $DIR/main.rs:12:9
|
LL | Foo
| ^^^ help: use the applicable keyword: `Self`

error: aborting due to 2 previous errors

15 changes: 13 additions & 2 deletions tests/ui/use_self_trait.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ impl Mul for Bad {

impl Clone for Bad {
fn clone(&self) -> Self {
// FIXME: applicable here
Bad
Self
}
}

Expand Down Expand Up @@ -138,4 +137,16 @@ mod impl_in_macro {
parse_ip_impl!(Foo); // Should not lint
}

mod full_path_replacement {
trait Error {
fn custom<T: std::fmt::Display>(_msg: T) -> Self;
}

impl Error for std::fmt::Error {
fn custom<T: std::fmt::Display>(_msg: T) -> Self {
Self // Should lint
}
}
}

fn main() {}
13 changes: 12 additions & 1 deletion tests/ui/use_self_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ impl Mul for Bad {

impl Clone for Bad {
fn clone(&self) -> Self {
// FIXME: applicable here
Bad
}
}
Expand Down Expand Up @@ -138,4 +137,16 @@ mod impl_in_macro {
parse_ip_impl!(Foo); // Should not lint
}

mod full_path_replacement {
trait Error {
fn custom<T: std::fmt::Display>(_msg: T) -> Self;
}

impl Error for std::fmt::Error {
fn custom<T: std::fmt::Display>(_msg: T) -> Self {
std::fmt::Error // Should lint
}
}
}

fn main() {}
14 changes: 13 additions & 1 deletion tests/ui/use_self_trait.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,17 @@ error: unnecessary structure name repetition
LL | fn mul(self, rhs: Bad) -> Bad {
| ^^^ help: use the applicable keyword: `Self`

error: aborting due to 14 previous errors
error: unnecessary structure name repetition
--> $DIR/use_self_trait.rs:50:9
|
LL | Bad
| ^^^ help: use the applicable keyword: `Self`

error: unnecessary structure name repetition
--> $DIR/use_self_trait.rs:147:13
|
LL | std::fmt::Error // Should lint
| ^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`

error: aborting due to 16 previous errors

0 comments on commit 1909a6a

Please sign in to comment.