Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added documentation for Result Location Semantics #5035

Closed
wants to merge 13 commits into from
43 changes: 40 additions & 3 deletions doc/langref.html.in
Original file line number Diff line number Diff line change
Expand Up @@ -5458,9 +5458,46 @@ test "@intToPtr for pointer to zero bit type" {
{#header_close#}

{#header_open|Result Location Semantics#}
<p>
<a href="https://github.com/ziglang/zig/issues/2809">TODO add documentation for this</a>
</p>
<p>Certain expressions which manipulate a value in memory will directly initialize the final location of
that memory, to avoid making multiple allocations and copying between them:</p>
{#code_begin#}
pub fn main() void {
// foo() allocates its result directly in x -- only one allocation is made
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Allocation" is usually considered dynamic allocation, but that's not what's happening here.
Here we're talking about more general allocation of registers or stack space for variables.
For field2 below, not even that - the allocation of space was already done by var y so we're just referring to that space instead.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, what would the appropriate term for that be then?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure. I guess you could just clarify it; that the term refers to allocation of variables, which is either on the stack or in a register, rather than a dynamic allocation. 🤔

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about just qualify the allocation as a stack allocation?

Copy link
Contributor

@Tetralux Tetralux Apr 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it may not (and probably won't) always be a stack allocation, and you might care---Zig being a systems language---about that fact.

OTOH, you could argue that putting it in a register is an optimization, and that it's easier to think about if you just talk about the stack -- even though it's an optimization that always happens.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, then 'non-heap' allocation, if you want to factor in compiler optimization potentials.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, cleared up and rebased. Now it should be ready for merge.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also subscribed to #2761 and #2765 so I can fix those points when it's relevant (haven't yet gotten the hang of inline testing).

var x = foo();

// Result location is properly communicated through struct fields and if expressions
var y = Data {
.field1 = 26,
.field2 = if (condition) bar() else baz(),
};

// Unwrapping errors or optionals currently does not elide copy (https://github.com/ziglang/zig/issues/2765)
var z = quux() catch unreachable; // Value is allocated twice
}

fn foo() Large {
// Direct return correctly passes result location to callsite
return Large { ... }
}

fn bar() Large {
// Assignment to a variable always makes another allocation, even when this variable is returned
// -- automatic copy elision in this case is planned (https://github.com/ziglang/zig/issues/2765)
var l = Large { ... };
}

fn quux() !Large { ... }}
{#code_end#}
<p>The current result location semantics elide copies from the following locations where possible:</p>
<ul>
<li>Variable declaration bodies</li>
<li>Struct, array and union initializations</li>
<li>If statement branches</li>
<li>Switch statement arms</li>
<li>Function returns</li>
<li>{#syntax#}catch{#endsyntax#} and {#syntax#}orelse{#endsyntax#} default statements</li>
<li>Arguments to {#syntax#}@bitCast{#endsyntax#}</li>
</ul>
{#header_close#}

{#header_open|usingnamespace#}
Expand Down