아래 코드의 핵심은 Iterator 트레이트의 연관 타입(associated type) 과 트레이트 구현에 의한 타입 유추입니다. Item이 직접적으로 코드 안에서 보이지 않지만, 트레이트 시스템이 자동으로 Iterator trait의 type Item과 연결해 주고 있습니다.
1. 예제 코드
struct GivesOne;
impl Iterator for GivesOne {
type Item = i32;
fn next(&mut self) -> Option<i32> {
Some(1)
}
}
fn main() {
let five_ones = GivesOne.into_iter().take(5).collect::<Vec<i32>>();
println!("{five_ones:?}");
}
2. 구조체 정의
struct GivesOne;
- GivesOne은 단순한 빈 구조체입니다.
3.Iterator 트레이트 구현
impl Iterator for GivesOne {
type Item = i32;
fn next(&mut self) -> Option<i32> {
Some(1)
}
}
여기서 중요한 부분이 바로 type Item = i32; 입니다.
Iterator 트레이트는 아래와 같이 정의되어 있습니다 (표준 라이브러리 축약본).
pub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
}
즉,
- Item은 연관 타입으로, 이 이터레이터가 어떤 타입의 요소를 내보내는지를 지정합니다.
- Self::Item이 Option<Self::Item> 안에서 쓰이죠.
그런데 GivesOne에서는 type Item = i32;로 정했으니,
→ Self::Item이 i32가 됩니다.
→ 따라서 fn next의 실제 타입은 fn next(&mut self) -> Option<i32>가 되는 겁니다.
next()는다음 요소를 하나 반환하거나(None을 반환하면 종료) 하는 메서드입니다.
이터레이터는 내부 상태를 가지고 “이번에 무엇을 내보낼지”를 결정하죠.
GivesOne 구조체에는 아무 필드도 없습니다. 즉, 몇 번째 요소를 내보냈는지 추적하는 정보가 없습니다. 따라서, 이터레이터는 “항상 똑같은 값 1만 계속 내보내는” 무한 반복 이터레이터가 됩니다.
4. GivesOne.into_iter()의 동작
let five_ones = GivesOne.into_iter().take(5).collect::<Vec<i32>>();
여기서 헷갈릴 수 있는 부분은 into_iter()인데,
GivesOne이 스스로 Iterator를 구현하고 있기 때문에,
Rust는 GivesOne.into_iter()를 IntoIterator 트레이트를 통해 다음처럼 해석합니다.
impl<I: Iterator> IntoIterator for I {
type Item = I::Item;
type IntoIter = I;
fn into_iter(self) -> I {
self
}
}
즉,
- GivesOne이 이미 Iterator니까
→ IntoIterator도 자동으로 적용되고,
→ into_iter()는 그냥 자기 자신(GivesOne)을 반환합니다.
5. 체인 전체의 타입 흐름
- GivesOne.into_iter() → 타입: GivesOne
위에서 알아본 바와 같이 next() 메소드는 영원히 Some(1)만 반환하고, None을 반환하지 않으므로 무한루프가 됩니다. - .take(5) → 타입: Take<GivesOne>
따라서.take(5)로 “앞의 5번만 가져오라”고 제한을 두는 것입니다. - collect::<Vec<i32>>()
collect()는 Item 타입을 기반으로 Vec<i32>를 만듭니다.
6. 실제로 내부 타입이 어떻게 “보이지 않지만 작동하는가?”
Rust는 트레이트 바인딩을 통해 자동으로 타입을 유추합니다.
Item은 직접 변수로 존재하지 않고, 트레이트 정의 안에서 연관 타입으로만 쓰이죠.
즉,
GivesOne → Iterator → Item = i32
이 연결이 트레이트 시스템 레벨에서 자동으로 이어지므로,
어디에도 Item이라는 이름이 코드에 명시적으로 안 나와도,
Rust는 Iterator<Item = i32>인 것을 정확히 압니다.
7. 요약
| 코드 부분 | 역할 |
| type Item = i32; | 이터레이터가 내보내는 값의 타입을 지정 |
| fn next(&mut self) | 실제로 값을 하나씩 생성 |
| into_iter() | Iterator를 자기 자신으로 반환 |
| take(5) | 최대 5번 next()호출 |
| collect::<Vec<i32>>() | 결과를 Vec<i32>로 수집 |
결과적으로println!(“{five_ones:?}”)는 [1, 1, 1, 1, 1]을 출력하게 됩니다.

