www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 4251] New: const(T) is appendable to const(T)[]

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

           Summary: const(T) is appendable to const(T)[]
           Product: D
           Version: unspecified
          Platform: Other
        OS/Version: Linux
            Status: NEW
          Severity: major
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: pelle.mansson gmail.com


--- Comment #0 from Pelle Månsson <pelle.mansson gmail.com> 2010-05-30 04:11:17
PDT ---
void messwith(T)(ref const(T)[] ts, const(T) t) {
    ts ~= t;
}

class C {
    int x;
    this(int i) { x = i; }
}

void main(string[] args) {

    C[] cs;
    immutable C ci = new immutable(C)(6);

    assert (ci.x == 6);

    messwith(cs,ci);

    cs[$-1].x = 14;

    assert (ci.x == 14); //whoops.
}

I'm pretty sure you shouldn't be able to do that.

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


nfxjfg gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |nfxjfg gmail.com
            Summary|const(T) is appendable to   |Hole in the const system:
                   |const(T)[]                  |immutable values can be
                   |                            |overwritten (const(T) is
                   |                            |appendable to const(T)[])
           Severity|major                       |blocker


--- Comment #1 from nfxjfg gmail.com 2010-07-13 10:57:33 PDT ---
Isn't this a really really really bad bug in the language specification?

Obviously you shouldn't be able to overwrite immutable values (unless you use
unsafe tricks).

What can be done to fix this hole in the const system?

Just disallowing appending const(T) to const(T)[] isn't really an option, is
it?

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


Steven Schveighoffer <schveiguy yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |schveiguy yahoo.com


--- Comment #2 from Steven Schveighoffer <schveiguy yahoo.com> 2010-07-13
11:54:33 PDT ---
The issue is casting a ref T[] to a ref const(T)[].

The safety is broken if you implicitly apply const two references deep.

I think this is a dup of bug 2095 (which actually is dup of a sub-1000 bug). 
But I think the const implications are somewhat new.  I recall there was either
a discussion on the NG or another bug that covers this.  Maybe someone else can
find it.

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


yebblies <yebblies gmail.com> changed:

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


--- Comment #3 from yebblies <yebblies gmail.com> 2011-06-12 08:14:13 PDT ---
https://github.com/D-Programming-Language/dmd/pull/115

When implicitly converting types with indirections, only allow the following
results:
 completely mutable
 completely non-mutable
 exactly one mutable indirection
 the same number of mutable indirections as before
eg.
 T*** => const(T***)   allowed, full const
 T*** => const(T**)*   allowed, tail const
 T*** => const(T*)**   not allowed
 T*** => const(T)***   not allowed
 T*** => T***          allowed, same number of mutable indirections
 immutable(T*)** => const(T*)** allowed, same number of mutable indirections
etc This prevents (as far as I know) using implicit conversions to let a pointer to mutable and a pointer to immutable point to the same place using const conversions. eg. int** a = [new int].ptr; const(int)*** b = &a; *b = [new immutable(int)].ptr; The same applies to other reference types. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jun 12 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4251


yebblies <yebblies gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |lat7h virginia.edu


--- Comment #4 from yebblies <yebblies gmail.com> 2011-06-15 20:22:49 PDT ---
*** Issue 2544 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: -------
Jun 15 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4251


Stewart Gordon <smjg iname.com> changed:

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


