View mode: basic / threaded / horizontal-split · Log in · Help
December 28, 2009
the const correctness of the this pointer
Hello, 
I was dealing with delegates when I found that the const correctness of the this pointer was 'lost' when accessing a member function of a class through a temporary delegate. 

Here is an example:

class A{
   void f () {}
}

const A a = new A;
a.f() //error, this is normal.
auto g = &a.f;
g(); //no error. Is this normal ?

I may be wrong, but it seems to me that as the const property of the this pointer is linked to the instance of the class (here 'a'), the delegate 'g' should contain a const pointer to A (because 'a' is const).

More generally, I seems that there is no management of the const correctness of the frame pointer of a delegate in D2

What about adding the const keyword for delegates, as we do for methods ? The const property of the delegate's frame pointer would be part of its type.

Example: 

void f()
{
   int x;
   void g() const {
       x ++; //would produce an error since the type of g is [void delegate() const]
  }
}


Any thoughts about this ?
December 28, 2009
Re: the const correctness of the this pointer
TM Wrote:

> Hello, 
> I was dealing with delegates when I found that the const correctness of the this pointer was 'lost' when accessing a member function of a class through a temporary delegate. 
> 
> Here is an example:
> 
> class A{
>     void f () {}
> }
> 
> const A a = new A;
> a.f() //error, this is normal.
> auto g = &a.f;
> g(); //no error. Is this normal ?
> 
> I may be wrong, but it seems to me that as the const property of the this pointer is linked to the instance of the class (here 'a'), the delegate 'g' should contain a const pointer to A (because 'a' is const).


Looks like something that should be entered into bugzilla
December 28, 2009
Re: the const correctness of the this pointer
On Sun, 27 Dec 2009 19:02:23 -0500, TM <ithink@therefore.iam> wrote:

> Hello,
> I was dealing with delegates when I found that the const correctness of  
> the this pointer was 'lost' when accessing a member function of a class  
> through a temporary delegate.
>
> Here is an example:
>
> class A{
>     void f () {}
> }
>
> const A a = new A;
> a.f() //error, this is normal.
> auto g = &a.f;
> g(); //no error. Is this normal ?
>
> I may be wrong, but it seems to me that as the const property of the  
> this pointer is linked to the instance of the class (here 'a'), the  
> delegate 'g' should contain a const pointer to A (because 'a' is const).
>
> More generally, I seems that there is no management of the const  
> correctness of the frame pointer of a delegate in D2
>
> What about adding the const keyword for delegates, as we do for methods  
> ? The const property of the delegate's frame pointer would be part of  
> its type.
>
> Example:
>
> void f()
> {
>     int x;
>     void g() const {
>         x ++; //would produce an error since the type of g is [void  
> delegate() const]
>    }
> }
>
> Any thoughts about this ?

This might be a difficult thing to fix, but it definitely *definitely*  
needs to be fixed.  The problem is that a delegate stores a function  
pointer and a context pointer.  However, it does not type the context  
pointer.  For example, if you do this:

import std.stdio;

class A
{
    void f() const {}
}

void main()
{
    const A a = new A;
    a.f();
    auto g = &a.f;
    writefln("%s", typeof(g).stringof);
}

You will get this:

void delegate()

The this pointer is hidden, and so is it's const decoration.  I would  
expect to see:

void delegate() const

I'll file a bugzilla request for this.

-Steve
December 28, 2009
Re: the const correctness of the this pointer
Steven Schveighoffer Wrote:

> 
> This might be a difficult thing to fix, but it definitely *definitely*  
> needs to be fixed.  The problem is that a delegate stores a function  
> pointer and a context pointer.  However, it does not type the context  
> pointer.  For example, if you do this:
> 
> import std.stdio;
> 
> class A
> {
>      void f() const {}
> }
> 
> void main()
> {
>      const A a = new A;
>      a.f();
>      auto g = &a.f;
>      writefln("%s", typeof(g).stringof);
> }
> 
> You will get this:
> 
> void delegate()
> 
> The this pointer is hidden, and so is it's const decoration.  I would  
> expect to see:
> 
> void delegate() const
> 
> I'll file a bugzilla request for this.
> 
> -Steve


