Using `Option::unwrap_unchecked()` after setting the option to `Some(...)`

In a struct, I would like a method which sets an option to Some(my_object), then directly returns the inner reference of the object (&MyObject, not Option<&MyObject>).

In this case:

  • Is it safe to use Option::unwrap_unchecked() ?
  • Is it possible to not use a unsafe block, without loosing a tiny bit of runtime?

Minimal example:

#[derive(Debug, Default)]
struct Child {
    // ...
}

#[derive(Debug, Default)]
struct Parent {
    opt_child: Option<Child>,
    // ...
}

impl Parent {
    pub fn set_child(&mut self, child: Child) -> &Child {
        self.opt_child = Some(child);

        // SAFETY: we are 100% sure that self.opt_child is `Some`
        unsafe {
            self.opt_child.as_ref().unwrap_unchecked()
        }
    }

    // ...
}

fn main() {
    let mut parent = Parent::default();
    let child = parent.set_child(Child::default());
    println!("{:?}", child);
}

The optimizer knows you just set it; you can use .unwrap() and the optimizer knows it doesn't need a check.

Demonstration on godbolt: https://rust.godbolt.org/z/8oM3qqYco.

You'll see that has no branches and no panicking code.

6 Likes

Option also has a method for this purpose, Option::insert, which has pretty much the exact same implementation as the code in the OP: https://doc.rust-lang.org/1.69.0/src/core/option.rs.html#1605-1607

pub fn set_child(&mut self, child: Child) -> &Child {
    self.opt_child.insert(child)
}
11 Likes

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.