Pre-RFC: minimal, flexible placement and returning unsized types

But what happens when the function doesn't return a result? How do you make it so that people can use the return_with functions in generic code?

I don't think it's possible to avoid returns-by-copy in general. Let's take your last not_bad example, and switch it into a Result and do a bit more complicated stuff.

fn not_bad() -> Result<[i32; 1_000_000], [i32; 8]> {
    let mut arr = [0i32; 1_000_000];
    for i in 0..1_000_000 {
        arr[i] = i;
    }
    if coin_flip() {
        Ok(arr)
    } else {
        Err([arr[7], arr[6], arr[5], arr[4], arr[3], arr[2], arr[1], arr[0]])
    }
}

In order to avoid copying, the compiler would have to compile it into this set of pseudocode steps:

  • First, it would need to perform the for loop, writing each list item directly into the return slot prepared by the caller. It does not yet populate the Result discriminant, and as such is treating the return slot as scratch space. This is fine.
  • Next, it does the coin flip.
  • If it returns true,
    • it should write the Ok discriminant,
    • and then jump into the caller.
  • Otherwise,
    • it writes the Err discriminant
    • It it reads from arr, which is in the caller's stack frame, while simultaneously writing its new return value, which is in the same spot in the caller's stack frame. <-- this is where the problem is
    • and then jump into the caller
1 Like