[Issue 6695] typeof(this) does not take into account const/immutable attributes inside member functions

2011-10-06 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6695


Kenji Hara k.hara...@gmail.com changed:

   What|Removed |Added

   Keywords||patch


--- Comment #11 from Kenji Hara k.hara...@gmail.com 2011-10-06 00:04:33 PDT 
---
https://github.com/D-Programming-Language/dmd/pull/434

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
--- You are receiving this mail because: ---


[Issue 6695] typeof(this) does not take into account const/immutable attributes inside member functions

2011-10-06 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6695


Walter Bright bugzi...@digitalmars.com changed:

   What|Removed |Added

 Status|NEW |RESOLVED
 CC||bugzi...@digitalmars.com
 Resolution||FIXED


--- Comment #12 from Walter Bright bugzi...@digitalmars.com 2011-10-06 
02:25:32 PDT ---
https://github.com/D-Programming-Language/dmd/commit/48ad063f127d3b150f4f1ed5cb4b27ff18d9b6fe

https://github.com/D-Programming-Language/dmd/commit/451dbb73e356e3cf530cfc11e1b5094bc2b823af

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
--- You are receiving this mail because: ---


[Issue 6695] typeof(this) does not take into account const/immutable attributes inside member functions

2011-09-20 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6695


Steven Schveighoffer schvei...@yahoo.com changed:

   What|Removed |Added

 CC||schvei...@yahoo.com
Version|unspecified |D2
Summary|immutable not inherited by  |typeof(this) does not take
   |members |into account
   ||const/immutable attributes
   ||inside member functions


--- Comment #1 from Steven Schveighoffer schvei...@yahoo.com 2011-09-20 
05:53:59 PDT ---
This is only a problem with the expression typeof(this), the real reference
'this' actually *is* immutable:

simplified example:

import std.stdio;

struct b {
   void c () immutable {
  writeln(typeid(typeof(this))); // b
  auto x = this;
  writeln(typeid(typeof(x))); // immutable(b)
   }
}

void main()
{
   immutable b b1;
   b1.c();
}

However, if you tried to change a member of b, you will get a compiler error. 
So the type of the this reference inside c() is not simply b, it really is
immutable(b).

However, typeof(this) is a special expression that the compiler replaces with
the actual type of the struct (i.e. struct b).

This is so it can be used in static functions and at a declaration level.  See
the special cases here:
http://www.d-programming-language.org/declaration.html#Typeof

However, I think it is extremely unintuitive to make that happen inside a
member function as well.  I'm not sure if this is an enhancement, it's not
exactly clear from the spec that typeof(this) should still be a special case
*inside* a member function.  It says it should be the same as if it were inside
a member function, it doesn't say *what kind* of member function.

At the very least, this is a doc bug.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
--- You are receiving this mail because: ---


[Issue 6695] typeof(this) does not take into account const/immutable attributes inside member functions

2011-09-20 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6695



--- Comment #2 from luka8088 luka8...@owave.net 2011-09-20 08:19:42 PDT ---
The actual problem is:


import std.stdio;

immutable struct a {
  b b1;
}

struct b {
  /*
void c () { }
  case 1 = Error: function b.c () is not callable using argument types ()
immutable
void c () immutable { }
 case 2 = Error: function b.c () immutable is not callable using argument
types ()
  */
  void c () { }
}
void main () {

  a a1;
  b b1;

  a1.b1.c(); // case 1
  b1.c();// case 2

}



Lets say there is a struct b that can be independent and is mutable. On the
other hand we have struct a that has b immutable, by some reason immutable is
not inherited by void c () { }, so by trying to call a1.b1.c(); compiler throws
Error: function b.c () is not callable using argument types () immutable

I also tried a work-around by making void c () immutable { }, but then
independent usage of b throws Error: function b.c () immutable is not callable
using argument types ()


The reason for trying typeof(this) is I was trying to make two functions:
  void c () if (is(typeof(this) == b)) { }
  void c () if (is(typeof(this) == immutable(b))) immutable { }
but since typeof(this) does not indicate immutable I found no work-around.

Until this is resolved, is there any work-around for this situation... or am I
doing something wrong ?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
--- You are receiving this mail because: ---


[Issue 6695] typeof(this) does not take into account const/immutable attributes inside member functions

2011-09-20 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6695



--- Comment #3 from Steven Schveighoffer schvei...@yahoo.com 2011-09-20 
08:47:22 PDT ---
void c() const {}

This should work, as mutable and const implicitly cast to immutable.

Two other things (even though the above is the *right* solution to your
problem):

