On 2009-12-15 22:02:59 -0500, Andrei Alexandrescu <seewebsiteforem...@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.for...@michelf.com
http://michelf.com/

Reply via email to