--- Comment #5 from Stewart Gordon <smjg iname.com> 2011-06-16 01:22:22 PDT ---
(In reply to comment #3)
 T*** => const(T***)   allowed, full const
 T*** => const(T**)*   allowed, tail const
 T*** => const(T*)**   not allowed
 T*** => const(T)***   not allowed
 T*** => T***          allowed, same number of mutable indirections
 immutable(T*)** => const(T*)** allowed, same number of mutable indirections
etc
I agree about the first five of these. But I'm not sure if this last one is safe. I'll think about it when I've more time. In any case, see this set of rules I proposed before: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81566 -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jun 16 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4251



--- Comment #6 from yebblies <yebblies gmail.com> 2011-06-16 01:41:07 PDT ---
(In reply to comment #5)
 I agree about the first five of these.  But I'm not sure if this last one is
 safe.  I'll think about it when I've more time.  In any case, see this set of
 rules I proposed before:
 
I haven't been able to think of a way to break it, but that doesn't mean there isn't one!
 http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81566
I did find this today. As far as I can tell, this fix combined with the fix for issue 2095 fixes it all. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jun 16 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4251



--- Comment #7 from Steven Schveighoffer <schveiguy yahoo.com> 2011-06-16
08:06:02 PDT ---
I think the cases are all sound.

In order for there to be a problem, both mutable and immutable data need to be
castable into const.  If you cannot cast mutable into const N references deep,
then you can't accidentally rebind it to immutable data.

This all stems from being able to treat mutable data as const, and also as
mutable at the same time.  Being able to treat immutable data as const and
immutable at the same time does not cause any harm.

This is definitely one of those things that makes my brain hurt... It's like 4
dimensional geometry :)

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



--- Comment #8 from yebblies <yebblies gmail.com> 2011-06-16 08:14:06 PDT ---
(In reply to comment #7)
 This is definitely one of those things that makes my brain hurt... It's like 4
 dimensional geometry :)
I had to draw out tables and diagrams before I could get this right in my mind. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jun 16 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4251



--- Comment #9 from Stewart Gordon <smjg iname.com> 2011-06-16 12:12:23 PDT ---
(In reply to comment #5)
 immutable(T*)** => const(T*)** allowed, same number of mutable indirections
As it turns out, this is unsafe, as the following code shows: ---------- import std.stdio; void main() { immutable(int) i = 42; immutable(int)* ip = &i; immutable(int)** ipp = &ip; const(int)** cpp = ipp; int m = 69; // the next statement makes ip point to a mutable value! *cpp = &m; writefln("%d", *ip); m = 105; writefln("%d", *ip); } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jun 16 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4251


Andrei Alexandrescu <andrei metalanguage.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrei metalanguage.com


--- Comment #10 from Andrei Alexandrescu <andrei metalanguage.com> 2011-06-16
12:23:01 PDT ---
Yah, this has constantly puzzled starting C++ programmers - you can convert
char* to const(char*) but not char** to const(char*)*.

Generally, consider types P (permissive) and N (nonpermissive). Assume both
types have the same structure, so there is no matter of converting
representation. Generally you can't convert the address of a N to the address
of a P even if you can actually convert a N to an P. This is because the
address conversion would allow you subsequent P-specific operations directly
against an N object.

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



--- Comment #11 from Stewart Gordon <smjg iname.com> 2011-06-16 13:18:31 PDT ---
(In reply to comment #10)
 Yah, this has constantly puzzled starting C++ programmers - you can convert
 char* to const(char*) but not char** to const(char*)*.
Do you mean char** to const(char)** ?
 Generally, consider types P (permissive) and N (nonpermissive). Assume both
 types have the same structure, so there is no matter of converting
 representation. Generally you can't convert the address of a N to the address
 of a P even if you can actually convert a N to an P. This is because the
 address conversion would allow you subsequent P-specific operations directly
 against an N object.
Well said. Converting T* (N) to const(T)* (P) is safe. The P-specific operation is rebinding it to an immutable(T). So converting T** to const(T)** is unsafe. Similarly, Converting immutable(T)* (N) to const(T)* (P) is safe. The P-specific operation is rebinding it to a mutable T. So converting immutable(T)** to const(T)** is unsafe. This is the principle that underlies all these proposed rules - whether the indirection is a pointer, dynamic array or other container type, and whether the N->P is a constancy change or a walk up the class hierarchy. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jun 16 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4251



--- Comment #12 from yebblies <yebblies gmail.com> 2011-06-16 20:18:02 PDT ---
(In reply to comment #9)
 (In reply to comment #5)
 immutable(T*)** => const(T*)** allowed, same number of mutable indirections
As it turns out, this is unsafe, as the following code shows:
Good catch! I'll get on it. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jun 16 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4251


yebblies <yebblies gmail.com> changed:

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


--- Comment #13 from yebblies <yebblies gmail.com> 2011-06-22 00:31:47 PDT ---
*** Issue 6190 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: -------
Jun 22 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4251


Brad Roberts <braddr puremagic.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|patch                       |
                 CC|                            |braddr puremagic.com


--- Comment #14 from Brad Roberts <braddr puremagic.com> 2011-08-03 20:16:33
PDT ---
I've removed the patch keyword from this bug since the pull request was
withdrawn.  I don't suppose you've had a chance to fix the issues with the
first version of the patch, have you yebblies?

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



--- Comment #15 from yebblies <yebblies gmail.com> 2011-08-04 13:31:41 EST ---
(In reply to comment #14)
 I've removed the patch keyword from this bug since the pull request was
 withdrawn.  I don't suppose you've had a chance to fix the issues with the
 first version of the patch, have you yebblies?
Unfortunately no. My patch was instantiating templates it shouldn't have, and I haven't had the time lately to fix the template deduction. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Aug 03 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4251


timon.gehr gmx.ch changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |timon.gehr gmx.ch
            Summary|Hole in the const system:   |Hole in the type system:
                   |immutable values can be     |Base type reference can be
                   |overwritten (const(T) is    |assigned to subtype
                   |appendable to const(T)[])   |reference (Super* is
                   |                            |treated as a supertype of
                   |                            |Sub*)


--- Comment #16 from timon.gehr gmx.ch 2011-11-17 11:59:55 PST ---
Class references have the same problem.

class A{}
class B:A{}

void main(){
    B x;
    A* y=&x; // bad!
    *y=new A;
    Object o = x;
    assert(o is x && o && is(typeof(x)==B) && !cast(B)o);
}

I have generalized the title accordingly.

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


Luther Tychonievich <lat7h virginia.edu> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|Hole in the type system:    |Hole in the const system:
                   |Base type reference can be  |immutable values can be
                   |assigned to subtype         |overwritten (const(T) is
                   |reference (Super* is        |appendable to const(T)[])
                   |treated as a supertype of   |
                   |Sub*)                       |


--- Comment #17 from Luther Tychonievich <lat7h virginia.edu> 2011-11-18
05:28:26 PST ---
(In reply to comment #16)
     B x;
     A* y=&x; // bad!
Everything you describe is supposed to happen. "A* y = &x" is the point of inheritance. What exactly is the problem you see in the above? All of your assert elements seem fine too… Reverting title. This bug is about the const safety design of the language, not about inheritance. Even if there is a problem with inheritance, it should be a separate bug unless you can argue they have the same cause. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 18 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4251



--- Comment #18 from Steven Schveighoffer <schveiguy yahoo.com> 2011-11-18
07:10:20 PST ---
(In reply to comment #17)
 (In reply to comment #16)
     B x;
     A* y=&x; // bad!
Everything you describe is supposed to happen. "A* y = &x" is the point of inheritance. What exactly is the problem you see in the above? All of your assert elements seem fine too…
The example isn't illustrative enough. Here's a better example: class A {} class B : A {void foo() {writeln("hello, B");} } void main() { B x; A* y = &x; *y = new A; x.foo(); // boom! Call to invalid vtable entry } As I said in an earlier comment, this bug is really a dup of bug 2095, but it adds a different twist. If we want to consolidate, we should close this as a duplicate of 2095.
 Reverting title. This bug is about the const safety design of the language, not
 about inheritance. Even if there is a problem with inheritance, it should be a
 separate bug unless you can argue they have the same cause.
It's somewhat the same thing. const(T) is really a "base class" of T, since T implicitly casts to const(T), but const(T) doesn't implicitly cast to T. I won't revert the bug description again, because I think this case is already covered in 2095. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 18 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4251


Steven Schveighoffer <schveiguy yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|Hole in the const system:   |Hole in the const system:
                   |immutable values can be     |immutable(T)[] implicitly
                   |overwritten (const(T) is    |casts to ref const(T)[]
                   |appendable to const(T)[])   |


--- Comment #19 from Steven Schveighoffer <schveiguy yahoo.com> 2011-11-18
07:12:53 PST ---
However, I just realized the title is not correct.  So I'll change the title to
reflect the actual problem (const(T) is perfectly legal to append to
const(T)[]).

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



--- Comment #20 from Andrei Alexandrescu <andrei metalanguage.com> 2011-11-18
07:45:55 PST ---
(In reply to comment #19)
 However, I just realized the title is not correct.  So I'll change the title to
 reflect the actual problem (const(T) is perfectly legal to append to
 const(T)[]).
I like Timon's example though, it clarifies quite well a significant problem. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Nov 18 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4251


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

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |patch


--- Comment #21 from Kenji Hara <k.hara.pg gmail.com> 2011-12-12 21:56:04 PST
---
https://github.com/D-Programming-Language/dmd/pull/558

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


Walter Bright <bugzilla digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |bugzilla digitalmars.com
         Resolution|                            |FIXED


--- Comment #22 from Walter Bright <bugzilla digitalmars.com> 2012-01-16
10:38:48 PST ---
https://github.com/D-Programming-Language/dmd/commit/47ad405f25ffefb9781ca9eed89de61025ca82ac

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