I disagree. Once the delegate is passed off to some other region of code, why should that other code care that there's an object that might not get modified from using the delegate? Especially when you consider that which object or stack frame is not tracked by the type system. Pure delegates make sense to me though.
December 28, 2009
Re: the const correctness of the this pointer
On Mon, 28 Dec 2009 10:50:02 -0500, Jason House  
<jason.james.house@gmail.com> wrote:

> Steven Schveighoffer Wrote:
>
>>
>> This might be a difficult thing to fix, but it definitely *definitely*
>> needs to be fixed.  The problem is that a delegate stores a function
>> pointer and a context pointer.  However, it does not type the context
>> pointer.  For example, if you do this:
>>
>> import std.stdio;
>>
>> class A
>> {
>>      void f() const {}
>> }
>>
>> void main()
>> {
>>      const A a = new A;
>>      a.f();
>>      auto g = &a.f;
>>      writefln("%s", typeof(g).stringof);
>> }
>>
>> You will get this:
>>
>> void delegate()
>>
>> The this pointer is hidden, and so is it's const decoration.  I would
>> expect to see:
>>
>> void delegate() const
>>
>> I'll file a bugzilla request for this.
>>
>> -Steve
>
>
> I disagree. Once the delegate is passed off to some other region of  
> code, why should that other code care that there's an object that might  
> not get modified from using the delegate? Especially when you consider  
> that which object or stack frame is not tracked by the type system. Pure  
> delegates make sense to me though.

It could be part of the interface for a function that takes a delegate  
(i.e. I require that this delegate does not modify it's 'this' parameter).

But I agree, there could be issues -- if you don't care what the delegate  
does (const or not), then how do you specify that?

I suppose we need delegate contravariance at that point -- a delegate to a  
const function should implicitly casts to a delegate of a non-const  
function.  See http://d.puremagic.com/issues/show_bug.cgi?id=3075

This might be a good reason to revive that enhancement.

BTW, you also need to correctly mark shared functions, which *do* matter  
as far as delegates go, since you need to synchronize access to the 'this'  
pointer before calling the delegate.

-Steve
December 28, 2009
Re: the const correctness of the this pointer
Jason House Wrote:

> Steven Schveighoffer Wrote:
> 
> > 
> > This might be a difficult thing to fix, but it definitely *definitely*  
> > needs to be fixed.  The problem is that a delegate stores a function  
> > pointer and a context pointer.  However, it does not type the context  
> > pointer.  For example, if you do this:
> > 
> > import std.stdio;
> > 
> > class A
> > {
> >      void f() const {}
> > }
> > 
> > void main()
> > {
> >      const A a = new A;
> >      a.f();
> >      auto g = &a.f;
> >      writefln("%s", typeof(g).stringof);
> > }
> > 
> > You will get this:
> > 
> > void delegate()
> > 
> > The this pointer is hidden, and so is it's const decoration.  I would  
> > expect to see:
> > 
> > void delegate() const
> > 
> > I'll file a bugzilla request for this.
> > 
> > -Steve
> 
> 
> I disagree. Once the delegate is passed off to some other region of code, why should that other code care that there's an object that might not get modified from using the delegate? Especially when you consider that which object or stack frame is not tracked by the type system. Pure delegates make sense to me though.


I disagree with you. To me, the loss of the frame pointer's const attribute looks like a cast. I do not expect to be allowed to call the above 'a.f' wihout casting a into a const A. And yet it is possible by using a delegate, which I think performs a hidden cast operation.

I think Steven Schveighoffer is right. Moreover the const correctness of the this pointer is well managed as far as objects are concerned, so why not have the same behaviour with delegate ?
December 28, 2009
Re: the const correctness of the this pointer
On Mon, 28 Dec 2009 03:02:23 +0300, TM <ithink@therefore.iam> wrote:

> Hello,
> I was dealing with delegates when I found that the const correctness of  
> the this pointer was 'lost' when accessing a member function of a class  
> through a temporary delegate.
>
> Here is an example:
>
> class A{
>     void f () {}
> }
>
> const A a = new A;
> a.f() //error, this is normal.
> auto g = &a.f;
> g(); //no error. Is this normal ?
>
> I may be wrong, but it seems to me that as the const property of the  
> this pointer is linked to the instance of the class (here 'a'), the  
> delegate 'g' should contain a const pointer to A (because 'a' is const).
>
> More generally, I seems that there is no management of the const  
> correctness of the frame pointer of a delegate in D2
>
> What about adding the const keyword for delegates, as we do for methods  
> ? The const property of the delegate's frame pointer would be part of  
> its type.
>
> Example:
>
> void f()
> {
>     int x;
>     void g() const {
>         x ++; //would produce an error since the type of g is [void  
> delegate() const]
>    }
> }
>
> Any thoughts about this ?

