On 02/08/2012 10:26 PM, Artur Skawina wrote:
On 02/08/12 19:51, Timon Gehr wrote:
On 02/08/2012 07:30 PM, Artur Skawina wrote:
On 02/08/12 18:24, Timon Gehr wrote:

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,


Actually that is not true. It could type check, because y is not alive after x 
has been cast to immutable.

I assumed this was a simplified example and both 'y' and 'z' would be accessed 
later.


Ok, sorry about that.

The problem shows here:

void main(){
     unique x = new C;
     auto y = x.z;
     immutable z = x;
     foo(y,z);
}

But in real code the situation will be more complex, and like i said, while i
think it can be done in theory, i don't think it should. Consider your two above
examples - you want to allow something that's not really useful (dead 
assignment,
that will be eliminated by an optimizing compiler), while not really solving
the real case (for which there's no ideal solution, if it were to be legal).

and that reduces its usefulness dramatically.

Can you show me an example of its use?

I think that introducing a new type modifier/class might not be necessary. What 
if
in all these examples we were to use "auto" instead of "unique" when declaring 
the
variables _and_ have the compiler internally keep a 'unique' flag? It can then 
do
the safe conversions implicitly, and this is still backwards compatible.

How do you pass ownership of an object graph between threads if there is no explicit representation of ownership in the type system?

The problematic cases are a) accessing the type directly (ie typeof etc) and b) 
multiple
conflicting assignments.

Also, consider your original example from this thread:

void main(){
     auto x = new C; // pure or scope
     auto y = x;
     y.foo(); // pure or scope
     spawn(&bar, x); // fine!
}

What if 'x' is used after the call to spawn()?

Then it does not implicitly convert to unique. This example relied on a modified definition of spawn whose sketch you did not quote.

If we effectively passed ownership of our unique instance to another context, 
'x' can no longer
be "unique". If it were to mutate to the target type, then leaving it
accessible from the current context should be reasonably safe.


The idea was that spawn could take unique class references and pass ownership to a different thread -- eliminating the need to cast to and from shared.

(Unless the new type is "unique" too - but allowing this only when there
are no further accesses to 'x' should be enough)


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.

I think it would be practical enough.

typeof(C.z) global;

void main(){
     unique x = new C;
     auto y = x.z;
     static assert(!is(typeof(y)==immutable));
     static assert(!is(typeof({global = y;}));
     immutable z = x;
     static assert(is(typeof(y)==immutable));
     static assert(is(typeof(x)==immutable);
     foo(y,z);
}

'y's type changed here - this wouldn't have worked for a "static" unique type.

I know. A unique field / static variable cannot be copied, only moved:

unique int[] a = [1,2,3,4];

void main(){
    unique b = a;
    a = null;
}

And if it can work for "auto" - is an explicit "unique" for 'x' needed?
This example *could* work, but the interesting cases are the ones when the
assignments/mutations are non-trivial and done because the data is actually
used - i'm worried that doing the analysis *then* would be too expensive.


I don't think so.




Reply via email to