首页 > 解决方案 > 为什么?操作员报告错误“特征绑定NoneError:不满足错误”?

问题描述

第9 行的?运算符工作正常,但如果我在第 19 行对相同类型使用相同的逻辑,它就会崩溃。

use std::error::Error;
use walkdir::WalkDir;

fn main() -> Result<(), Box<dyn Error>> {
    let valid_entries = WalkDir::new("/tmp")
        .into_iter()
        .flat_map(|e| e)
        .flat_map(|e| {
            let name = e.file_name().to_str()?; // <-- this works
            if name.contains(".txt") {
                Some(e)
            } else {
                None
            }
        });

    for entry in valid_entries {
        println!("This file matches: {:?}", entry);
        let name_to_str = entry.file_name().to_str()?; // <-- this blows up
        // ...
    }
    Ok(())
}

这些错误对我来说有点神秘:

error[E0277]: the trait bound `std::option::NoneError: std::error::Error` is not satisfied
  --> src/main.rs:19:53
   |
26 |         let name_to_str = entry.file_name().to_str()?;
   |                                                     ^ the trait `std::error::Error` is not implemented for `std::option::NoneError`
   |
   = note: required because of the requirements on the impl of `std::convert::From<std::option::NoneError>` for `std::boxed::Box<dyn std::error::Error>`
   = note: required by `std::convert::From::from`

为什么?操作员在迭代时会爆炸valid_entries

标签: error-handlingrust

解决方案


?用于检查并返回任何实现该Try特征的类型(仍然不稳定)。其中唯一的实现stdOption<T>and Result<T, E>(加上一些Future与本讨论无关的相关 impls)。这意味着您可以?在任何返回Result<T, E>或的函数中使用运算符Option<T>

但是你不能混合搭配那些。也就是说,如果您的函数返回 a ,则您Result<T, E>不能?在 type 的值中使用Option<T>。或相反亦然。

你第一次?工作的原因是因为你在一个flat_map()返回Option<String>并且一切顺利的内部。但是,第二个是在返回 a 的函数中,Result<(), Box<dyn Error>>因此您不能与 a?一起使用Option<String>

解决方案只是以另一种方式处理None您的问题:Option<String>

  1. match/if let Some(x)来分别处理错误。
  2. 转换为 aResult<String, Error>并使用?,例如 with .ok_or(std::io::ErrorKind::InvalidData)?;
  3. 类似于 2,但利用impl From<&str> for Box<dyn Error>and do .ok_or("invalid file name")
  4. 给出一个默认值,有Option::unwrap_or()或类似。
  5. unwrap()和恐慌如果None

好的,但是这个错误是什么意思?这个想法是,实际上你可以使用?返回Option<T>a 的 a Result<T, E>,只要你的Eimplements From<std::option::NoneError>。不幸的是,NoneError它仍然不稳定,所以你不能From<NoneError>使用稳定的编译器在你的代码中实现。尽管如此,E您的代码中的 是Box<dyn Error>,只要NoneError实现,编译器就会很乐意进行装箱Error,但是......

error[E0277]: the trait bound `std::option::NoneError: std::error::Error` is not satisfied

推荐阅读