Bit*_*nce 4 rust borrow-checker nom
我有这个使用 nom 4.2.2 的 Rust 程序。(我冒昧地扩展了 nom 解析器功能。)
extern crate failure;
extern crate nom;
use failure::Error;
use std::fs::File;
use std::io::Read;
fn nom_parser(i: &[u8]) -> ::nom::IResult<&[u8], String, u32> {
{ ::nom::lib::std::result::Result::Ok((i, ("foo".to_owned()))) }
}
fn my_parser(buf: &[u8]) -> Result<(&[u8], String), Error> {
Ok((buf, "foo".to_owned()))
}
fn main() -> Result<(), Error> {
let handler = |mut entries: String| { entries.clear() };
loop {
let mut buf = Vec::new();
File::open("/etc/hosts")?.read_to_end(&mut buf)?;
let res = nom_parser(&buf)?.1;
// let res = my_parser(&buf)?.1;
handler(res);
}
}
Run Code Online (Sandbox Code Playgroud)
编译这个程序会rustc 1.33.0 (2aa4c46cf 2019-02-28)产生以下问题:
error[E0597]: `buf` does not live long enough
--> nom-parsing/src/main.rs:21:26
|
21 | let res = nom_parser(&buf)?.1;
| -----------^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `buf` is borrowed for `'static`
...
24 | }
| - `buf` dropped here while still borrowed
Run Code Online (Sandbox Code Playgroud)
切换到解析器的注释版本编译就好了。如何my_parser与nom_parser不同?谁在借buf?我应该如何更改程序以安抚借阅检查员?
let res = nom_parser(&buf)?.1;
^ here
Run Code Online (Sandbox Code Playgroud)
您正在使用?运算符将错误传播出去main。该IResult<&[u8], String, u32>= Result<(&[u8], String), nom::Err<&[u8], u32>>。因此,如果出现错误,&buf将作为它的一部分返回,因此即使在main函数退出后它也必须保持活动状态,但它不会因为buf内部变量是局部变量main。
在您的情况下,nom_parser永远不会返回错误,但验证只关心类型和函数签名。
要修复它,您应该在传播之前以某种方式处理错误。例如:
let res = nom_parser(&buf).map_err(|_| failure::format_err!("Parsing failed!"))?.1;
Run Code Online (Sandbox Code Playgroud)
请注意,Err在IResult并不总是硬错误。它可能是nom::Err::Incomplete,意味着如果提供更多数据,解析可能会成功,或者nom::Err::Error意味着解析器不匹配输入(因此可能另一个解析器alt!可能会成功),或者nom::Err::Failure意味着解析过程中确实出了问题。根据情况,您可以将它们都视为失败,或者以不同的方式处理它们。
| 归档时间: |
|
| 查看次数: |
332 次 |
| 最近记录: |