How to solve “returns a value referencing data owned by the current function” error in Rust? [duplicate]

The biggest problem with the code is the use of &str in the ExpressionNode.
The simplest fix is to change it to String. You can see the fix for that below.
This also allows removal of all the lifetime annotations.

There’s also a second fix in that code that is important.

let value: &str = *rand::thread_rng().choose(&operators).unwrap();
if value == "ELEM"{
    let value = rand::thread_rng().gen::<f64>().to_string();
}

should be updating value, so the assignment within the if should not contain let, and the first assignment should be let mut value.

If you’re not happy with all the assignments that are happening when switching to a String, you have two other options – use a Cow string or use a enum for the contained value type so that it can contain a string or a float, something like – val: Either<&str, f64> (There’s a version using this at the end of this answer).

The string based version:

use rand::Rng;

#[derive(Debug)]
struct ExpressionNode {
    val: String,
    left: Option<Box<ExpressionNode>>,
    right: Option<Box<ExpressionNode>>,
}

fn create_expression(operators: &[&str], p: i32) -> Option<Box<ExpressionNode>> {
    if p == 0 {
        let value = String::from(rand::thread_rng().gen::<f64>().to_string());
        let new_node = ExpressionNode {
            val: value,
            left: None,
            right: None,
        };
        return Some(Box::new(new_node));
    }
    let mut value = rand::thread_rng().choose(&operators).unwrap().to_string();
    if value == "ELEM" {
        value = rand::thread_rng().gen::<f64>().to_string();
    }

    let new_node = ExpressionNode {
        val: value,
        left: create_expression(operators.clone(), p - 1),
        right: create_expression(operators.clone(), p - 1),
    };
    Some(Box::new(new_node))
}

fn main() {
    let v = vec!["a", "b", "c", "ELEM"];
    let tree = create_expression(&v, 3);
    println!("tree = {:?}", tree)
}

For comparison, here’s a version using Either<&str, f64>:

use either::Either;
use rand::Rng;

#[derive(Debug)]
struct ExpressionNode<'a> {
    val: Either<&'a str, f64>,
    left: Option<Box<ExpressionNode<'a>>>,
    right: Option<Box<ExpressionNode<'a>>>,
}

fn create_expression<'a>(operators: &[&'a str], p: i32) -> Option<Box<ExpressionNode<'a>>> {
    if p == 0 {
        let value = rand::thread_rng().gen::<f64>();
        let new_node = ExpressionNode {
            val: Either::Right(value),
            left: None,
            right: None,
        };
        return Some(Box::new(new_node));
    }
    let v = *rand::thread_rng().choose(&operators).unwrap();
    let value = if v == "ELEM" {
        Either::Right(rand::thread_rng().gen::<f64>())
    } else {
        Either::Left(v)
    };

    let new_node = ExpressionNode {
        val: value,
        left: create_expression(operators.clone(), p - 1),
        right: create_expression(operators.clone(), p - 1),
    };
    Some(Box::new(new_node))
}

fn main() {
    let v = vec!["a", "b", "c", "ELEM"];
    let tree = create_expression(&v, 3);
    println!("tree = {:?}", tree)
}

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)