But data from `x` flows into `x` here

There is a struct:

struct D {
  d1: String,
  d2: &String
}

Function test, let d2=&d1:

fn test(d: &mut D) {
  d.d2 = &d.d1;
}

Compile tell me add 'a lifetime. I do as:
fn test<'a>(d: &'a mut D<'a>)
and in main:

fn main() {
  let d = D{d1:"a".to_string(), d2:&"".to_string};
  test(&d);
  println("{:?}", d)
}

Compile tell me d as mut borrow then again as immut borrow in println.

Please edit your post to follow our code formatting guidelines:

This is almost always wrong, since this effectively locks the structure forever.

2 Likes

Ok. This is wrong. Please tell me, how can I fixed first error?

fn test(d: &mut D) {
  let d.d2 = &d.d1
}

How can I resole this error?
but data from `db` flows into `db` here

You can't. This is a self-referential struct, which Rust can't really support. Such a struct would have its pointer-to-itself invalidated when moved. What are you trying to do? Usually, there are better ways to solve problems in Rust than self-referential types.

Thanks. I can use Rc to solve the problem.

struct D {
    d1: Rc<String>,
    d2: Rc<String>
}

fn test(db: &mut Database) {
    db.d2 = Rc::clone(&db.d1);
}

But I worry degradation of performance.

Using Rc is a decent option, though Rc<str> is usually faster than Rc<String>. An Rc<str> can be created with Rc::from(your_str).

You could also use an Option<String> and let None mean "the value in d1".

1 Like

Thank all. I resove the problem using macro. Code is:

#[derive(Debug)]
struct Database<'a> {
    d1: String,
    d2: &'a String,
}

#[macro_export]
macro_rules! test {
    ( $x:expr ) => {
        {
            $x.d2 = &$x.d1;
        }
    };
}

fn main() {
    let mut db: Database = Database{ d1:"a".to_string(), d2:&"".to_string() };
    test!(db);
    println!("{:?}", db);
}

This wouldn't work in general. For example, trying to return Database from the function (or, more generally, move it out of its creation point) would fail - playground:

// struct Database and macro test - as above
fn get_db<'a>() -> Database<'a> {
    let mut db: Database = Database {
        d1: "a".to_string(),
        d2: &"".to_string(),
    };
    test!(db);
    db
}

fn main() {
    let db = get_db();
    println!("{:?}", db);
}

Errors:

error[E0505]: cannot move out of `db` because it is borrowed
  --> src/main.rs:19:5
   |
11 |             $x.d2 = &$x.d1;
   |                     ------ borrow of `db.d1` occurs here
...
16 | fn get_db<'a>() -> Database<'a> {
   |           -- lifetime `'a` defined here
...
19 |     db
   |     ^^
   |     |
   |     move out of `db` occurs here
   |     returning this value requires that `db.d1` is borrowed for `'a`

error[E0515]: cannot return value referencing local data `db.d1`
  --> src/main.rs:19:5
   |
11 |             $x.d2 = &$x.d1;
   |                     ------ `db.d1` is borrowed here
...
19 |     db
   |     ^^ returns a value referencing data owned by the current function

error[E0515]: cannot return value referencing temporary value
  --> src/main.rs:19:5
   |
17 |     let mut db: Database = Database{ d1:"a".to_string(), d2:&"".to_string() };
   |                                                              -------------- temporary value created here
18 |     test!(db);
19 |     db
   |     ^^ returns a value referencing data owned by the current function

You are right. I use it in special case. In fact, all within one function. If out-of the function, it's error.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.