闭包中使用nom_supreme的tag解析器遇到生命周期问题
使用nom_supreme的tag时闭包生命周期编译错误问题
背景
我正在用nom解析自定义语言,同时借助nom_supreme优化错误处理等开发体验,整体流程顺畅,但遇到一个闭包生命周期相关的编译问题。
nom的tag函数会返回一个消耗输入字符串的解析器,示例代码如下:
fn parser(s: &str) -> IResult<&str, &str> { tag("Hello")(s) } assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
nom_supreme提供了同名的tag实现,错误处理更完善(核心是将tag内容嵌入错误信息)。二者函数签名对比如下:
nom_supreme的tag签名
pub fn tag<T, I, E>(tag: T) -> impl Clone + Fn(I) -> IResult<I, I, E> where T: InputLength + Clone, I: InputTake + Compare<T>, E: TagError<I, T>
nom的tag签名
pub fn tag<T, I, E>(tag: T) -> impl Fn(I) -> IResult<I, I, E> where T: InputLength + Clone, I: Input + Compare<T>, E: ParseError<I>
从签名看二者逻辑一致,但在闭包中使用时表现不同。
问题重现
使用nom的tag时,以下代码可以正常编译:
pub fn create_test_parser(captured_tag: &str) -> impl FnMut(&str) -> AsmResult<String> + '_ { move |i: &str| { let captured_tag_parser = nom::bytes::complete::tag(captured_tag); let (i, parsed_tag) = captured_tag_parser(i)?; Ok((i, String::from(parsed_tag))) } }
但替换为nom_supreme的tag后,编译失败,报错信息如下:
lifetime may not live long enough
returning this value requires that'1must outlive'static
对应的代码:
pub fn create_test_parser(captured_tag: &str) -> impl FnMut(&str) -> AsmResult<String> + '_ { move |i: &str| { let captured_tag_parser = nom_supreme::tag::complete::tag(captured_tag); let (i, parsed_tag) = captured_tag_parser(i)?; Ok((i, String::from(parsed_tag))) } }
已尝试的解决方法
- 克隆
captured_tag:触发“在双重引用上使用'clone'”错误 - 调用
captured_tag.to_owned():触发“返回引用当前函数拥有的数据的值”错误 - 在外部作用域克隆
captured_tag:仍存在生命周期错误 - 在外部作用域执行
captured_tag.to_owned():触发“捕获的变量无法逃逸FnMut”错误 - 使用Arc:可以正常编译,但疑惑为什么标准nom的tag不需要这种高级内存管理手段
我认为自己遗漏了将字符串所有权正确转移到闭包的方法,传入create_test_parser的是字符串字面量,理论上不应与调用者的生命周期绑定。
内容的提问来源于stack exchange,提问作者Sean Dawson
相关产品推荐
相关产品推荐

