www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 3449] New: const and invariant struct members do not behave according to spec

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449

           Summary: const and invariant struct members do not behave
                    according to spec
           Product: D
           Version: 2.035
          Platform: Other
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: bugzilla kyllingen.net



04:52:34 PDT ---
When struct members are declared const or invariant, they seem to become
manifest constants. Example:

  struct Foo { const int bar = 123; }
  writeln(Foo.sizeof);   // Prints "1", not "4"

  Foo foo;
  auto p = &foo.bar;     // Error: constant 123 is not an lvalue

The same happens if const is replaced with immutable. According to the spec it
should be possible to take the address of const/immutable variables, and in the
case of const it is even considered well-defined behaviour to change their
value after casting them to non-const. I see no reason why this shouldn't apply
to structs as well.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Oct 29 2009
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449


Stewart Gordon <smjg iname.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |smjg iname.com




 and in the case of const it is even considered well-defined 
 behaviour to change their value after casting them to non-const.
What bit of the spec is this? Are you sure you aren't confusing D with C(++)? But the rest of what you say is probably right. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Oct 29 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449




23:35:28 PDT ---


 and in the case of const it is even considered well-defined 
 behaviour to change their value after casting them to non-const.
What bit of the spec is this? Are you sure you aren't confusing D with C(++)?
You're right, I got things mixed up there. :) On the "const and immutable" page there is a section named "Removing Immutable With A Cast", where it says that "The immutable type can be removed with a cast [...] This does not mean, however, that one can change the data". It says nothing about const, which was what led me to believe that changing consts is not illegal, at least. But I see now that the D/C++ comparison table at the bottom of the page has a similar statement for consts. But the rest still stands: It should be possible to take the address of both consts and immutables. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Oct 29 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449







 and in the case of const it is even considered well-defined 
 behaviour to change their value after casting them to non-const.
What bit of the spec is this? Are you sure you aren't confusing D with C(++)?
You're right, I got things mixed up there. :) On the "const and immutable" page there is a section named "Removing Immutable With A Cast", where it says that "The immutable type can be removed with a cast [...] This does not mean, however, that one can change the data". It says nothing about const, which was what led me to believe that changing consts is not illegal, at least.
Since immutable is implicitly convertible to const, it's reasonable that the same rule should apply to const. My guess is that the reason for being able to cast away const/immutable is to interface APIs that take pointers to mutable because they _may_ change the data, but which can be controlled not to. The Windows API function DrawTextEx is an example of this. But I do wish the means of casting away const/immutable were explicit - see http://tinyurl.com/yzzbgdn
 But I see now that the D/C++ comparison table at the bottom of the 
 page has a similar statement for consts.
 
 But the rest still stands: It should be possible to take the 
 address of both consts and immutables.
Agreed. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Oct 30 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449


Lars T. Kyllingstad <bugzilla kyllingen.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Severity|normal                      |major



04:43:38 PDT ---
More strangeness:  If you don't explicitly provide an initial value for
const/immutable members, they do contribute to the size of the struct.

    struct Foo { const int i; }
    writeln(Foo.sizeof); // Prints 4

    struct Bar { const int i = 123; }
    writeln(Bar.sizeof); // Prints 1

I suspect that this bug could cause unexpected memory corruption when such
structs are, for instance, passed to C functions -- especially when the
behaviour depends on such a small detail.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Sep 21 2010
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449


bearophile_hugs eml.cc changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bearophile_hugs eml.cc



This is an important bug. See also the threads:

http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learn&article_id=22540

http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=120910

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 03 2010
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449


yebblies <yebblies gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |patch
                 CC|                            |yebblies gmail.com



https://github.com/D-Programming-Language/dmd/pull/93

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jun 15 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449


Walter Bright <bugzilla digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bugzilla digitalmars.com



00:50:02 PST ---
I believe the correct solution is to make const/immutable fields with
initializers into static members. Without initializers, they are per-instance
fields, and must be initialized by the constructor.

If the user wants manifest constants in a struct/class, use enum.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 24 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449





 I believe the correct solution is to make const/immutable fields with
 initializers into static members.
Changing this would alter the memory layout of the struct, thereby breaking code that interfaces (for example) a C API or a binary file format. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 24 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449




