Struct str attribute must be reference? [duplicate] - string

This question already has answers here:
How to solve "returns a value referencing data owned by the current function" error in Rust? [duplicate]
(1 answer)
Return local String as a slice (&str)
(7 answers)
Why can't I return an &str value generated from a String?
(1 answer)
Is there any way to return a reference to a variable created in a function?
(5 answers)
Closed 3 years ago.
For the following code:
fn get_lines() -> String {
String::from("Hello\nWorld")
}
fn get_first_line(s: &String) -> &str {
s.lines().next().unwrap()
}
struct World<'a> {
a_str: &'a str,
}
fn work<'a>() -> World<'a> {
let s1 = get_lines();
let s2 = get_first_line(&s1);
World { a_str: s2 }
}
fn main() {
let w = work();
}
I got the following error:
error[E0515]: cannot return value referencing local variable `s1`
--> src/main.rs:17:5
|
15 | let s2 = get_first_line(&s1);
| --- `s1` is borrowed here
16 |
17 | World { a_str: s2 }
| ^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
How to build a struct instance using s2? Is it a conceptual error of the World struct?

World refers to a str slice which must be owned by something else. Your function work allocates a new String (through get_lines), and makes a reference into it (through get_first_line). When it returns, the String goes out of scope and will be dropped, so you cannot keep a reference to it, since the thing it refers to is no longer there.
If you want a World object that does not depend on a String owned by something else, it will need to own the data itself: Contain a String instead of a &'a str.
See also 'dangling references' in the Rust Book.

Related

Error when returning object containing RefCell [duplicate]

This question already has answers here:
How do I return a reference to something inside a RefCell without breaking encapsulation?
(3 answers)
How to borrow the T from a RefCell<T> as a reference?
(1 answer)
How can I obtain an &A reference from a Rc<RefCell<A>>?
(1 answer)
Closed 7 months ago.
I am trying to make a rust program that can parse equations. One part of the program requires, that I have multiple variable objects that point to a single definition. To be able to do that I use a VariableContext object that stores multiple variable definitions. It has a get_variable method that either returns a new variable or an existing one. This object is then passed to a parser function. Sadly I seem unable to actually use the returned variable, I have already tried wrapping the VariableContext object in a Rc, but it still gives me errors.
The parse function:
fn parse<'a>(
tokens: Vec<Token<'a>>
context: Rc<RefCell<VariableContext<'a>>>,
) -> Result<ExprVariant<'a>, ParserError> {
/* ... */
let variable = (*context).borrow_mut().get_variable(token.slice);
Ok(expression::ExprVariant::Variable(variable))
/* ... */
}
the VariableContext struct:
pub struct VariableContext<'a>{
pub variables: Vec<Rc<VariableDefinition<'a>>>
}
The get_variable method:
pub fn get_variable(&'a mut self, name: &str) -> VariableExpr<'a> {
if let Some(definition) = self.find_definition(name){
let variable = VariableExpr::new(definition.clone());
variable
//ExprVariant::Variable(variable)
}else{
let definition = Rc::new(VariableDefinition::new(name.to_string()));
self.add_definition(definition.clone());
let variable = VariableExpr::new(definition.clone());
//ExprVariant::Variable(variable)
variable
//&self.variables[self.variables.len()-1]
}
}
The Error:
error[E0515]: cannot return value referencing function parameter `context`
--> src/parser/textparser.rs:35:13
|
34 | let variable = (*context).borrow_mut().get_variable(token.slice);
| ------- `context` is borrowed here
35 | Ok(expression::ExprVariant::Variable(variable))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
I am sorry if I haven't given enough information or am doing something stupid

How to move ownership of PathBuf together with Path slice [duplicate]

This question already has answers here:
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
Closed 1 year ago.
I want to create a struct containing a PathBuf (with an absolute path) and a &Path (with a relative path derived from that absolute path). Here is my attempt:
use std::path::{Path, PathBuf};
struct File<'a> {
abs_path: PathBuf,
rel_path: &'a Path,
}
impl<'a> File<'a> {
fn new(abs_path: PathBuf, rel_path: &'a Path) -> File<'a> {
File { abs_path, rel_path }
}
}
fn main() {
let abs_path = PathBuf::from("/path/to/file");
let rel_path = abs_path.strip_prefix("/path").unwrap();
let _file = File::new(abs_path, rel_path);
}
When I compile this, I get the following error:
error[E0505]: cannot move out of `abs_path` because it is borrowed
--> src/main.rs:17:27
|
16 | let rel_path = abs_path.strip_prefix("/path").unwrap();
| -------- borrow of `abs_path` occurs here
17 | let _file = File::new(abs_path, rel_path);
| ^^^^^^^^ -------- borrow later used here
| |
| move out of `abs_path` occurs here
I understand that I cannot transfer ownership of abs_path because I borrowed a reference to it when I created rel_path. I am attempting to link the two together inside the struct, by restricting the lifetime of rel_path. Can anyone tell me how to get both values into the struct?
Thanks!
While there are ways to store a reference and a value together (raw pointers + Pin, Box + https://crates.io/crates/rental), the easiest thing to do would probably be to store the start and end index of the slice.

Rust - Lifetime of struct member depends on another struct member [duplicate]

This question already has answers here:
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
Closed 3 years ago.
I'm trying to write a Rust struct. The struct owns a Reference counted pointer to a string and also owns a vector of string slices to the same string.
Furthermore I'm trying to write a function to generate this struct. I'm unsure how to proceed.
struct MyStruct<'a> {
rc_string: Rc<String>,
vec: Vec<&'a str>
}
fn build_my_struct<'a>(s: &Rc<String>) -> MyStruct<'a> {
let rc_string = s.clone();
let mut vec = Vec::new();
vec.push(&rc_string[0..2]);
MyStruct {
rc_string: rc_string,
vec: vec
}
}
error[E0515]: cannot return value referencing local variable `rc_string`
--> src/main.rs:13:5
|
11 | vec.push(&rc_string[0..2]);
| --------- `rc_string` is borrowed here
12 |
13 | / MyStruct {
14 | | rc_string: rc_string,
15 | | vec: vec
16 | | }
| |_____^ returns a value referencing data owned by the current function
I understand that the vec variable has borrowed the rc_string. The compiler doesn't like returning vec because it has the borrow to the local variable rc_string.
However rc_string is being returned as well? The string slices are valid for the duration of the life of MyStruct.rc_string?
You need to borrow Rc for life time 'a as well. Compiler needs to know that slice from a String is living in 'a or not. In this case we need to borrow Rc for 'a and compiler will know inner of Rc will also live in 'a.
If you clone s and assign it to rc_string:
s will stay in the function's scope as borrowed Rc for lifetime 'a
rc_string will be the owner of the Rc pointer
and compiler won't be able to know slice of a rc_string is living for 'a or not.
Using slice from a s will work :
fn build_my_struct<'a>(s: &'a Rc<String>) -> MyStruct<'a> {
let mut vec = Vec::new();
let rc_string = s.clone();
vec.push(&s[0..2]);
MyStruct { rc_string, vec }
}
Playground

