Skip to content

Commit c992247

Browse files
committed
Auto merge of #12054 - y21:issue12037, r=Jarcho
add external macro checks to `iter_without_into_iter` and `into_iter_without_iter` Fixes #12037 I think it's useful to still lint on local macros, since the user should still be able to add another impl with the `IntoIterator` or `iter` method. I think it's also fairly common to write a macro for generating many impls (e.g. for many similar types), so it'd be nice if we can continue linting in those cases. For that reason I went with `in_external_macro`. I also added a test for `#[allow]`ing the lint while I was at it. changelog: [`iter_without_into_iter`]: don't lint if the `iter` method is defined in an external macro changelog: [`into_iter_without_iter`]: don't lint if the `IntoIterator` impl is defined in an external macro
2 parents 174a0d7 + 0848e12 commit c992247

5 files changed

+140
-17
lines changed

clippy_lints/src/iter_without_into_iter.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use clippy_utils::ty::{implements_trait, make_normalized_projection};
55
use rustc_ast::Mutability;
66
use rustc_errors::Applicability;
77
use rustc_hir::{FnRetTy, ImplItemKind, ImplicitSelfKind, ItemKind, TyKind};
8-
use rustc_lint::{LateContext, LateLintPass};
8+
use rustc_lint::{LateContext, LateLintPass, LintContext};
9+
use rustc_middle::lint::in_external_macro;
910
use rustc_middle::ty::{self, Ty};
1011
use rustc_session::declare_lint_pass;
1112
use rustc_span::{sym, Symbol};
@@ -152,7 +153,8 @@ fn adt_has_inherent_method(cx: &LateContext<'_>, ty: Ty<'_>, method_name: Symbol
152153

153154
impl LateLintPass<'_> for IterWithoutIntoIter {
154155
fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) {
155-
if let ItemKind::Impl(imp) = item.kind
156+
if !in_external_macro(cx.sess(), item.span)
157+
&& let ItemKind::Impl(imp) = item.kind
156158
&& let TyKind::Ref(_, self_ty_without_ref) = &imp.self_ty.kind
157159
&& let Some(trait_ref) = imp.of_trait
158160
&& trait_ref
@@ -219,7 +221,8 @@ impl {self_ty_without_ref} {{
219221
_ => return,
220222
};
221223

222-
if let ImplItemKind::Fn(sig, _) = item.kind
224+
if !in_external_macro(cx.sess(), item.span)
225+
&& let ImplItemKind::Fn(sig, _) = item.kind
223226
&& let FnRetTy::Return(ret) = sig.decl.output
224227
&& is_nameable_in_impl_trait(ret)
225228
&& cx.tcx.generics_of(item_did).params.is_empty()

tests/ui/into_iter_without_iter.rs

+39
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//@no-rustfix
2+
//@aux-build:proc_macros.rs
23
#![warn(clippy::into_iter_without_iter)]
4+
extern crate proc_macros;
35

46
use std::iter::IntoIterator;
57

@@ -111,6 +113,43 @@ impl IntoIterator for &Alias {
111113
}
112114
}
113115

116+
// Fine to lint, the impls comes from a local macro.
117+
pub struct Issue12037;
118+
macro_rules! generate_impl {
119+
() => {
120+
impl<'a> IntoIterator for &'a Issue12037 {
121+
type IntoIter = std::slice::Iter<'a, u8>;
122+
type Item = &'a u8;
123+
fn into_iter(self) -> Self::IntoIter {
124+
todo!()
125+
}
126+
}
127+
};
128+
}
129+
generate_impl!();
130+
131+
// Impl comes from an external crate
132+
proc_macros::external! {
133+
pub struct ImplWithForeignSpan;
134+
impl<'a> IntoIterator for &'a ImplWithForeignSpan {
135+
type IntoIter = std::slice::Iter<'a, u8>;
136+
type Item = &'a u8;
137+
fn into_iter(self) -> Self::IntoIter {
138+
todo!()
139+
}
140+
}
141+
}
142+
143+
pub struct Allowed;
144+
#[allow(clippy::into_iter_without_iter)]
145+
impl<'a> IntoIterator for &'a Allowed {
146+
type IntoIter = std::slice::Iter<'a, u8>;
147+
type Item = &'a u8;
148+
fn into_iter(self) -> Self::IntoIter {
149+
todo!()
150+
}
151+
}
152+
114153
fn main() {}
115154

116155
pub mod issue11635 {

tests/ui/into_iter_without_iter.stderr

+32-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: `IntoIterator` implemented for a reference type without an `iter` method
2-
--> $DIR/into_iter_without_iter.rs:7:1
2+
--> $DIR/into_iter_without_iter.rs:9:1
33
|
44
LL | / impl<'a> IntoIterator for &'a S1 {
55
LL | |
@@ -23,7 +23,7 @@ LL + }
2323
|
2424

2525
error: `IntoIterator` implemented for a reference type without an `iter_mut` method
26-
--> $DIR/into_iter_without_iter.rs:15:1
26+
--> $DIR/into_iter_without_iter.rs:17:1
2727
|
2828
LL | / impl<'a> IntoIterator for &'a mut S1 {
2929
LL | |
@@ -45,7 +45,7 @@ LL + }
4545
|
4646

4747
error: `IntoIterator` implemented for a reference type without an `iter` method
48-
--> $DIR/into_iter_without_iter.rs:25:1
48+
--> $DIR/into_iter_without_iter.rs:27:1
4949
|
5050
LL | / impl<'a, T> IntoIterator for &'a S2<T> {
5151
LL | |
@@ -67,7 +67,7 @@ LL + }
6767
|
6868

6969
error: `IntoIterator` implemented for a reference type without an `iter_mut` method
70-
--> $DIR/into_iter_without_iter.rs:33:1
70+
--> $DIR/into_iter_without_iter.rs:35:1
7171
|
7272
LL | / impl<'a, T> IntoIterator for &'a mut S2<T> {
7373
LL | |
@@ -89,7 +89,7 @@ LL + }
8989
|
9090

9191
error: `IntoIterator` implemented for a reference type without an `iter_mut` method
92-
--> $DIR/into_iter_without_iter.rs:84:1
92+
--> $DIR/into_iter_without_iter.rs:86:1
9393
|
9494
LL | / impl<'a, T> IntoIterator for &mut S4<'a, T> {
9595
LL | |
@@ -110,5 +110,31 @@ LL + }
110110
LL + }
111111
|
112112

113-
error: aborting due to 5 previous errors
113+
error: `IntoIterator` implemented for a reference type without an `iter` method
114+
--> $DIR/into_iter_without_iter.rs:120:9
115+
|
116+
LL | / impl<'a> IntoIterator for &'a Issue12037 {
117+
LL | | type IntoIter = std::slice::Iter<'a, u8>;
118+
LL | | type Item = &'a u8;
119+
LL | | fn into_iter(self) -> Self::IntoIter {
120+
LL | | todo!()
121+
LL | | }
122+
LL | | }
123+
| |_________^
124+
...
125+
LL | generate_impl!();
126+
| ---------------- in this macro invocation
127+
|
128+
= note: this error originates in the macro `generate_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
129+
help: consider implementing `iter`
130+
|
131+
LL ~
132+
LL + impl Issue12037 {
133+
LL + fn iter(&self) -> std::slice::Iter<'a, u8> {
134+
LL + <&Self as IntoIterator>::into_iter(self)
135+
LL + }
136+
LL + }
137+
|
138+
139+
error: aborting due to 6 previous errors
114140

tests/ui/iter_without_into_iter.rs

+31
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//@no-rustfix
2+
//@aux-build:proc_macros.rs
23
#![warn(clippy::iter_without_into_iter)]
4+
extern crate proc_macros;
35

46
pub struct S1;
57
impl S1 {
@@ -121,4 +123,33 @@ impl S12 {
121123
}
122124
}
123125

126+
pub struct Issue12037;
127+
macro_rules! generate_impl {
128+
() => {
129+
impl Issue12037 {
130+
fn iter(&self) -> std::slice::Iter<'_, u8> {
131+
todo!()
132+
}
133+
}
134+
};
135+
}
136+
generate_impl!();
137+
138+
proc_macros::external! {
139+
pub struct ImplWithForeignSpan;
140+
impl ImplWithForeignSpan {
141+
fn iter(&self) -> std::slice::Iter<'_, u8> {
142+
todo!()
143+
}
144+
}
145+
}
146+
147+
pub struct Allowed;
148+
impl Allowed {
149+
#[allow(clippy::iter_without_into_iter)]
150+
pub fn iter(&self) -> std::slice::Iter<'_, u8> {
151+
todo!()
152+
}
153+
}
154+
124155
fn main() {}

tests/ui/iter_without_into_iter.stderr

+32-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: `iter` method without an `IntoIterator` impl for `&S1`
2-
--> $DIR/iter_without_into_iter.rs:6:5
2+
--> $DIR/iter_without_into_iter.rs:8:5
33
|
44
LL | / pub fn iter(&self) -> std::slice::Iter<'_, u8> {
55
LL | |
@@ -22,7 +22,7 @@ LL + }
2222
|
2323

2424
error: `iter_mut` method without an `IntoIterator` impl for `&mut S1`
25-
--> $DIR/iter_without_into_iter.rs:10:5
25+
--> $DIR/iter_without_into_iter.rs:12:5
2626
|
2727
LL | / pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
2828
LL | |
@@ -43,7 +43,7 @@ LL + }
4343
|
4444

4545
error: `iter` method without an `IntoIterator` impl for `&S3<'a>`
46-
--> $DIR/iter_without_into_iter.rs:26:5
46+
--> $DIR/iter_without_into_iter.rs:28:5
4747
|
4848
LL | / pub fn iter(&self) -> std::slice::Iter<'_, u8> {
4949
LL | |
@@ -64,7 +64,7 @@ LL + }
6464
|
6565

