我想得到一个随机数发生器.由于OsRng::new()可能会失败,如果必须的话,我想回到thread_rng():

extern crate rand; // 0.5.5

use rand::{thread_rng, OsRng, 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::OsRng`, found struct `rand::ThreadRng`
  |
  = note: expected type `rand::OsRng`
             found type `rand::ThreadRng`

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

我不相信这是How do I return an instance of a trait from a method?的复制品,因为另一个问题是关于how,一个人可以从函数返回一个特征,这个问题是关于why,编译器不允许我返回一个特征,但希望我返回一个OsRng,它不是函数的返回类型.

推荐答案

impl Trait并不等同于返回接口或基类对象.这是一种表达"我不想写我要返回的特定类型的名称"的方式.您仍然返回一个单一的特定类型的值;你不是说which型.

每个分支都返回不同的类型,因此出现了问题.实施同样的特征是不够的.

在这种特殊情况下,你可能想要一个trait 对象,比如Box<dyn RngCore>.

extern crate rand; // 0.6.5

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

fn rng() -> Box<dyn RngCore> {
    match OsRng::new() {
        Ok(rng) => Box::new(rng),
        Err(_) => Box::new(thread_rng()),
    }
}

Note:如果你使用的是稍旧的Rust版本,你可能需要删除dyn关键字.在之前(2015)版的Rust中,它是可选的.

Rust相关问答推荐

空字符串转换为Box字符串时是否分配?<>

为什么BitVec缺少Serialize trait?

在自定义序列化程序中复制serde(With)的行为

取得本地对象字段的所有权

从未排序的链表中删除重复项的铁 rust 代码在ELSE分支的低级上做了什么?

Rust面向对象设计模式

信号量释放后 Rust 输出挂起线程

通过写入 std::io::stdout() 输出不可见

Rust 如何将链表推到前面?

Rust中如何实现一个与Sized相反的负特性(Unsized)

Rust 打包在 .deb 中

有什么方法可以通过使用生命周期来减轻嵌套生成器中的当生成器产生时borrow 可能仍在使用错误?

为什么 `tokio::join!` 宏不需要 Rust 中的 `await` 关键字?

如何在 Rust 中将 Vec> 转换为 Vec>?

如何递归传递闭包作为参数?

Rust 生命周期:这两种类型声明为不同的生命周期

在每个循环迭代中删除borrow

如果我不想运行析构函数,如何移出具有析构函数的 struct ?

火箭整流罩、tokio-scheduler 和 cron 的生命周期问题

tokio async rust 的 yield 是什么意思?