Reputation: 46
Let's say a Manager
holds references to a Designer
and a Programmer
, but the Programmer
also has to hold a reference to a Designer
, in order to ping them whenever they want.
The problem is, by creating both the Designer
and the Programmer
in Manager::new()
, the &designer
reference doesn't live long enough, since in the following lines, it gets moved inside the Manager
.
The error is 'designer' does not live long enough
.
struct Programmer<'a> {
designer: &'a Designer,
}
impl<'a> Programmer<'a> {
pub fn new(designer: &'a Designer) -> Programmer<'a> {
Programmer { designer: designer }
}
}
struct Designer {
iq: u32,
}
impl Designer {
pub fn new(iq: u32) -> Designer {
Designer { iq: iq }
}
}
struct Manager<'a> {
programmer: Programmer<'a>,
designer: Designer
}
impl<'a> Manager<'a> {
pub fn new() -> Manager<'a> {
let designer = Designer::new(42);
let programmer = Programmer::new(&designer);
Manager { designer: designer, programmer: programmer }
}
}
fn main() {
Manager::new();
}
Compilation fails with this message:
test.rs:29:47: 29:55 error: `designer` does not live long enough
test.rs:29 let programmer = Programmer::new(&designer);
^~~~~~~~
test.rs:27:37: 32:10 note: reference must be valid for the lifetime 'a as defined on the block at 27:36...
test.rs:27 pub fn new() -> Manager<'a> {
test.rs:28 let designer = Designer::new(42);
test.rs:29 let programmer = Programmer::new(&designer);
test.rs:30
test.rs:31 Manager { designer: designer, programmer: programmer }
test.rs:32 }
test.rs:27:37: 32:10 note: ...but borrowed value is only valid for the block at 27:36
test.rs:27 pub fn new() -> Manager<'a> {
test.rs:28 let designer = Designer::new(42);
test.rs:29 let programmer = Programmer::new(&designer);
test.rs:30
test.rs:31 Manager { designer: designer, programmer: programmer }
test.rs:32 }
How could I fix this problem, without injecting the Designer
via Manager::new(&designer)
?
Upvotes: 1
Views: 87
Reputation: 38626
I imagine you know what you're doing, but that doesn't seem like the best design to use with Rust. You say a Programmer
should hold a reference to a Designer
in order to ping them, but I imagine that pinging them implies mutating the Designer
in some way (e.g. imagine some is_pinged
field on the Designer
), which you can't do via a simple reference. All you can do through a regular, immutable reference is read the data or call methods which don't mutate the variable. What's more, so long as you have that reference, the original Designer
cannot be mutated.
If you do just want to have an immutable reference though, then you can use the Rc
type, which provides an immutable reference-counted pointer.
If you want to somehow allow the Programmer
to send messages to the Designer
which may or may not trigger mutations on the Designer
, then you can try using channels. Each Designer
would store its own channel
, and it could have a method which clones the Sender
end of the channel for an interested Programmer
to store and use.
Upvotes: 2