It shouldn't compile: it makes no sense to can't non-const method through  
const reference, and the same applies to shared. OTOH, the following  
should just work:

class A {
    void constMethod() const {}
    void sharedMethod() shared {}
}

const A a1 = new A();
void delegate() const dg1 = &a1.constMethod;

shared A a2 = new shared A();
void delegate() shared dg2 = &a2.sharedMethod();

(in examples above, const and shared attributes are applied to both  
function pointer and frame pointer)

I already wrote about a necessity of introduction of "shared delegates" in  
a separate thread. Until then, Thread creation is broken in D.
December 28, 2009
Re: the const correctness of the this pointer
TM Wrote:

> Jason House Wrote:
> 
> > Steven Schveighoffer Wrote:
> > 
> > > 
> > > This might be a difficult thing to fix, but it definitely *definitely*  
> > > needs to be fixed.  The problem is that a delegate stores a function  
> > > pointer and a context pointer.  However, it does not type the context  
> > > pointer.  For example, if you do this:
> > > 
> > > import std.stdio;
> > > 
> > > class A
> > > {
> > >      void f() const {}
> > > }
> > > 
> > > void main()
> > > {
> > >      const A a = new A;
> > >      a.f();
> > >      auto g = &a.f;
> > >      writefln("%s", typeof(g).stringof);
> > > }
> > > 
> > > You will get this:
> > > 
> > > void delegate()
> > > 
> > > The this pointer is hidden, and so is it's const decoration.  I would  
> > > expect to see:
> > > 
> > > void delegate() const
> > > 
> > > I'll file a bugzilla request for this.
> > > 
> > > -Steve
> > 
> > 
> > I disagree. Once the delegate is passed off to some other region of code, why should that other code care that there's an object that might not get modified from using the delegate? Especially when you consider that which object or stack frame is not tracked by the type system. Pure delegates make sense to me though.
> 
> 
> I disagree with you. To me, the loss of the frame pointer's const attribute looks like a cast. 

The quoted code (by Steve) above is not the same as yours. Both the variable and the called member are const. Invoking the delegate does not violate the const system. I did respond to your original example saying to file a bugzilla entry.



> I do not expect to be allowed to call the above 'a.f' wihout casting a into a const A. And yet it is possible by using a delegate, which I think performs a hidden cast operation.
> 

Calling a const member function is allowed without casting from either thread-local mutable data or immutable data. Calling a non-const member function on a const object is what's illegal. That's what your original sample did. Constructing such a delegate (without casts) should be illegal and is a bug in dmd.

Once a const-correct delegate is created, it should be usable like any other delegate.
December 28, 2009
Re: the const correctness of the this pointer
Am 28.12.2009 18:44, schrieb Denis Koroskin:
> On Mon, 28 Dec 2009 03:02:23 +0300, TM <ithink@therefore.iam> wrote:
>
>> Hello,
>> I was dealing with delegates when I found that the const correctness
>> of the this pointer was 'lost' when accessing a member function of a
>> class through a temporary delegate.
>>
>> Here is an example:
>>
>> class A{
>> void f () {}
>> }
>>
>> const A a = new A;
>> a.f() //error, this is normal.
>> auto g = &a.f;
>> g(); //no error. Is this normal ?
>>
>> I may be wrong, but it seems to me that as the const property of the
>> this pointer is linked to the instance of the class (here 'a'), the
>> delegate 'g' should contain a const pointer to A (because 'a' is const).
>>
>> More generally, I seems that there is no management of the const
>> correctness of the frame pointer of a delegate in D2
>>
>> What about adding the const keyword for delegates, as we do for
>> methods ? The const property of the delegate's frame pointer would be
>> part of its type.
>>
>> Example:
>>
>> void f()
>> {
>> int x;
>> void g() const {
>> x ++; //would produce an error since the type of g is [void delegate()
>> const]
>> }
>> }
>>
>> Any thoughts about this ?
>
> It shouldn't compile: it makes no sense to can't non-const method
> through const reference, and the same applies to shared. OTOH, the
> following should just work:
>
> class A {
> void constMethod() const {}
> void sharedMethod() shared {}
> }
>
> const A a1 = new A();
> void delegate() const dg1 = &a1.constMethod;
>
> shared A a2 = new shared A();
> void delegate() shared dg2 = &a2.sharedMethod();
>
> (in examples above, const and shared attributes are applied to both
> function pointer and frame pointer)
>
> I already wrote about a necessity of introduction of "shared delegates"
> in a separate thread. Until then, Thread creation is broken in D.

