Open
Description
We currently unconditionally permit returned var
s in functions, and the implication seems to be that the assert in this testcase holds for any type T
:
fn F[T:! type](v: T, p: T**) -> T {
returned var ret: T = v;
*p = &ret;
return var;
}
fn G[T:! type](x: T) {
var p: T*;
var v: T = F(x, &p);
Assert(&v == p);
}
But that's problematic: it means that a function like F
that uses a returned var
(or, transitively, initializes its return object from a function that uses a returned var
) cannot return in registers, which means that our calling convention, at least for functions whose bodies we can't see, can't return in registers, even for types like i32
or ()
.
I think:
- A type author should be able to choose whether their type is guaranteed to be returned in-place or not (and in the latter case might be returned in registers).
- A function author should be able to choose whether they guarantee to return in-place or not.
As a starting point, how about this:
- Any type
T
whose value representation isconst T*
defaults to being returned in-place; any type whose value representation isconst T
defaults to being returned by copy.- Possibly this default can be overridden in some way, separately from customizing the value representation, or possibly not.
- For the in-place case, we could choose to both pass in a return slot and return a pointer to where the result actually is, putting the burden of performing an optional copy on the caller, or we could choose to require that the function actually initializes into the provided address.
- For a custom value representation, we could provide some mechanism to let the class author choose, or we could always use in-place initialization, or we could pass in a return slot and return a value representation and a bool indicating whether the return slot got initialized.
- A function that uses a
-> T
return uses the default for the type; a function that uses a-> var T
return guarantees to return in-place.returned var
notation is only permitted in a function that is guaranteed to return in-place, either because the function uses-> var
or (optionally) because the type requires an in-place return.