The return value is represented inside the body of a routine as the special result variable. This allows for a mechanism much like C++’s “named return value optimization” (NRVO). NRVO means that the stores to result inside p directly affect the destination dest in let/var dest = p(args) (definition of dest) and also in dest = p(args) (assignment to dest). This is achieved by rewriting dest = p(args) to p’(args, dest) where p’ is a variation of p that returns void and receives a hidden mutable parameter representing result.
Let T’s be p’s return type. NRVO applies for T if sizeof(T) >= N (where N is implementation dependent), in other words, it applies for “big” structures.
BigT = array[16, int]
proc p(raiseAt: int): BigT =
for i in 0..high(result):
result[i] = i
proc main =
var x: BigT
except ValueError:
doAssert x == [0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0]
However, the current implementation produces a warning in these cases. There are different ways to deal with this warning:
- Disable the warning via {.push warning[ObservableStores]: off.} … {.pop.}. Then one may need to ensure that p only raises before any stores to result happen.