mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-30 08:30:45 +00:00
226 lines
5.5 KiB
Rust
226 lines
5.5 KiB
Rust
//@no-rustfix
|
|
//@aux-build:proc_macros.rs
|
|
#![warn(clippy::into_iter_without_iter)]
|
|
extern crate proc_macros;
|
|
|
|
use std::iter::IntoIterator;
|
|
|
|
pub struct S1;
|
|
impl<'a> IntoIterator for &'a S1 {
|
|
//~^ ERROR: `IntoIterator` implemented for a reference type without an `iter` method
|
|
type IntoIter = std::slice::Iter<'a, u8>;
|
|
type Item = &'a u8;
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
todo!()
|
|
}
|
|
}
|
|
impl<'a> IntoIterator for &'a mut S1 {
|
|
//~^ ERROR: `IntoIterator` implemented for a reference type without an `iter_mut` method
|
|
type IntoIter = std::slice::IterMut<'a, u8>;
|
|
type Item = &'a mut u8;
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
todo!()
|
|
}
|
|
}
|
|
|
|
pub struct S2<T>(T);
|
|
impl<'a, T> IntoIterator for &'a S2<T> {
|
|
//~^ ERROR: `IntoIterator` implemented for a reference type without an `iter` method
|
|
type IntoIter = std::slice::Iter<'a, T>;
|
|
type Item = &'a T;
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
todo!()
|
|
}
|
|
}
|
|
impl<'a, T> IntoIterator for &'a mut S2<T> {
|
|
//~^ ERROR: `IntoIterator` implemented for a reference type without an `iter_mut` method
|
|
type IntoIter = std::slice::IterMut<'a, T>;
|
|
type Item = &'a mut T;
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
todo!()
|
|
}
|
|
}
|
|
|
|
// Both iter and iter_mut methods exist, don't lint
|
|
pub struct S3<'a, T>(&'a T);
|
|
impl<'a, T> S3<'a, T> {
|
|
fn iter(&self) -> std::slice::Iter<'a, T> {
|
|
todo!()
|
|
}
|
|
fn iter_mut(&mut self) -> std::slice::IterMut<'a, T> {
|
|
todo!()
|
|
}
|
|
}
|
|
impl<'a, T> IntoIterator for &S3<'a, T> {
|
|
type IntoIter = std::slice::Iter<'a, T>;
|
|
type Item = &'a T;
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
todo!()
|
|
}
|
|
}
|
|
impl<'a, T> IntoIterator for &mut S3<'a, T> {
|
|
type IntoIter = std::slice::IterMut<'a, T>;
|
|
type Item = &'a mut T;
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
todo!()
|
|
}
|
|
}
|
|
|
|
// Only `iter` exists, no `iter_mut`
|
|
pub struct S4<'a, T>(&'a T);
|
|
|
|
impl<'a, T> S4<'a, T> {
|
|
fn iter(&self) -> std::slice::Iter<'a, T> {
|
|
todo!()
|
|
}
|
|
}
|
|
|
|
impl<'a, T> IntoIterator for &S4<'a, T> {
|
|
type IntoIter = std::slice::Iter<'a, T>;
|
|
type Item = &'a T;
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
todo!()
|
|
}
|
|
}
|
|
|
|
impl<'a, T> IntoIterator for &mut S4<'a, T> {
|
|
//~^ ERROR: `IntoIterator` implemented for a reference type without an `iter_mut` method
|
|
type IntoIter = std::slice::IterMut<'a, T>;
|
|
type Item = &'a mut T;
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
todo!()
|
|
}
|
|
}
|
|
|
|
// `iter` exists, but `IntoIterator` is implemented for an alias. inherent_impls doesn't "normalize"
|
|
// aliases so that `inherent_impls(Alias)` where `type Alias = S` returns nothing, so this can lead
|
|
// to fun FPs. Make sure it doesn't happen here (we're using type_of, which should skip the alias).
|
|
pub struct S5;
|
|
|
|
impl S5 {
|
|
fn iter(&self) -> std::slice::Iter<'static, u8> {
|
|
todo!()
|
|
}
|
|
}
|
|
|
|
pub type Alias = S5;
|
|
|
|
impl IntoIterator for &Alias {
|
|
type IntoIter = std::slice::Iter<'static, u8>;
|
|
type Item = &'static u8;
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
todo!()
|
|
}
|
|
}
|
|
|
|
// Fine to lint, the impls comes from a local macro.
|
|
pub struct Issue12037;
|
|
macro_rules! generate_impl {
|
|
() => {
|
|
impl<'a> IntoIterator for &'a Issue12037 {
|
|
type IntoIter = std::slice::Iter<'a, u8>;
|
|
type Item = &'a u8;
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
todo!()
|
|
}
|
|
}
|
|
};
|
|
}
|
|
generate_impl!();
|
|
|
|
// Impl comes from an external crate
|
|
proc_macros::external! {
|
|
pub struct ImplWithForeignSpan;
|
|
impl<'a> IntoIterator for &'a ImplWithForeignSpan {
|
|
type IntoIter = std::slice::Iter<'a, u8>;
|
|
type Item = &'a u8;
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
todo!()
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct Allowed;
|
|
#[allow(clippy::into_iter_without_iter)]
|
|
impl<'a> IntoIterator for &'a Allowed {
|
|
type IntoIter = std::slice::Iter<'a, u8>;
|
|
type Item = &'a u8;
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
todo!()
|
|
}
|
|
}
|
|
|
|
fn main() {}
|
|
|
|
pub mod issue11635 {
|
|
// A little more involved than the original repro in the issue, but this tests that it correctly
|
|
// works for more than one deref step
|
|
|
|
use std::ops::Deref;
|
|
|
|
pub struct Thing(Vec<u8>);
|
|
pub struct Thing2(Thing);
|
|
|
|
impl Deref for Thing {
|
|
type Target = [u8];
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
impl Deref for Thing2 {
|
|
type Target = Thing;
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
impl<'a> IntoIterator for &'a Thing2 {
|
|
type Item = &'a u8;
|
|
type IntoIter = <&'a [u8] as IntoIterator>::IntoIter;
|
|
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
self.0.iter()
|
|
}
|
|
}
|
|
}
|
|
|
|
pub mod issue12964 {
|
|
pub struct MyIter<'a, T: 'a> {
|
|
iter: std::slice::Iter<'a, T>,
|
|
}
|
|
|
|
impl<'a, T> Iterator for MyIter<'a, T> {
|
|
type Item = &'a T;
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
self.iter.next()
|
|
}
|
|
}
|
|
|
|
pub struct MyContainer<T> {
|
|
inner: Vec<T>,
|
|
}
|
|
|
|
impl<T> MyContainer<T> {}
|
|
|
|
impl<T> MyContainer<T> {
|
|
#[must_use]
|
|
pub fn iter(&self) -> MyIter<'_, T> {
|
|
<&Self as IntoIterator>::into_iter(self)
|
|
}
|
|
}
|
|
|
|
impl<'a, T> IntoIterator for &'a MyContainer<T> {
|
|
type Item = &'a T;
|
|
|
|
type IntoIter = MyIter<'a, T>;
|
|
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
Self::IntoIter {
|
|
iter: self.inner.as_slice().iter(),
|
|
}
|
|
}
|
|
}
|
|
}
|