在Rust的nom库中使用tuple为何有时需要类型注解?
问题原因解析
首先得明确nom里解析器的核心类型:每个解析器都是Fn(&[u8]) -> IResult<&[u8], Output, Error>,其中Error(也就是报错里的E)是实现了ParseError trait的类型,很多解析器对E是泛型兼容的。
两种场景的差异
用
identifier的情况
不管你是用nom自带的标识符解析器(比如alpha1+alphanumeric0组合的)还是自己实现的,这类解析器通常会固定错误类型(比如默认用nom::error::Error<&[u8]>),或者在定义时就绑定了具体的E。当你把它放进tuple里时,编译器会以这个具体的E为基准,自动推导tuple里其他解析器的E类型(比如tag、multispace1这些泛型解析器会自动适配这个具体的E),所以不需要显式注解。换成
multispace0的情况multispace0是nom提供的“零或多空白”解析器,它的错误类型E是完全泛型的——只要E实现了ParseError<&[u8]>就行,没有绑定具体类型。这时候tuple里的所有解析器(tag、multispace1、multispace0)的E都是泛型的,编译器没有任何“锚点”来确定到底要用哪一种Error类型,所以会报错要求你显式指定E的类型。
解决办法
你可以给tuple加上类型注解,或者给整个解析器指定错误类型,比如:
// 显式指定错误类型为nom的默认Error let parser: fn(&[u8]) -> IResult<&[u8], (&[u8], &[u8], &[u8]), nom::error::Error<&[u8]>> = tuple((tag("fn"), multispace1, multispace0)); // 或者用 turbofish 语法指定tuple的类型参数 let parser = tuple::<_, _, nom::error::Error<&[u8]>>((tag("fn"), multispace1, multispace0));
内容的提问来源于stack exchange,提问作者Amir reza Riahi
相关产品推荐
相关产品推荐

