someguynamedjosh/ouroboros

Docs: unclear when `*_builder` functions are called

Closed this issue · 0 comments

The following:

use ouroboros::self_referencing;

#[self_referencing]
struct Foo {
    value: usize,
    #[borrows(value)]
    value_ref: &'this usize,
}

fn main() {
    let foo = FooBuilder {
        value: 3,
        value_ref_builder: |value| {
            println!("Invoking builder!");
            value
        },
    }
    .build();
    println!("Before printing");
    println!("foo value ref #1 is {}", foo.borrow_value_ref());
    println!("foo value ref #2 is {}", foo.borrow_value_ref());
}

prints

Invoking builder!
Before printing
foo value ref #1 is 3
foo value ref #2 is 3

This implies that the *_builder function is called exactly once at .build() time. This is certainly what I would expect, but you could imagine that it could be called on the first call to borrow_*, or indeed, to every call to borrow_* (which you would have to go out of your way to implement in ouroboros, but technically consistent with the documentation, I think?).

In particular, it's not explicit whether it's fine to do expensive initialization in the _builder function and when that initialization is actually performed. The documentation should specify that all _builder functions are called exactly once at .build() time.

I don't see it explicitly specified which order the builder functions are called, either. Presumably in declaration order? Maybe a more interesting situation is whether *AsyncBuilder::build calls the _builder functions serially or concurrently. Given that the builder functions accept immutable borrows, it seems possible that all _builder functions could be called concurrently?