Actually in both cases the error is not happening when the delegate is 
called but at the point where the delegate is created. _Creating_ a 
delegate to a non-const function should simply be impossible when a 
const object is bound (result in a compile time error). Similarily, for 
a shared object, the necessary synchronization code should be added to 
the delegate instead of having the shared attribute attached to the 
delegate.

Typing the delegate will just create superfluous type combinations and 
complicate delegate usage - additionally it would be strange in the 
sense that it makes assumptions about the type of the "context pointer" 
without knowing what it is (object, stack frame, struct, ...).

Sönke
December 28, 2009
Re: the const correctness of the this pointer
Jason House Wrote:

> TM Wrote:
> 
> > Jason House Wrote:
> > 
> > > Steven Schveighoffer Wrote:
> > > 
> > > > 
> > > > This might be a difficult thing to fix, but it definitely *definitely*  
> > > > needs to be fixed.  The problem is that a delegate stores a function  
> > > > pointer and a context pointer.  However, it does not type the context  
> > > > pointer.  For example, if you do this:
> > > > 
> > > > import std.stdio;
> > > > 
> > > > class A
> > > > {
> > > >      void f() const {}
> > > > }
> > > > 
> > > > void main()
> > > > {
> > > >      const A a = new A;
> > > >      a.f();
> > > >      auto g = &a.f;
> > > >      writefln("%s", typeof(g).stringof);
> > > > }
> > > > 
> > > > You will get this:
> > > > 
> > > > void delegate()
> > > > 
> > > > The this pointer is hidden, and so is it's const decoration.  I would  
> > > > expect to see:
> > > > 
> > > > void delegate() const
> > > > 
> > > > I'll file a bugzilla request for this.
> > > > 
> > > > -Steve
> > > 
> > > 
> > > I disagree. Once the delegate is passed off to some other region of code, why should that other code care that there's an object that might not get modified from using the delegate? Especially when you consider that which object or stack frame is not tracked by the type system. Pure delegates make sense to me though.
> > 
> > 
> > I disagree with you. To me, the loss of the frame pointer's const attribute looks like a cast. 
> 
> The quoted code (by Steve) above is not the same as yours. Both the variable and the called member are const. Invoking the delegate does not violate the const system. I did respond to your original example saying to file a bugzilla entry.
>  
> 
> 
> > I do not expect to be allowed to call the above 'a.f' wihout casting a into a const A. And yet it is possible by using a delegate, which I think performs a hidden cast operation.
> > 
> 
> Calling a const member function is allowed without casting from either thread-local mutable data or immutable data. Calling a non-const member function on a const object is what's illegal. That's what your original sample did. Constructing such a delegate (without casts) should be illegal and is a bug in dmd.
> 
> Once a const-correct delegate is created, it should be usable like any other delegate.

I totally agree that the problem is the conversion of a [ void delegate() const] to a [void delegate()]. 
I totally agree that we should be allowed to call the const-correct delegate once it has been created.

ie, this should be correct:

void delegate() g = cast ( void delegate() ) (f); //here a cast would be necessary
g(); //This would be OK, of course

Concerning the bugzilla, the problem is that adding the 'const' and 'share' properties of the frame pointer as a part of the delegate's type is more like a new feature than a compiler bug, isn't it ?
On the other hand, it looks like we all agree to say this is a must have feature. Do wee ?
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home