【问题标题】:Returning a Result::Err() causes E0308 and its clogging my error log返回 Result::Err() 会导致 E0308 并阻塞我的错误日志
【发布时间】:2020-12-30 03:21:47
【问题描述】:

我正在尝试使用 Rust 为尚未实现的处理器架构编写汇编程序。我刚刚完成了词法分析器,并正在尝试构建它并修复我在此过程中犯的所有错别字和错误。

但是,一个不断阻塞构建日志的错误是错误 E0308:类型不匹配。本质上,每次我尝试在 rust 编译器不希望我返回的地方返回 Result::Err (因为源文件包含错误)时,我都会收到此错误。我不在乎 rust 编译器期望什么。我正在尝试在这里编写一个汇编程序。我能做些什么来阻止 E0308 的发生?

示例:这是我的程序中触发此错误的部分内容。

if bin_regex.is_match(&s[1..25]) {
    // Absolute Memory
    add_info = AddressInfo::new(ValueType::Binary, AddressMode::AbsoluteMemory);
    content = &s[0..25];
} else if bin_regex.is_match(&s[1..17]) {
    if &s[17..18] == "p" {
        // Absolute Port
        add_info = AddressInfo::new(ValueType::Binary, AddressMode::AbsolutePort);
        content = &s[0..18];
    } else {
        // Zero Bank
        add_info = AddressInfo:new(ValueType::Binary, AddressMode::ZeroBank);
        content = &s[0..17];
} else if bin_regex.is_match(&s[1..9]) {
    // Zero Page
    add_info = AddressInfo::new(ValueType::Hexadecimal, AddressMode::ZeroPage);
    content = &s[0..9];
} else {
    // Error
    Err(format!("Invalid Binary address or Binary address out of range"))
}

这是错误的样子:

...

 error[E0308]: mismatched types
    --> src/lex.rs:407:17
     |
 401 |               } else if bin_regex.is_match(&s[1..9]) {
     |  ____________________-
 402 | |                 // Zero Page
 403 | |                 add_info = AddressInfo::new(ValueType::Binary, AddressMode::ZeroPage);
 404 | |                 content = &s[0..9];
 ... | |
 407 | |                 Err(format!("Invalid Binary address or Binary address out of range"))
     | |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found enum `std::result::Result`
 408 | |             }
     | |_____________- expected this to be `()`
     |
     = note: expected unit type `()`
                     found enum `std::result::Result<_, std::string::String>`
...

【问题讨论】:

  • 你知道Err 是一个类型构造函数,而不是一个函数吗?当你写Err(...) 时,你只是在创建一个新的Err 对象,你可以用它做些什么。也许你的意思是return Err(...);
  • 代码位所在的函数返回 Result,当帮助函数在词法分析器中返回错误时,它会传播到 lex() 函数,该函数将所有这些Vec() 中的错误字符串,如果至少有一个错误并且它不处于详细模式,则将该错误字符串向量返回给主函数,该函数将它们打印出来并以错误代码退出。

标签: rust


【解决方案1】:

错误在 Rust 中并不特殊。如果您希望从函数返回错误,则该函数必须具有 Result 返回类型。假设我们有这个函数:

fn divide(a: i64, b: i64) -> i64 {
    a / b
}

但是如果b == 0有问题,所以我们想报错:

fn divide(a: i64, b: i64) -> i64 {
    if b == 0 {
        Err("divide by zero")
    } else {
        a / b
    }
}

但这会遇到你的错误:

error[E0308]: mismatched types
 --> src/main.rs:3:13
  |
1 |     fn divide(a: i64, b: i64) -> i64 {
  |                                  --- expected `i64` because of return type
2 |         if b == 0 {
3 |             Err("divide by zero")
  |             ^^^^^^^^^^^^^^^^^^^^^ expected `i64`, found enum `std::result::Result`
  |
  = note: expected type `i64`
             found enum `std::result::Result<_, &str>`

我们必须做的是给函数适当的类型,这允许我们返回可能有错误的结果。我们还必须在Ok(...) 中包装任何不是错误的结果:

fn divide(a: i64, b: i64) -> Result<i64, &'static str> {
    if b == 0 {
        Err("divide by zero")
    } else {
        Ok(a / b)
    }
}

请注意,使用原始字符串作为错误类型不是一个好习惯 - 这只是一个简单的示例。

【讨论】:

  • 它确实有适当的返回类型。我开始认为我应该只是链接源存储库,让你们都疯狂......
【解决方案2】:

如果您只是希望您的应用程序在您的错误情况发生时退出,那么您应该使用panic! 而不是Err(...)(因为 Err 是一个构造函数,它只创建一个 Result 对象而对它不做任何事情)


pub fn doit() {
  if ... {
    // ...
  } else {
    // Error
    panic!("Invalid Binary address or Binary address out of range"))
  }
}

通常使用panic! 在某种程度上是不受欢迎的。但对于初始工作,通常是可以的。稍后您可能想要更改函数以返回 Result,以便您可以更好地处理错误。在这种情况下,你会返回一个 Err。

pub fn doit() -> Result<(), String> {
  if ... {
    // ...
  } else {
    // Error
    return Err(format!("Invalid Binary address or Binary address out of range"));
  }
  Ok(())
}

下一步是使用特定的错误类型对错误进行编码

#[derive(Debug, Clone)]
pub enum Error {
   InvalidAddressError,
   ...
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Invalid Binary address or Binary address out of range")
    }
}

pub fn doit() -> Result<(), Error> {
  if ... {
    // ...
  } else {
    // Error
    return Err(Error::InvalidAddressError);
  }
  Ok(())
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多