What is the correct way to get values via a method without moving it? [duplicate]

This question already has answers here:
How to prevent a value from being moved?
(2 answers)
When would an implementation want to take ownership of self in Rust?
(2 answers)
What do I have to do to solve a "use of moved value" error?
(3 answers)
How can I solve "use of moved value" and "which does not implement the `Copy` trait"?
(1 answer)
Closed 3 years ago.
I don't understand why Rust moves the value. Do I oversee a major point in the ownership?
The struct MyData is a smaller version. I store some values in this struct, and want to access the stored values, but the compiler tells me after the second access, that the value was moved.
I want to make some getters for my structs. I already derived Clone, but that does not help.
The problem occurs on Windows 10 with the GNU-Compiler and on Kubuntu 18.04 LTS.
My current workaround is to clone the data beforehand, but this can't be the correct way.
#[derive(Debug, Clone)]
struct MyData {
val1: i32,
val2: String,
}
impl MyData {
pub fn get_val1(self) -> i32 {
return self.val1.clone();
}
pub fn get_val2(self) -> String {
return self.val2.clone();
}
pub fn get_both(self) -> (i32, String) {
return (self.val1, self.val2);
}
}
fn main() {
let d = MyData {
val1: 35,
val2: String::from("Hello World"),
};
let both = d.get_both();
let x = d.get_val1();
let y = d.get_val2();
}
error[E0382]: use of moved value: `d`
--> src/main.rs:28:13
|
27 | let both = d.get_both();
| - value moved here
28 | let x = d.get_val1();
| ^ value used here after move
|
= note: move occurs because `d` has type `MyData`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `d`
--> src/main.rs:29:13
|
28 | let x = d.get_val1();
| - value moved here
29 | let y = d.get_val2();
| ^ value used here after move
|
= note: move occurs because `d` has type `MyData`, which does not implement the `Copy` trait
I expect that let x = d.get_val1(); won't cause an error. In my understanding of ownership in Rust, I did not move the value, since I'm calling a method of MyData and want to work with the value.
Why does Rust move the value and to whom?

Method that returns reference to value created in the method? [duplicate]

This question already has answers here:
Is there any way to return a reference to a variable created in a function?
(5 answers)
Return local String as a slice (&str)
(7 answers)
Proper way to return a new string in Rust
(2 answers)
Closed 4 years ago.
I have a struct that contains references to two different values. There's two constructors - one that takes a reference for each value, and one that only takes a reference to one of the values while assigning a default to the other.
My problem is assigning that default. See the code below:
struct Foo<'t> {
a: &'t String,
b: &'t String,
}
impl<'t> Foo<'t> {
fn new(a: &'t String, b: &'t String) -> Foo<'t> {
Foo { a, b }
}
fn new_with_default_b(a: &'t String) -> Foo<'t> {
Foo {
a,
b: &String::from("default"),
}
}
}
This does not compile:
error[E0515]: cannot return value referencing temporary value
--> src/lib.rs:12:9
|
12 | / Foo {
13 | | a,
14 | | b: &String::from("default"),
| | ----------------------- temporary value created here
15 | | }
| |_________^ returns a value referencing data owned by the current function
Is it possible to fix this?

Resources