diff options
| author | bors <bors@rust-lang.org> | 2023-09-13 23:46:27 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-09-13 23:46:27 +0000 |
| commit | 2009b58df27aab2463eaaba8b870aee09caabf1e (patch) | |
| tree | eb75397b57b38c42e545f968876d6bf78202e0fa | |
| parent | b788addfcc955368b9771b77d312c248fab60253 (diff) | |
| parent | 26c0f97579763363310bc32cf6d8ef4cd6f5588f (diff) | |
| download | rust-2009b58df27aab2463eaaba8b870aee09caabf1e.tar.gz rust-2009b58df27aab2463eaaba8b870aee09caabf1e.zip | |
Auto merge of #11452 - y21:issue11165, r=Centri3
[`len_without_is_empty`]: follow type alias to find inherent `is_empty` method Fixes #11165 When we see an `impl B` and `B` is a type alias to some type `A`, then we need to follow the type alias to look for an `is_empty` method on the aliased type `A`. Before this PR, it'd get the inherent impls of `B`, which there aren't any and so it would warn that there isn't an `is_empty` method even if there was one. Passing the type alias `DefId` to `TyCtxt::type_of` gives us the aliased `DefId` (or simply return the type itself if it wasn't a type alias) so we can just use that changelog: [`len_without_is_empty`]: follow type alias to find inherent `is_empty` method
| -rw-r--r-- | clippy_lints/src/len_zero.rs | 8 | ||||
| -rw-r--r-- | tests/ui/len_without_is_empty.rs | 23 | ||||
| -rw-r--r-- | tests/ui/len_without_is_empty.stderr | 8 |
3 files changed, 38 insertions, 1 deletions
diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index deba232bdd2..c06b35ca0da 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -424,6 +424,14 @@ fn check_for_is_empty( item_name: Symbol, item_kind: &str, ) { + // Implementor may be a type alias, in which case we need to get the `DefId` of the aliased type to + // find the correct inherent impls. + let impl_ty = if let Some(adt) = cx.tcx.type_of(impl_ty).skip_binder().ty_adt_def() { + adt.did() + } else { + return; + }; + let is_empty = Symbol::intern("is_empty"); let is_empty = cx .tcx diff --git a/tests/ui/len_without_is_empty.rs b/tests/ui/len_without_is_empty.rs index ac6c3e06365..d623601110e 100644 --- a/tests/ui/len_without_is_empty.rs +++ b/tests/ui/len_without_is_empty.rs @@ -436,4 +436,27 @@ impl DifferingErrors { } } +// Issue #11165 +pub struct Aliased1; +pub type Alias1 = Aliased1; + +impl Alias1 { + pub fn len(&self) -> usize { + todo!() + } + + pub fn is_empty(&self) -> bool { + todo!() + } +} + +pub struct Aliased2; +pub type Alias2 = Aliased2; +impl Alias2 { + pub fn len(&self) -> usize { + //~^ ERROR: type `Alias2` has a public `len` method, but no `is_empty` method + todo!() + } +} + fn main() {} diff --git a/tests/ui/len_without_is_empty.stderr b/tests/ui/len_without_is_empty.stderr index 4815ce6a04b..8e51c28b330 100644 --- a/tests/ui/len_without_is_empty.stderr +++ b/tests/ui/len_without_is_empty.stderr @@ -141,5 +141,11 @@ error: struct `AsyncResultLenWithoutIsEmpty` has a public `len` method, but no ` LL | pub async fn len(&self) -> Result<usize, ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 15 previous errors +error: type `Alias2` has a public `len` method, but no `is_empty` method + --> $DIR/len_without_is_empty.rs:456:5 + | +LL | pub fn len(&self) -> usize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 16 previous errors |
