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