我正在写一个通用的Iterator
,它使用一个内部值来计算数字序列。在每个步骤中,将几个操作应用于内部值,以计算序列中的下一个值。我可以将这些操作的特征范围放在Iterator
实现本身上,并且一切都很好,但是如果将它们移到关联的类型,编译器将无法推断正确的特征实现。
这是一个人为设计的示例,它演示了该问题。此迭代器将一个加到内部值并将其加倍。从内部值1开始,将产生序列4、10、22、46 ...
这需要Add
上的Shl<usize>
和MyType::InnerType
特征范围,以及From
范围,才能将这些操作的结果转换回InnerType
。 / p>
use std::ops::*;
fn main() {
let iter: MyIterator<f32> = MyIterator::new();
for (i, val) in iter.take(10).enumerate() {
println!("{} => {}", i, val);
}
}
struct MyIterator<T: MyType> {
previous: T::InnerType,
}
impl<T: MyType> MyIterator<T> {
pub fn new() -> Self {
MyIterator {
previous: T::InnerType::ONE,
}
}
}
// `Add`, `Shl`, and `From` trait bounds only work when put here...
impl<T: MyType> Iterator for MyIterator<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
// Add one
let plus_one = T::InnerType::from(self.previous + T::InnerType::ONE);
// Multiply by two
let times_two = T::InnerType::from(plus_one << 1);
// Save state
self.previous = times_two;
// Return value
Some(T::from_inner(times_two))
}
}
trait MyType {
// Want to put `Add`, `Shl`, and `From` trait bounds on InnerType here...
type InnerType: One
+ Copy
+ Add
+ Shl<usize>
+ From<<Self::InnerType as Add>::Output>
+ From<<Self::InnerType as Shl<usize>>::Output>;
fn from_inner(val: Self::InnerType) -> Self;
}
impl MyType for f32 {
type InnerType = u32;
fn from_inner(val: u32) -> f32 {
val as f32
}
}
trait One {
const ONE: Self;
}
impl One for u32 {
const ONE: u32 = 1;
}
编译器无法确定要调用哪个MyType::InnerType::from
方法:
error[E0308]: mismatched types
--> src/main.rs:28:43
|
28 | let plus_one = T::InnerType::from(self.previous + T::InnerType::ONE);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected std::ops::Shl::Output, found std::ops::Add::Output
|
= note: expected type `<<T as MyType>::InnerType as std::ops::Shl<usize>>::Output`
found type `<<T as MyType>::InnerType as std::ops::Add>::Output`
但是,如果我使用impl<T: MyType> Iterator<T>
子句将这些边界放在where
上,则所有内容都会按预期编译。
为什么将特征边界放在From
impl上,而不是直接将它们放在相关类型上,编译器为什么不能推断使用哪个Iterator
实现?
具有工作版本和非工作版本的游乐场:
MyType::InnerType
上)Iterator
的边界)