01:37:27 PST ---

 More strangeness:  If you don't explicitly provide an initial value for
 const/immutable members, they do contribute to the size of the struct.
     struct Foo { const int i; }
     writeln(Foo.sizeof); // Prints 4
     struct Bar { const int i = 123; }
     writeln(Bar.sizeof); // Prints 1
This is as designed. A const field without an initializer can be initialized by a constructor. A const field with an initializer does not need any per-instance storage, and becomes a static member.
 I suspect that this bug could cause unexpected memory corruption when such
 structs are, for instance, passed to C functions -- especially when the
 behaviour depends on such a small detail.
It is not a bug, it is as designed. (const in D and C are different, and conflating the two will cause problems anyway) -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 23 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449


Walter Bright <bugzilla digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|spec                        |



01:39:58 PST ---

 When struct members are declared const or invariant, they seem to become
 manifest constants. Example:
   struct Foo { const int bar = 123; }
   writeln(Foo.sizeof);   // Prints "1", not "4"
   Foo foo;
   auto p = &foo.bar;     // Error: constant 123 is not an lvalue
Taking the address should work. Compiler bug, not a spec issue. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 23 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449




---

 This is as designed. A const field without an initializer can be initialized by
 a constructor. A const field with an initializer does not need any per-instance
 storage, and becomes a static member.
 It is not a bug, it is as designed. (const in D and C are different, and
 conflating the two will cause problems anyway)
 Taking the address should work. Compiler bug, not a spec issue.
I think that the *implicit static* variable is the worst specification in D. 'const/immutable(not modifiable)' and 'static(not per-instance)' is definitely orthogonal concepts, but in your argument, they are scary mixed. So, if we want to need static variable, language *must* require 'static' storage class for the purpose. Otherwise, it will force us a big (and meaningless) leap of imaging. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 23 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449





 I think that  the *implicit static* variable is the worst 
 specification in D.  'const/immutable(not modifiable)' and 
 'static(not per-instance)' is definitely orthogonal concepts, but 
 in your argument, they are scary mixed.
Agreed. Half the point of structs is that the layout in memory can be guaranteed. Being able to include immutable values within this memory layout (such as struct size in the case of some Windows API structs, or file format signatures) should be part of this. In classes, where there is no guarantee of memory layout, it makes sense to optimise immutable members to be static. In structs, OTOH, const/immutable should do what it says and nothing more. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 23 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449


Masahiro Nakagawa <repeatedly gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |repeatedly gmail.com



18:30:07 PDT ---
I hit this issue in my new library.

I have a following struct.

  struct Option
  {
    string name;
    string[] fields;
    immutable type = "hoge";
  }

