Order of assignment to the fields matters, and the borrow checker will let you use variables before you move them into the struct. In general this pattern works:
let value = …;
SomeStruct {
derived: read(&value), // borrowed
value: value, // then moved
}
The borrow must be temporary and end before the next line.
'static
is very weird here. It's pretty much never used for anything in real code. It's leaked memory, so if you insist, you can leak it like this:
struct Foo {
f0: &'static str,
f1: &'static dyn Fn(),
}
impl Foo {
fn new() -> Self {
let f0 = "foo!";
Self {
f1: Box::leak(Box::new(move || {
f0;
})),
f0,
}
}
}
It doesn't access via field, because even though the pointed-to string is static, the address of the field holding the reference isn't guaranteed to be static.
If you need to access the field, then a more realistic design would be:
struct Foo {
f0: &'static str,
f1: fn(&Foo),
}
impl Foo {
fn new() -> Self {
Self {
f0: "foo!",
f1: |ctx| println!("{}", ctx.f0),
}
}
}
and if you want support more than just string literals/leaked memory, then:
struct Foo<'a> {
f0: &'a str, // or even better — f0: String
f1: fn(&Foo),
}
or
struct Foo {
f0: String,
f1: fn(&Foo),
}
impl Foo {
fn new() -> Self {
Self {
f0: "foo!".into(),
f1: Self::f1, // I assume you need ability to reassign this,
// as otherwise there's no point having it as a field
}
}
fn f1(&self) {
println!("{}", self.f0);
}
}