Skip to content

Instantly share code, notes, and snippets.

@rohlem
Last active January 28, 2020 21:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rohlem/b534bc88eaa95aa3719c065f4655f534 to your computer and use it in GitHub Desktop.
Save rohlem/b534bc88eaa95aa3719c065f4655f534 to your computer and use it in GitHub Desktop.
example cases of aliasing via result location
const expectEqual = @import("std").testing.expectEqual;
const V = struct{
a: i32,
b: i32,
pub fn sum(self: V) i32 {
// Note: in a more complex use case, we may depend on the result location within this function ( see issue #2765 ).
// (necessary for e.g. self-referential result types)
return self.a + self.b;
}
};
test "example 1: simple inline math" {
var x: V = V{.a = 1, .b = 1};
x = V{ // the new temporary's result location is x
.a = x.sum(), // x is used in the member init expressions
.b = x.sum(), // if sub-assignment to x.a already took place => 3, otherwise => 2
};
//Note that syntactically the assignment to x seems take place only "after" the right hand side has finished evaluation (at least in my interpretation)
expectEqual(i32(3), x.b); // => 2 would have been my "expected" answer
}
// Potential solution: construct a copy ("old behaviour"), but with result-loc semantics:
//var _result: @typeOf(x) = undefined; // provide an out-of-place result location
//@_spoofAddress(_result, &x); // obviously compiler-internal, exposition-only
//_result = V{.a = x.sum(), .b = x.sum()}; // sum operations get &x.a and &x.b as "observable" result location, but write to &_result as "actual" result location
//x = _result; // copy the out-of-place result back to where we pretended it was all along
test "example 1 (trivially) fixed" {
var x: V = V{.a = 1, .b = 1};
var _result: @typeOf(x) = undefined; // provide separate result location
//@_spoofAddress(_result, &x); // (address not used in this simple case)
_result = V{ // actual/final result location is x, but intermediate result location is _result
.a = x.sum(),
.b = x.sum(), // sub-assignment to intermediate result location obviously didn't affect x.a
};
x = _result;
expectEqual(i32(2), x.b);
}
//In summary: Pass one "final" (observable) and one "intermediate" result location, to allow in-place semantics despite the intermediate copy.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment