You can't return a value that borrows from a local variable of the function because that value will be destroyed when it goes out of scope. You have to return an owned value (e.g. a Box) in this case.
This foo has to live somewhere as long as the Bar it is in lives. It doesn't matter whether you use Box or something else.
You may pass the foo as a parameter to the create_bar for solving the lifetime problem. Or you may make the Bar struct own the local foo instead of borrowing it.
It depends on what you're trying to achieve and why you want to get rid of Box.
You can use smallbox instead of Box to avoid an allocation if your objects are small.
You can leak the Box and return the produced static reference if you don't need to ever delete the object.
You can refactor your code so that you don't return the borrowed value at all, instead you just store it locally and pass it to somewhere by reference to process it while it's still in scope:
fn main() {
let foo = MyFoo {};
let bar = Bar { foo: &foo };
work_with_bar(bar);
}
Box is not less performant in usage then references, since both are compiled down to plain pointers (or fat pointers, in case of trait objects). The only performance hit is during the allocation, since value must be first created on stack and then moved to heap.