为什么将特征范围放置在关联的类型上不起作用?

时间:2019-01-16 19:06:33

标签: rust

我正在写一个通用的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实现?

具有工作版本和非工作版本的游乐场:

  • Working({{1}的特征边界位于MyType::InnerType上)
  • Not Working(特征 直接放置在关联类型上的Iterator的边界)

0 个答案:

没有答案