rust-bakery / nom

Rust parser combinator framework
MIT License
9.18k stars 792 forks source link

Nom's error is referencing data owned by the calling function #1706

Open absoludity opened 8 months ago

absoludity commented 8 months ago

Prerequisites

Here are a few things you should provide to help me understand the issue:

[package]
name = "repro_nom_error_issue"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
nom = "7.1.3"

Test case

I've created an example with the work around at:

https://github.com/absoludity/repro_nom_error_issue/blob/df4e339accb4a4ddb40c9c781f1febca1b4dd73f/src/main.rs#L1-L26 :

use nom::bytes::complete::tag;
use nom::multi::many0;
use nom::IResult;
use std::error::Error;

fn parser(s: &str) -> IResult<&str, Vec<&str>> {
    many0(tag("abc"))(s)
}

fn main() -> Result<(), Box<dyn Error>> {
    // In actual code, the input comes as a string through:
    // let input = std::fs::read_to_string(INPUT_FILE_PATH)?
    let input = "abcabc123".to_string();

    // This following fails, without mapping the error:

    // let (remaining, parsed) = parser(&input)?;

    // Whereas it works fine if I ensure that the content of the error is owned
    // (which is internally cloning the &str content, I assume):
    let (remaining, parsed) = parser(&input).map_err(|e| e.map_input(|s| s.to_owned()))?;

    assert_eq!(remaining, "123");
    assert_eq!(parsed, vec!["abc", "abc"]);
    Ok(())
}

As you can see, it will compile fine if I map the error input to ensure it is owned, but without that map, the compiler won't compile as it appears the error content is referencing the original input data, which is owned by the calling function:

$ cargo run       
   Compiling repro_nom_error_issue v0.1.0 (/xxx/repro_nom_error_issue)
error[E0515]: cannot return value referencing local variable `input`
  --> src/main.rs:17:31
   |
17 |     let (remaining, parsed) = parser(&input)?;
   |                               ^^^^^^^------^^
   |                               |      |
   |                               |      `input` is borrowed here
   |                               returns a value referencing data owned by the current function

For more information about this error, try `rustc --explain E0515`.
error: could not compile `repro_nom_error_issue` (bin "repro_nom_error_issue") due to previous error

If this is an actual error that could be improved in nom (as opposed to me missing something obvious here), and you think it might be a good first issue, I'd be happy to jump in and fix it.