Last active
January 28, 2020 21:58
-
-
Save rohlem/b534bc88eaa95aa3719c065f4655f534 to your computer and use it in GitHub Desktop.
example cases of aliasing via result location
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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