猿问

为什么不能使用impl trait返回多个/条件类型?

我正在尝试获得一个随机数生成器。由于OsRng::new()可能会失败,因此我不得不退回给thread_rng()我:


extern crate rand; // 0.6.5


use rand::{rngs::OsRng, thread_rng, RngCore};


fn rng() -> impl RngCore {

    match OsRng::new() {

        Ok(rng) => rng,

        Err(e) => thread_rng(),

    }

}

但是,我收到此错误消息,我无法理解:


error[E0308]: match arms have incompatible types

 --> src/lib.rs:6:5

  |

6 | /     match OsRng::new() {

7 | |         Ok(rng) => rng,

8 | |         Err(e) => thread_rng(),

  | |                   ------------ match arm with an incompatible type

9 | |     }

  | |_____^ expected struct `rand::rngs::OsRng`, found struct `rand::prelude::ThreadRng`

  |

  = note: expected type `rand::rngs::OsRng`

             found type `rand::prelude::ThreadRng`

为什么编译器期望rand::OsRng在这里而不是实现RngCore?如果删除match并直接返回thread_rng(),则不会得到以上错误消息。


我不认为这与如何从方法中返回特征的实例重复吗?,因为另一个问题是关于如何从函数返回特征的问题,而这个问题是关于为什么编译器不允许我返回特征,但希望我返回OsRng不是函数返回类型的。


哔哔one
浏览 602回答 2
2回答

holdtom

impl Trait不等同于返回接口或基类对象。这是说“我不想写我要返回的特定类型的名称”的一种方式。您仍在返回单个特定类型的值。您只是没有说哪种类型。这些分支中的每一个都返回不同的类型,因此出现了问题。仅仅实现相同的特征是不够的。在这种特定情况下,您可能需要的是trait对象Box<dyn RngCore>。extern crate rand; // 0.6.5use rand::{rngs::OsRng, thread_rng, RngCore};fn rng() -> Box<dyn RngCore> {&nbsp; &nbsp; match OsRng::new() {&nbsp; &nbsp; &nbsp; &nbsp; Ok(rng) => Box::new(rng),&nbsp; &nbsp; &nbsp; &nbsp; Err(_) => Box::new(thread_rng()),&nbsp; &nbsp; }}注意:如果您使用的是Rust的旧版本,则可能需要删除dyn关键字。在当前(2015)版本的Rust中,它是可选的。

牧羊人nacy

DK。已经解释了为什么,但是我想提供一个替代的解决方法。正如提到有条件迭代在几个可能的迭代器一个,您可以创建如果同时它的组件类型做一个实现特征的枚举。例如:extern crate rand; // 0.6.5use rand::{rngs::OsRng, thread_rng, RngCore};fn rng() -> impl RngCore {&nbsp; &nbsp; match OsRng::new() {&nbsp; &nbsp; &nbsp; &nbsp; Ok(rng) => EitherRng::Left(rng),&nbsp; &nbsp; &nbsp; &nbsp; Err(_) => EitherRng::Right(thread_rng()),&nbsp; &nbsp; }}enum EitherRng<L, R> {&nbsp; &nbsp; Left(L),&nbsp; &nbsp; Right(R),}impl<L, R> RngCore for EitherRng<L, R>where&nbsp; &nbsp; L: RngCore,&nbsp; &nbsp; R: RngCore,{&nbsp; &nbsp; fn next_u32(&mut self) -> u32 {&nbsp; &nbsp; &nbsp; &nbsp; match self {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EitherRng::Left(l) => l.next_u32(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EitherRng::Right(r) => r.next_u32(),&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; fn next_u64(&mut self) -> u64 {&nbsp; &nbsp; &nbsp; &nbsp; match self {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EitherRng::Left(l) => l.next_u64(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EitherRng::Right(r) => r.next_u64(),&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; fn fill_bytes(&mut self, b: &mut [u8]) {&nbsp; &nbsp; &nbsp; &nbsp; match self {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EitherRng::Left(l) => l.fill_bytes(b),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EitherRng::Right(r) => r.fill_bytes(b),&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; fn try_fill_bytes(&mut self, b: &mut [u8]) -> Result<(), rand::Error> {&nbsp; &nbsp; &nbsp; &nbsp; match self {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EitherRng::Left(l) => l.try_fill_bytes(b),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EitherRng::Right(r) => r.try_fill_bytes(b),&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}在任一箱提供了很多这些类型的基本特征实现的。
随时随地看视频慕课网APP
我要回答