Ironclad C++

Timon Gehr timon.gehr at gmx.ch
Sun Aug 4 08:04:47 PDT 2013


On 08/04/2013 11:51 AM, Kagamin wrote:
> On Sunday, 4 August 2013 at 02:41:18 UTC, Timon Gehr wrote:
>> D's inout is a somewhat failed attempt
>
> Why?

Off the top of my head:

- No naming or scoping:

// is this ok?
inout(int)* foo(inout(int)* a, inout(int)* delegate(inout(int)*) dg){
     return dg(a);
}

// is this ok?
int b;
const(int) c;
int bar(inout(int)* a, inout(int)* delegate(inout(int)*) dg){
     return *dg(a)+*dg(&b)+*dg(&c);
}

void main(){
     immutable int a;
     // which of those is valid? take your pick.
     assert(foo(&a,(typeof(a)* x)=>x) is a);
     assert(!bar(&a,(inout(int)* x)=>x));
}

(Apparently, currently both crash the compiler in mtype.c:1894.)

Assuming some kind of polymorphic type system allowing at least named 
type constructor parameters, we can express both:

// (details will vary here, eg. if the language is fully dependently 
typed, this concept can likely be expressed within it.)
alias const_immutable_or_mutable TC;

C(int)* foo[TC C](C(int)* a, C(int)* delegate(C(int)*) dg){
     return dg(a);
}

int b;
const(int) c;
int bar[TC A](A(int)* a, B(int)* delegate[TC B](B(int)*) dg){
     return *dg(a)+*dg(&b)+*dg(&c);
}

void main(){
     immutable int a;
     // everything is fine now:
     assert(foo(&a,x=>x) is a);
     assert(!bar(&a,x=>x));
}

(Here [ ] parameters introduce universal quantification: There is only 
one foo function, that works for every such type constructor argument, 
but you cannot find out what that argument was from within the function 
in order to change its behaviour. This is similar to inout except that 
it allows naming and scoping.)



- Only works for parameters or stack based variables:

Tuple!(inout(int)*, inout(int)*) foo(inout(int)* x){
     return tuple(x,x);
}

/usr/include/dmd/phobos/std/typecons.d(363): Error: variable 
std.typecons.Tuple!(inout(int)*,inout(int)*).Tuple._field_field_0 only 
parameters or stack based variables can be inout



- Plain unsoundness of current type checking approach:

The following compiles and runs without errors with DMD:

int* foo(inout(int)* x)@safe{
     inout(int)* screwUp(inout(int)*){ return x; }
     return screwUp((int*).init);
}

void main(){
     immutable x = 123;
     static assert(is(typeof(*&x)==immutable));
     assert(*&x==123);
     immutable(int)* y = &x;
     *foo(y)=456;
     assert(*&x==456);
     assert(x!=*&x); // (!)
}





More information about the Digitalmars-d mailing list