首页 > 解决方案 > Rust新手问题,如何处理这个函数中的错误?

问题描述

我正在用 nom crate 学习 Rust,下面是我的程序。

fn get_indent_level(input: &str) -> usize {
    let (_, result) = many0_count(alt((tag("L_ "), tag("|  "), tag("   "))))(input).unwrap_or_default();
    result
}

运行时出现此错误:

error[E0283]: type annotations needed
   --> src\lib.rs:149:23
    |
149 |     let (_, result) = many0_count(alt((tag("L_ "), tag("|  "), tag("   "))))(input).unwrap_or_default();
    |                       ^^^^^^^^^^^ cannot infer type for type parameter `E` declared on the function `many0_count`
    | 
   ::: C:\Users\user1\.cargo\registry\src\github.com-xxxxxxxxxxxxxxx\nom-6.2.1\src\multi\mod.rs:486:6
    |
486 |   E: ParseError<I>,
    |      ------------- required by this bound in `many0_count`
    |
    = note: cannot satisfy `_: ParseError<&str>`
help: consider specifying the type arguments in the function call
    |
149 |     let (_, result) = many0_count::<I, O, E, F>(alt((tag("L_ "), tag("|  "), tag("   "))))(input).unwrap_or_default();
    |                                  ^^^^^^^^^^^^^^

当我添加这样的类型时:

fn get_indent_level(input: &str) -> usize {
    let (_, result) = many0_count::<&str, usize, nom::error::ErrorKind, &str>(alt((tag("L_ "), tag("|  "), tag("   "))))(input).unwrap_or_default();
    result
}

我收到了这个新错误:

error[E0277]: the trait bound `nom::error::ErrorKind: ParseError<&str>` is not satisfied
   --> src\lib.rs:149:23
    |
149 |     let (_, result) = many0_count::<&str, usize, nom::error::ErrorKind, &str>(alt((tag("L_ "), tag("|  "), tag("   "))))(input).unwrap_or...
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ParseError<&str>` is not implemented for `nom::error::ErrorKind`
    | 
   ::: C:\Users\user1\.cargo\registry\src\github.com-xxxxxxxxxx\nom-6.2.1\src\multi\mod.rs:486:6
    |
486 |   E: ParseError<I>,
    |      ------------- required by this bound in `many0_count`

添加类型和解决问题的正确方法是什么?

标签: rustnom

解决方案


您只需要指定错误类型,因为 nom 可以返回不同的错误类型并且编译器无法推断它,因为错误不会在任何地方使用。您可以使用_语法让编译器推断其余已知类型。

最简单的方法是在类型上指定IResult类型,因为它需要的类型少于many0_count()

fn get_indent_level(input: &str) -> usize {
    let result: IResult<_, _, nom::error::Error<_>> =
        many0_count(alt((
            tag("L_ "), 
            tag("|  "),
            tag("   ")
        )))(input);
    result.map(|(_, x)| x).unwrap_or_default()
}

这样,您只需要提供 3 种类型,其中 2 种是已知的(输入 - &str; 和结果 - usize),因此您可以让编译器使用_语法推断它们并仅手动编写错误类型。


推荐阅读