Is there a way to have a struct contain a reference that might no longer be valid?

Viewed 317

Like some kind of Box that holds the reference to the value or something? I'd have to check whether the value is still alive or not before reading it, like when a Option is pattern matched.

A mock example:

struct Whatever {
    thing: AliveOrNot<i32>,
}
fn main() {
    let mut w = Whatever { thing: Holder::Empty };
    w.thing = AliveOrNot::new(100);
    match w.thing {
        Empty => println!("doesn't exist"),
        Full(value) => println!("{}", value),
    }
}

The exact case is that I'm using a sdl2 Font and I want to store instances of that struct in another struct. I don't want to do something like this because the Parent would have to live exactly as long as the Font:

struct Font<'a, 'b> {
    aa: &'a i32,
    bb: &'b i32,
}
struct Parent<'a, 'b, 'c> {
    f: &'c Font<'a, 'b>
}

What I want is for the Parent to work regardless of whether that field is still alive or not.

1 Answers

You may be interested in std::rc::Weak or std::sync::Weak:

use std::rc::{Rc, Weak};

struct Whatever {
    thing: Weak<i32>,
}

impl Whatever {
    fn do_it(&self) {
        match self.thing.upgrade() {
            Some(value) => println!("{}", value),
            None => println!("doesn't exist"),
        }
    }
}

fn its_dead_jim() -> Whatever {
    let owner = Rc::new(42);
    let thing = Rc::downgrade(&owner);

    let whatever = Whatever { thing };
    whatever.do_it();

    whatever
}

fn main() {
    let whatever = its_dead_jim();
    whatever.do_it();
}
42
doesn't exist

There is no way to do this in safe Rust using non-'static references. A huge point of Rust's references is that it's impossible to refer to invalid values.

  • You could leak the memory, creating a &'static i32, but that's not sustainable if you need to do this multiple times.

  • You could use unsafe code and deal with raw pointers that have no notion of lifetimes. You then assume the responsibility of ensuring you don't introduce memory unsafety.

See also:

Related