関数の返し型を具体的に書くかimpl Traitと書くかの違いはもちろん明瞭にある
簡単な例で説明する

// まず実験用のおもちゃ(5ずつ増えるイテレータStepFive)を用意
pub struct StepFive { n: i64 }
impl StepFive {
 fn new(init: i64) -> Self { StepFive { n: init } }
 pub fn cur_value(&self) -> i64 { self.n } // 注意: イテレータには不要な追加機能
}
impl Iterator for StepFive {
 type Item = i64;
 fn next(&mut self) -> Option<Self::Item> { self.n += 5; Some(self.n) }
}

// このおもちゃイテレータを返す関数を二つ用意する
// 返し型を具体的に StepFive と書くケース
pub fn step_five_1(init: i64) -> StepFive { StepFive::new(init) }
// 返し型を impl Trait の形で書くケース
pub fn step_five_2(init: i64) -> impl Iterator<Item = i64> { StepFive::new(init) }

fn main() {
 // イテレータとしてはどちらも当然機能する
 assert_eq!(vec![5, 10, 15], step_five_1(0).take(3).collect::<Vec<_>>());
 assert_eq!(vec![5, 10, 15], step_five_2(0).take(3).collect::<Vec<_>>());

 // しかしイテレータにない機能を使うと違いが明瞭に出る
 assert_eq!(123, step_five_1(123).cur_value()); // コンパイル通る
 assert_eq!(123, step_five_2(123).cur_value()); // コンパイルエラー method not found in `impl Iterator<Item = i64>`
}