6666
error: `iter_mut` method without an `IntoIterator` impl for `&mut S3<'a>`
67-
--> $DIR/iter_without_into_iter.rs:30:5
67+
--> $DIR/iter_without_into_iter.rs:32:5
6868
|
6969
LL | / pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
7070
LL | |
@@ -85,7 +85,7 @@ LL + }
8585
|
8686

8787
error: `iter` method without an `IntoIterator` impl for `&S8<T>`
88-
--> $DIR/iter_without_into_iter.rs:67:5
88+
--> $DIR/iter_without_into_iter.rs:69:5
8989
|
9090
LL | / pub fn iter(&self) -> std::slice::Iter<'static, T> {
9191
LL | | todo!()
@@ -105,7 +105,7 @@ LL + }
105105
|
106106

107107
error: `iter` method without an `IntoIterator` impl for `&S9<T>`
108-
--> $DIR/iter_without_into_iter.rs:75:5
108+
--> $DIR/iter_without_into_iter.rs:77:5
109109
|
110110
LL | / pub fn iter(&self) -> std::slice::Iter<'_, T> {
111111
LL | |
@@ -126,7 +126,7 @@ LL + }
126126
|
127127

128128
error: `iter_mut` method without an `IntoIterator` impl for `&mut S9<T>`
129-
--> $DIR/iter_without_into_iter.rs:79:5
129+
--> $DIR/iter_without_into_iter.rs:81:5
130130
|
131131
LL | / pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
132132
LL | |
@@ -146,5 +146,29 @@ LL + }
146146
LL + }
147147
|
148148

149-
error: aborting due to 7 previous errors
149+
error: `iter` method without an `IntoIterator` impl for `&Issue12037`
150+
--> $DIR/iter_without_into_iter.rs:130:13
151+
|
152+
LL | / fn iter(&self) -> std::slice::Iter<'_, u8> {
153+
LL | | todo!()
154+
LL | | }
155+
| |_____________^
156+
...
157+
LL | generate_impl!();
158+
| ---------------- in this macro invocation
159+
|
160+
= note: this error originates in the macro `generate_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
161+
help: consider implementing `IntoIterator` for `&Issue12037`
162+
|
163+
LL ~
164+
LL + impl IntoIterator for &Issue12037 {
165+
LL + type IntoIter = std::slice::Iter<'_, u8>;
166+
LL + type Item = &u8;
167+
LL + fn into_iter(self) -> Self::IntoIter {
168+
LL + self.iter()
169+
LL + }
170+
LL + }
171+
|
172+
173+
error: aborting due to 8 previous errors
150174

0 commit comments

Comments
 (0)