Auto merge of #12177 - y21:issue12154, r=Jarcho
[`unconditional_recursion`]: compare by `Ty`s instead of `DefId`s
Fixes #12154
Fixes #12181 (this was later edited in, so the rest of the description refers to the first linked issue)
Before this change, the lint would work with `DefId`s and use those to compare types. This PR changes it to compare types directly. It fixes the linked issue, but also other false positives I found in a lintcheck run. For example, one of the issues is that some types don't have `DefId`s (primitives, references, etc., leading to possible FNs), and the helper function used to extract a `DefId` didn't handle type parameters.
Another issue was that the lint would use `.peel_refs()` in a few places where that could lead to false positives (one such FP was in the `http` crate). See the doc comment on one of the added functions and also the test case for what I mean.
The code in the linked issue was linted because the receiver type is `T` (a `ty::Param`), which was not handled in `get_ty_def_id` and returned `None`, so this wouldn't actually *get* to comparing `self_arg != ty_id` here, and skip the early-return:
70573af31e/clippy_lints/src/unconditional_recursion.rs (L171-L178)
This alone could be fixed by doing something like `&& get_ty_def_id(ty).map_or(true, |ty_id)| self_arg != ty_id)`, but we don't really need to work with `DefId`s in the first place, I don't think.
changelog: [`unconditional_recursion`]: avoid linting when the other comparison type is a type parameter
This commit is contained in:
commit
62dcbd672b
2 changed files with 106 additions and 39 deletions
|
|
@ -291,4 +291,63 @@ impl PartialEq for S15<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
mod issue12154 {
|
||||
struct MyBox<T>(T);
|
||||
|
||||
impl<T> std::ops::Deref for MyBox<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq> PartialEq for MyBox<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
(**self).eq(&**other)
|
||||
}
|
||||
}
|
||||
|
||||
// Not necessarily related to the issue but another FP from the http crate that was fixed with it:
|
||||
// https://docs.rs/http/latest/src/http/header/name.rs.html#1424
|
||||
// We used to simply peel refs from the LHS and RHS, so we couldn't differentiate
|
||||
// between `PartialEq<T> for &T` and `PartialEq<&T> for T` impls.
|
||||
#[derive(PartialEq)]
|
||||
struct HeaderName;
|
||||
impl<'a> PartialEq<&'a HeaderName> for HeaderName {
|
||||
fn eq(&self, other: &&'a HeaderName) -> bool {
|
||||
*self == **other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialEq<HeaderName> for &'a HeaderName {
|
||||
fn eq(&self, other: &HeaderName) -> bool {
|
||||
*other == *self
|
||||
}
|
||||
}
|
||||
|
||||
// Issue #12181 but also fixed by the same PR
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
fn as_str(&self) -> &str {
|
||||
"Foo"
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Foo {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.as_str().eq(other.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PartialEq<T> for Foo
|
||||
where
|
||||
for<'a> &'a str: PartialEq<T>,
|
||||
{
|
||||
fn eq(&self, other: &T) -> bool {
|
||||
(&self.as_str()).eq(other)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue