为什么在编译稳定代码时会收到有关缺少不稳定特征(std::iter::Step - 编译器不允许我实现)的错误?

gar*_*pen 0 iterator for-loop range rust

我想定义一个函数,它应该允许我返回一系列结构实例上的迭代器。

我已经为标准类型尝试了相同的功能,例如 usize (请参阅简化的代码示例)并且这有效(尽管有点尴尬)。我无法在我想到的场景中使用标准类型,因此这对解决方案没有帮助,但它帮助我理解这里存在某种问题。

#[derive(Debug)]
struct MyThing();

fn main() {
    let good  = 0usize..=10usize;
    // ALSO WORKS for thing in *good.start()..=*good.end() {
    for thing in 0usize..=10usize {
        dbg!(thing);
    }
    dbg!(good);

    let bad  = MyThing()..=MyThing();
    for thing in *bad.start()..=*bad.end() {
        dbg!(thing);
    }
    dbg!(bad);
}
Run Code Online (Sandbox Code Playgroud)
$ cargo --version
cargo 1.35.0 (6f3e9c367 2019-04-04)

$ cargo build
   Compiling huh v0.1.0 (huh)
error[E0277]: the trait bound `MyThing: std::iter::Step` is not satisfied
  --> src/main.rs:13:18
   |
13 |     for thing in *bad.start()..=*bad.end() {
   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::iter::Step` is not implemented for `MyThing`
   |
   = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::ops::RangeInclusive<MyThing>`
Run Code Online (Sandbox Code Playgroud)

我不希望稳定编译器告诉我我缺少不稳定的特征。我在这里可能有一些其他类型的问题,我不明白,但稳定编译器告诉我,我的问题是我没有实现不稳定的特征。我绝对无法像这样修复我的代码(不切换到不稳定状态)。

我想我想了解的是是否可以基于用户定义的类型定义一个范围,然后可以对其进行迭代。

谁能解释一下发生了什么并建议我解决问题的方法?

Pet*_*all 5

= note: required because of the requirements on the impl of `std::iter::Iterator` for `std::ops::RangeInclusive<MyThing>`
Run Code Online (Sandbox Code Playgroud)

Step特性尚未稳定。然而,正如这个错误注释所暗示的那样,它仍然在内部使用;Iterator类型的实现依赖Range*Step正在实现的。

这样做的结果是,在(或某些替代 API)稳定Iterator之前,您(尚)无法实现自定义类型的范围。Step


请注意,Rust 中的“不稳定”并不意味着它有错误或可能以任何方式损坏。这只是意味着 API 将来仍有可能发生变化并破坏向后兼容性。Rust 编译器可以利用此类 API 进行语法脱糖,因为它可以在 API 更改的同一版本中稍后更改脱糖。


为了解决这个问题,我建议迭代其他可以轻松转换为您的类型的东西。您的代码可能有点过于简化,无法为您的实际用例提供一些实际的东西,但大致如下:

impl From<usize> for Thing {
    fn from(index: usize) -> Thing {
        Thing()
    }
}

for i in 0..=10 {
    let thing = Thing::from(i);
    dbg!(thing);
}
Run Code Online (Sandbox Code Playgroud)

这不应导致任何性能开销。