On 02/08/12 18:24, Timon Gehr wrote: > I think we'd indeed need ownership / an 'unique' type qualifier. This could > also be helpful: > http://d.puremagic.com/issues/show_bug.cgi?id=7316 > > I think type system controlled aliasing is very important to make it work, so > another important step would be to enforce the 'scope' storage class through > flow-analysis. > > As far as the 'unique' type qualifier goes, we need to find a suitable design: > > > void main(){ > auto x = new C; // if constructor is pure or scope, x can be unique > pragma(msg, typeof(x)); // ? > auto y = x; // ? > pragma(msg, typeof(x)," ",typeof(y)); // ? > x.foo(); // ? > spawn(&bar, x) // ? > } > > So maybe it should look more like this: > > void main(){ > auto x = new C; // pure/scope constructor > static assert(typeof(x) == C); > auto y = x; > y.foo(); // foo is pure or scope > spawn(&bar, unique x); // fine > } > > This would add unique as an unary operator to perform a safe conversion to > unique. Similar operators could be added for immutable/shared/const/inout. > Such an approach would be backwards-compatible.
"cast(uniq)x" would be much more intuitive. But, for the code above, what advantage would an explicit conversion have, given that the compiler has to perform the checks anyway? If spawn() has an overload that does not require conversion (and eg copies the object internally) it's important that the right thing happens automatically. > This solution uses flow-analysis to make sure that no alias to x is alive > after the safe conversion to unique. > Because of the guarantees that unshared gives, the flow analysis can even > include unshared fields. > > We could even do: > > void spawn(F,T...)(F fun, T args) if(!mayHaveMutableNonUniqueAliasing!T) { > ... } > void spawn(F,T...)(F fun, unique T args) > if(mayHaveMutableNonUniqueAliasing!T) { spawn(fun, args); } > > Then the example would look like: > > void main(){ > auto x = new C; // pure or scope > auto y = x; > y.foo(); // pure or scope > spawn(&bar, x); // fine! > } > > x converts to unique if flow analysis can prove no alias to it is alive after > the conversion. The first spawn overload does not match, therefore the second > one is chosen. x is implicitly converted to unique and then the other > overload is used to finish up. > > > Open issue: > > void main(){ > unique x = new C; > pragma(msg, typeof(x.z)); // ??? > auto y = x.z; // error? > immutable z = x; > } > > x.z is not necessarily unique, but assigning it to y breaks the guarantees of > the unique qualifier of x. This is why treating "unique" as a static storage class doesn't really work. One of the two last lines above would have to be disallowed, and that reduces its usefulness dramatically. The "auto" assignment either has to be illegal, or trigger a mutation, eg to immutable. I don't think having the compiler keep track of all possible relations would be a practical solution, even if theoretically possible. For those not reading D.learn - unique helps in other cases too: http://lists.puremagic.com/pipermail/digitalmars-d-learn/2012-February/029547.html artur