我遇到了生命周期问题,我不确定如何解决,因为我所做的改变对于生命周期来说似乎是微不足道的。
鉴于:
use anyhow::Context;
use nom::{IResult, bytes::complete::tag};
Run Code Online (Sandbox Code Playgroud)
以下代码编译:
let input = std::str::from_utf8(&output.stdout).unwrap();
let mut lines = input.lines();
let branch_line = lines.next().context("no output from `git status`")?;
let branch: IResult<&str, &str> = tag("On branch ")(branch_line);
let (branch, _) = branch.expect("failed to get name of current branch");
Run Code Online (Sandbox Code Playgroud)
expect将最后一行中的更改为 后context,代码不再编译:
let input = std::str::from_utf8(&output.stdout).unwrap();
let mut lines = input.lines();
let branch_line = lines.next().context("no output from `git status`")?;
let branch: IResult<&str, &str> = tag("On branch ")(branch_line);
let (branch, _) = branch.context("failed to get name of current branch")?;
Run Code Online (Sandbox Code Playgroud)
error[E0597]: `output.stdout` does not live long enough
--> src/status.rs:303:41
|
303 | let input = std::str::from_utf8(&output.stdout).unwrap();
| ^^^^^^^^^^^^^^ borrowed value does not live long enough
...
307 | let branch: IResult<&str, &str> = tag("On branch ")(branch_line);
| ------------------- type annotation requires that `output.stdout` is borrowed for `'static`
...
436 | }
| - `output.stdout` dropped here while still borrowed
Run Code Online (Sandbox Code Playgroud)
查看 的文档anyhow,在我看来,它不应该在&output.stdout.
fn context<C>(self, context: C) -> Result<T, Error>
where
C: Display + Send + Sync + 'static,
Run Code Online (Sandbox Code Playgroud)
挠我的头。对一生来说仍然是新鲜事。
问题是 的类型branch,即IResult<&str, &str>。
如果您查看实现,您可以看到这是 的别名IResult<&str, &str, nom::error::Error<&str>>,它又是 的别名Result<(&str, &str), nom::internal::err<nom::error::Error<&str>>>。
这看起来很复杂,但我想说的要点是它branch是一种Result类型,并且Err它的情况具有类型nom::internal::err<nom::error::Error<&str>>。换句话说,错误带有&str.
这是故意的,因为所有权对于 nom 来说是一个大问题。这与当前借用检查器的这些已知问题密切相关。Nom 通过类型返回所有权来解决这个问题Err。
遗憾的是,这意味着它与anyhow. 的错误类型nom旨在由 消耗nom,或者至少在引发到用户代码之前手动转换为其他内容。
为了解释您收到的确切错误:
output.stdout是一个局部变量input以及其背后的其他所有内容都引用了中的数据output.stdoutErr变体branch仍在引用output.stdout.context(),或者更准确地说,它的后面,尝试从函数中?返回变体,但失败了,因为它仍然引用,并且该引用将比它引用的数据更长寿。Erroutput.stdout这对于 来说不是问题next().context(),因为None的值next()不包含对 的引用output.stdout。
&str解决此问题的一种方法是通过将类型转换Err为拥有的来破坏引用String:
use anyhow::{Context, Result};
use nom::{bytes::complete::tag, IResult};
fn main() -> Result<()> {
let input = "aaaaaa".to_string();
let mut lines = input.lines();
let branch_line = lines.next().context("no output from `git status`")?;
let branch: IResult<&str, &str> = tag("On branch ")(branch_line);
let (branch, _) = branch
.map_err(|e| e.to_owned())
.context("failed to get name of current branch")?;
Ok(())
}
Run Code Online (Sandbox Code Playgroud)