• Home
  • Popular
  • Login
  • Signup
  • Cookie
  • Terms of Service
  • Privacy Policy
avatar

Posted by John Dev


30 Nov, 2024

Updated at 02 Dec, 2024

Problem in Lifetimes Issues with Allocator and Parser Struct Design

I am very new to Rust. After watching a few courses, I tried to write some of the code I needed, but it seems I've run into a problem with lifetimes, and I can't solve it.

I am using the OXC library to generate output from a JS file.
This is the code that ChatGPT provided me. However, it clearly includes some dynamic parts, and I feel the key part of it is incorrect, even though it works.

use oxc::allocator::Allocator;
use oxc::ast::ast::Program;
use oxc::parser::Parser;
use oxc::span::SourceType;
use std::fs;

pub fn source_to_ast(file_path: &str) -> Result<Program<'_>, String> {
    if !std::path::Path::new(file_path).exists() {
        return Err(format!("File does not exist: {}", file_path));
    }

    let js_code = Box::leak(
        fs::read_to_string(file_path)
            .map_err(|e| format!("Failed to read the JavaScript file: {}", e))?
            .into_boxed_str(),
    );

    let allocator = Box::leak(Box::new(Allocator::default()));
    let source_type = SourceType::from_path(file_path)
        .map_err(|e| format!("Failed to determine source type: {:?}", e))?;

    let parser = Parser::new(allocator, js_code, source_type);
    let parse_result = parser.parse();

    Ok(parse_result.program)
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::path::Path;

    #[test]
    fn test_parse_and_display_ast() {
        let test_file_path = "test_assets/test.js";

        assert!(
            Path::new(test_file_path).exists(),
            "Test file does not exist"
        );

        match source_to_ast(test_file_path) {
            Ok(ast) => println!("{:#?}", ast),
            Err(e) => eprintln!("Error: {}", e),
        }
    }
}

As you can see, it has used Box::leak multiple times, which I think is because I didn't provide a struct to store the data for persistence. It seems this was done to ensure the data lives long enough.

Assuming I use let allocator = Allocator::default();, unfortunately, I get the following error:

rust-analyzer: expected &Allocator, found Allocator
And when I use & , for example like this:

let allocator = Allocator::default();
let source_type = SourceType::from_path(file_path)
    .map_err(|e| format!("Failed to determine source type: {:?}", e))?;

let parser = Parser::new(&allocator, js_code, source_type);
let parse_result = parser.parse();

Ok(parse_result.program)

I get the following error on the last line:

rustc: cannot return value referencing local variable 'allocator' returns a value referencing data owned by the current function

I tried creating a struct to store the output, like the example below, but I still encountered lifetime-related errors and the same issues mentioned earlier:

pub struct ParseResult<'a> {
    pub program: Program<'a>,
    pub allocator: &'a Allocator,
}

I think I haven’t fully understood the core concept of this part. I hope I’ve managed to convey the steps I’ve taken so far.

Thank you in advance for your help! If you have any suggestions for the correct way to write this code, I’d really appreciate it.

Here’s the dependency I installed:

oxc = { version = "*", features = ["full"] }

1 post - 1 participant

Read full topic