1. You can overload c, you don't need to use a template
2. You *can* get the exact type called with by using a this template parameter:

import std.stdio;

struct b
{
void c(this T)() const
{
writeln(typeid(T));
}
}

void main()
{
immutable b b1;
b b2;
b1.c();
b2.c();
}

output:

immutable(testimmutable.b)
testimmutable.b

But please note, the struct a has nothing to do with these issues, it's just
simply a way you have declared an immutable b (which you can easily do on the
stack).

Declaring an immutable struct is the same as applying immutable to all the
members.  Declaring a local immutable variable is the same thing.

Also note that in your attempt to use if constraints, you must use templates
(I'm sure you would have gotten error messages, so I think this is a simple
copy-paste omission)

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
--- You are receiving this mail because: ---


[Issue 6695] typeof(this) does not take into account const/immutable attributes inside member functions

2011-09-20 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6695



--- Comment #4 from Steven Schveighoffer schvei...@yahoo.com 2011-09-20 
08:48:52 PDT ---
(In reply to comment #3)
 void c() const {}
 
 This should work, as mutable and const implicitly cast to immutable.

Oh my, that was completely off.  Should have read:

This should work, as mutable and immutable implicitly cast to const.

Sorry...

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
--- You are receiving this mail because: ---


[Issue 6695] typeof(this) does not take into account const/immutable attributes inside member functions

2011-09-20 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6695



--- Comment #5 from luka8088 luka8...@owave.net 2011-09-20 09:13:20 PDT ---
(In reply to comment #3)
 void c() const {}
 
 This should work, as mutable and const implicitly cast to immutable.


yes, it works, thx !


 Declaring an immutable struct is the same as applying immutable to all the
 members.  Declaring a local immutable variable is the same thing.
 

so this is a bug or not ... ?

// Error: function b.c () is not callable using argument types () immutable

import std.stdio;

immutable struct a {
  b b1;
}

struct b {
  void c () { }
}

void main () {
  a a1;
  a1.b1.c();
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
--- You are receiving this mail because: ---


[Issue 6695] typeof(this) does not take into account const/immutable attributes inside member functions

2011-09-20 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6695



--- Comment #6 from Steven Schveighoffer schvei...@yahoo.com 2011-09-20 
10:26:54 PDT ---
(In reply to comment #5)
 so this is a bug or not ... ?
 
 // Error: function b.c () is not callable using argument types () immutable
 
 import std.stdio;
 
 immutable struct a {
   b b1;
 }
 
 struct b {
   void c () { }
 }
 
 void main () {
   a a1;
   a1.b1.c();
 }

Not a bug.  Inside the c function, 'this' is mutable, and you are trying to
pass an immutable struct as the 'this' parameter.  Immutable cannot implicitly
cast to mutable, so it fails to compile.

You should read up on the spec documentation about const and immutable, it will
help to understand it.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
--- You are receiving this mail because: ---


[Issue 6695] typeof(this) does not take into account const/immutable attributes inside member functions

2011-09-20 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6695



--- Comment #7 from luka8088 luka8...@owave.net 2011-09-20 10:59:37 PDT ---
(In reply to comment #6)
 (In reply to comment #5)
  so this is a bug or not ... ?
  
  // Error: function b.c () is not callable using argument types () immutable
  
  import std.stdio;
  
  immutable struct a {
b b1;
  }
  
  struct b {
void c () { }
  }
  
  void main () {
a a1;
a1.b1.c();
  }
 
 Not a bug.  Inside the c function, 'this' is mutable, and you are trying to
 pass an immutable struct as the 'this' parameter.  Immutable cannot implicitly
 cast to mutable, so it fails to compile.
 
 You should read up on the spec documentation about const and immutable, it 
 will
 help to understand it.

I agree that maybe this is not a bug, but I don't agree with the explanation
... 

Documentation says Both immutable and const are transitive, which means that
any data reachable through an immutable reference is also immutable, and
likewise for const.

So in this example:

import std.stdio;

immutable struct a {
  b b1;
}

struct b {
  immutable void  c  () { }
  voidd  () { }
  immutable int   e  ;
  int f  ;
}
void main () {
  a a1;
  b b1;

  writeln(   b1.c  , typeid(typeof(b1.c))); // immutable(void())
  writeln(   b1.d  , typeid(typeof(b1.d))); // void()
  writeln(   b1.e  , typeid(typeof(b1.e))); // immutable(int)
  writeln(   b1.f  , typeid(typeof(b1.f))); // int

  writeln(a1.b1.c  , typeid(typeof(a1.b1.c)));  // immutable(void())
  writeln(a1.b1.d  , typeid(typeof(a1.b1.d)));  // void()
  writeln(a1.b1.e  , typeid(typeof(a1.b1.e)));  // immutable(int)
  writeln(a1.b1.f  , typeid(typeof(a1.b1.f)));  // immutable(int)

}


From the documentation, both
  typeid(typeof(a1.b1.d))
and
  typeid(typeof(a1.b1.f))
should be either mutable or immutable, right ?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
--- You are receiving this mail because: ---


[Issue 6695] typeof(this) does not take into account const/immutable attributes inside member functions

2011-09-20 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6695



--- Comment #8 from Steven Schveighoffer schvei...@yahoo.com 2011-09-20 
11:42:19 PDT ---
(In reply to comment #7)
 I agree that maybe this is not a bug, but I don't agree with the explanation
 ... 
 
 Documentation says Both immutable and const are transitive, which means that
 any data reachable through an immutable reference is also immutable, and
 likewise for const.

Note the key element here is *data*, not *functions*.

 So in this example:

[snip]

 From the documentation, both
   typeid(typeof(a1.b1.d))
 and
   typeid(typeof(a1.b1.f))
 should be either mutable or immutable, right ?

typeid(typeof(a1.b1.d)) is a method, not a piece of data.  In fact, when you
say typeof(a1.b1.d), you might as well have written typeof(b.d).

There is a confusing concept to grasp, and it's made harder because of the
terminology.  An immutable function is not actually immutable.  An immutable
function is a member function that *can be called* on an immutable instance of
the struct/class.  The immutable modifier only affects the 'this' pointer, even
though it seems like it's applied to the entire function.

Remember that all member functions have a hidden this pointer?  If we were
forced to write them out, then this:

struct S
{
   void foo () immutable {}
   void foo2() const {}
   void foo3()   {}
}

becomes this:

struct S
{
   void foo (ref immutable(S) this) {}
   void foo2(ref const(S) this) {}
   void foo3(ref   S  this) {}
}

Now you can see why its clear you cannot call for instance foo with a
non-immutable instance of S.  The reason the modifiers are applied to the
function is because there's no parameter for them to cling to -- the parameter
is hidden.

If you want to discuss this more, I think the d.learn newsgroup is probably
best, or you can email me directly.  I'd be happy to answer any questions on
it.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
--- You are receiving this mail because: ---


[Issue 6695] typeof(this) does not take into account const/immutable attributes inside member functions

2011-09-20 Thread d-bugmail
http://d.puremagic.com/issues/show_bug.cgi?id=6695



--- Comment #9 from luka8088 luka8...@owave.net 2011-09-20 12:16:01 PDT ---
(In reply to comment #8)
 (In reply to comment #7)
  I agree that maybe this is not a bug, but I don't agree with the explanation
  ... 
  
  Documentation says Both immutable and const are transitive, which means 
  that
  any data reachable through an immutable reference is also immutable, and
  likewise for const.
 
 Note the key element here is *data*, not *functions*.
 
  So in this example:
 
 [snip]
 
  From the documentation, both
typeid(typeof(a1.b1.d))
  and
typeid(typeof(a1.b1.f))
  should be either mutable or immutable, right ?
 
 typeid(typeof(a1.b1.d)) is a method, not a piece of data.  In fact, when you
 say typeof(a1.b1.d), you might as well have written typeof(b.d).
 
 There is a confusing concept to grasp, and it's made harder because of the
 terminology.  An immutable function is not actually immutable.  An immutable
 function is a member function that *can be called* on an immutable instance of
 the struct/class.  The immutable modifier only affects the 'this' pointer, 
 even
 though it seems like it's applied to the entire function.
 
 Remember that all member functions have a hidden this pointer?  If we were
 forced to write them out, then this:
 
 struct S
 {
void foo () immutable {}
void foo2() const {}
void foo3()   {}
 }
 
 becomes this:
 
 struct S
 {
void foo (ref immutable(S) this) {}
void foo2(ref const(S) this) {}
void foo3(ref   S  this) {}
 }
 
 Now you can see why its clear you cannot call for instance foo with a
 non-immutable instance of S.  The reason the modifiers are applied to the
 function is because there's no parameter for them to cling to -- the parameter
 is hidden.
 
 If you want to discuss this more, I think the d.learn newsgroup is probably
 best, or you can email me directly.  I'd be happy to answer any questions on
 it.

OK, I understand it now, you are right, thank you very much for detailed
explanation !

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
--- You are receiving this mail because: ---