transporting qualifier from parameter to the return value
Michel Fortin
michel.fortin at michelf.com
Tue Dec 15 19:43:55 PST 2009
On 2009-12-15 22:02:59 -0500, Andrei Alexandrescu
<SeeWebsiteForEmail at erdani.org> said:
> Time has come to make a decision on implementing Steven Schveighoffer's
> proposal:
>
> http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP2
>
> It's been in the back of my mind for a while now, I don't find a fault
> with it, it solves a very unpleasant problem that would seriously mar
> qualifiers, and although it doesn't solve 100% of the potential cases,
> it does solve a good fraction of them. I am confident that we can
> require body duplication for the remaining stragglers with a straight
> face.
>
> My main concern is allowing shared to participate to the inout
> transportation. I am tempted to allow it, but shared is constrained
> much more severely than the other two.
>
> To avoid problems with the existing uses of inout (which is an old
> synonym for ref), the language requires that you redundantly use inout
> in the return type as well. We could eliminate that in D3.
>
> Any thoughts would be appreciated.
inout? I guess you mean you decided to rename vconst by inout. I can't
seem to find a better name, so I guess it's good enough.
But I see a flaw in accepting shared. And vconst might be a better name
after all. Here's the explanation.
So what code inout would generate now? Generate one copy of the
function for each possible combination? It can't really do otherwise
because the const and non-const versions of other functions it calls
might be separate functions too, with separate addresses:
class Test {
void doThat() immutable {}
void doThat() const {}
void doThat() {}
void doThat() shared immutable {}
void doThat() shared const {}
void doThat() shared {}
void doSomething() inout // or vconst
{
doThat(); // which doThat does it call?
}
}
Let's accept that doSomething is generated in six copies to allow
doSomething to call each version of doThat, and let's look at the next
case:
class Test {
void doThat() immutable {}
void doThat() shared immutable {}
void doSomething() inout // or vconst
{
doThat(); // which doThat does it call?
}
}
Now you also have the problem that only the shared immutable and
non-shared immutable version of doSomething can compile. Should it
generate only two functions? What if I remove the body and only the
signature remains, how do I know I can't call doSomething on a mutable
object?
The problem here is conflating constness with sharedness (!). With
vconst, you know it can accept any kind of constness, so it's
automatically an error if you can't compile the immutable, the mutable
and the const version of the function. Mix shared into this and
everything is mixed up.
So to catch errors correctly you need vconst which would instanciate
three versions of the function: mutable, const, immutable, and be an
error if one of the three can't compile; and vshared which would
instanciate two: thread-local and shared, and be an error if one of the
two can't compile.
--
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/
More information about the Digitalmars-d
mailing list