You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

闭包中使用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 '1 must 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 00:13:32