My library automatically converts such struct to JSON.
But "type" field does not exist (tupleof does not return immutable field).

  expect:

  {"fields": ["a'], "unique": false, "type": "hoge"}

  actual:

  {"fields": ["a'], "unique": false}

Currently, I remove immutable keyword temporally but 'type' should be
immutable.

Is there a better solution?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 11 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449


David Piepgrass <qwertie256 gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |qwertie256 gmail.com



PDT ---
+1 from me. Implicit static and (worse) implicit enum are bad ideas, and the
worst part is that whether it's static or not depends on whether there is an
initializer or not. (admittedly I am left wondering what the difference is
between "const int" and "immutable int", is it relevant?)

However, as a compromise, perhaps if the user writes "const int x = 7;" the
compiler could warn: "warning: since x is a constant, it should be declared
with static or enum to avoid wasting memory."

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jul 25 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449





 +1 from me. Implicit static and (worse) implicit enum are bad ideas, and the
 worst part is that whether it's static or not depends on whether there is an
 initializer or not.
I entirely agree.
 (admittedly I am left wondering what the difference is
 between "const int" and "immutable int", is it relevant?)
There isn't any real difference on the surface. But when you take the address of one, you get quite different types.
 However, as a compromise, perhaps if the user writes "const int x = 7;" the
 compiler could warn: "warning: since x is a constant, it should be declared
 with static or enum to avoid wasting memory."
How would the programmer suppress this warning because it's deliberate? Maybe we need a new attribute for this. This would also enable an immutable value to be part of a struct's layout without breaking existing code. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jul 25 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449




PDT ---
 How would the programmer suppress this warning because it's deliberate?
When I wrote that, I was thinking that the developer can initialize in the constructor if he really wants it to be non-static. But now I remember that structs can't have a default constructor. Personally I think coders should be able to suppress warnings inside a pragma. But I think I heard Walter doesn't like that. Nevertheless it could easily be a mistake to use "const int Foo = 7;" instead of "enum" or "static const int", and the developer usually won't find out about the mistake without a warning. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jul 25 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449





 How would the programmer suppress this warning because it's deliberate?
When I wrote that, I was thinking that the developer can initialize in the constructor if he really wants it to be non-static. But now I remember that structs can't have a default constructor.
Indeed. Moreover, being able to set the value just once in the code, in the member declaration, could be used to address the ongoing problem with structs and const-safety by deciding that a struct with a const/immutable member can be reassigned as long as said member's value is a compile-time constant (in the absence of other constraints preventing it).
 Personally I think coders should be able to suppress warnings inside a pragma.
 But I think I heard Walter doesn't like that.
The tradition in C++ has been that typical compiler warnings can be suppressed by making changes at the code level, for example: - code has no effect - comment it out or cast it to void - unreachable code - comment it out - unused parameter - don't name it - implicit narrowing conversions - use an explicit cast - counter-intuitive operator precedence - use brackets It might be that Walter wants to follow this tradition. Or down to problems with the design of D pragmas.
 Nevertheless it could easily be a
 mistake to use "const int Foo = 7;" instead of "enum" or "static const int",
 and the developer usually won't find out about the mistake without a warning.
It could just as easily, if not more, be an attempt to use that declaration thinking it'll actually put that member in the structure's memory layout. An example would be to take a Windows API struct and modify the definition to hard-code that first member that is just the struct's size. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jul 26 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449




Commit pushed to master at https://github.com/D-Programming-Language/phobos

https://github.com/D-Programming-Language/phobos/commit/245274b4083cfc26e45111673b6264151f29abbe


Supplemental fix for Issue 3449 - Stop fwdref by the immutable field

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Nov 22 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449




14:27:45 PST ---
*** Issue 4203 has been marked as a duplicate of this issue. ***

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 26 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449


Andrej Mitrovic <andrej.mitrovich gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |timon.gehr gmx.ch



16:03:42 PST ---
*** Issue 8192 has been marked as a duplicate of this issue. ***

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 26 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449




17:23:46 PST ---
*** Issue 8193 has been marked as a duplicate of this issue. ***

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449




Commits pushed to master at https://github.com/D-Programming-Language/dmd

https://github.com/D-Programming-Language/dmd/commit/78e4dad96beccf795de36302feeb02d733553dc2
fix Issue 3449 - const and invariant struct members do not behave according to
spec

Non manifest-constant aggregate field now have runtime spaces.

https://github.com/D-Programming-Language/dmd/commit/9808f85a876e8cb3435daeb3c97765bbf75ac66a


Issue 3449 - const and invariant struct members do not behave according to spec

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 10 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449


Walter Bright <bugzilla digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Platform|Other                       |All
            Version|2.035                       |D2
         OS/Version|Linux                       |All
           Severity|major                       |enhancement


-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 10 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449


Andrej Mitrovic <andrej.mitrovich gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrej.mitrovich gmail.com



07:32:19 PDT ---
Can this be marked as fixed?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 06 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449


Kenji Hara <k.hara.pg gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |FIXED


-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 12 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449




Commits pushed to master at https://github.com/D-Programming-Language/dmd

https://github.com/D-Programming-Language/dmd/commit/5442ea40a311bf9f76ffdd014bb10e2224c72ee1
Add `-vfield` switch for user code migration by fixing bug 3449

https://github.com/D-Programming-Language/dmd/commit/101120eb4f2fb4c4c83922286fc6057a8e645dca


Add `-vfield` switch for user code migration by fixing bug 3449

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 17 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449




Commit pushed to 2.063 at https://github.com/D-Programming-Language/dmd

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


Add `-vfield` switch for user code migration by fixing bug 3449

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 17 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449


Walter Bright <bugzilla digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|FIXED                       |



14:39:10 PDT ---
Turning this into a warning instead:

https://github.com/D-Programming-Language/dmd/pull/2076

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 25 2013
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=3449


Walter Bright <bugzilla digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|REOPENED                    |RESOLVED
         Resolution|                            |FIXED


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