www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 9186] New: Manifest constant can violate const correctness restrictions when empty

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

           Summary: Manifest constant can violate const correctness
                    restrictions when empty
           Product: D
           Version: unspecified
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: major
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: monarchdodra gmail.com



The basic use case is having:
foo(const(char)[]);
and trying to pass a
immutable(char)[] to it. Which is illegal.

The problem here is that if you define a manifest constant that is empty, and
try to pass it to foo, the code will compile:

//----
void main()
{
    void foo(const(char)[][]);
    alias Type = string[];
    static assert(is(typeof(Type.init) == Type));
    static if (is(typeof(foo(Type.init)))) //Enter here !!!
    {
        Type Rbla()  property;
        Type Lbla;
        enum Type Ebla1 = [[]];
        enum Type Ebla2 = ["hello"];
        foo(Type.init); //OK!
        foo(Rbla);
        foo(Lbla);
        foo(Ebla1); //OK!
        foo(Ebla2);
    }
}
//----
Error: function dmd2.main.foo (const(char)[][]) is not callable using argument
types (string[])
Error: cannot implicitly convert expression (Rbla()) of type string[] to
const(char)[][]
Error: function dmd2.main.foo (const(char)[][]) is not callable using argument
types (string[])
Error: cannot implicitly convert expression (Lbla) of type string[] to
const(char)[][]
//----

This may not seem like a "huge" problem in and out of itself. The *REAL*
problem lies in the static if:
"static if (is(typeof(foo(Type.init))))"
This code is explicitly written to find out if we can pass a variable of type
Type to foo. This is especially true for array types, which are the ones
vulnerable to this problem.

I'm marking as "Major", because phobos is vulnerable to the bug.

Found inside "put":
//----
else static if (is(typeof(r.put((E[]).init))))
{
    r((&e)[0..1]);
}
//----
src\phobos\std\range.d(590): Error: cannot implicitly convert expression (&
e[0u..1u]) of type string[] to const(char)[][]
//----

Current workaround is to use an lvalueof type function.

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


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

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



07:12:53 PST ---

 The basic use case is having:
 foo(const(char)[]);
 and trying to pass a
 immutable(char)[] to it. Which is illegal.
Since when is that illegal? immutable and mutable both implicitly convert to const. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 19 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9186






 The basic use case is having:
 foo(const(char)[]);
 and trying to pass a
 immutable(char)[] to it. Which is illegal.
Since when is that illegal? immutable and mutable both implicitly convert to const.
Typo. My apologies:
 The basic use case is having:
 foo(const(char)[][]);
 and trying to pass a
 "immutable(char)[][]" to it. Which is illegal.
-- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 19 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9186




This is not a type system problem.

All manifest constants, which declared by `enum` and T.init, make literal
expressions in the places where they used.

alias T = string[];
enum T strs = [[]];
foo(T.init);  // same as foo(null);
foo(strs);    // same as foo([[]]);

And, empty array literal and null literal can ignore their type qualifiers in
constant-folding process, because they have no references to qualified values.

(From the view of compiler development, it is mainly designed by
Expression::implicitConvTo.)

I can agree that the behavior is not intuitive, but I'm not sure what is the
correct behavior...

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


Max Samukha <samukha voliacable.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |samukha voliacable.com



PST ---


 I'm not sure what is the correct behavior...
Obviously, the correct behavior is to preserve the type information. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 21 2012
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9186





 This is not a type system problem.
 
 All manifest constants, which declared by `enum` and T.init, make literal
 expressions in the places where they used.
 
 alias T = string[];
 enum T strs = [[]];
 foo(T.init);  // same as foo(null);
 foo(strs);    // same as foo([[]]);
 
 And, empty array literal and null literal can ignore their type qualifiers in
 constant-folding process, because they have no references to qualified values.
I see your point, but I argue there is a difference between a "type-less" literal and an "empty" literal. (T[]).init, while empty, does carry a type, and it should be preserved/propagated. Heck, proof that a non-empty literal can have "no type": "[[]]" is *not* empty. It is a type-less slice which carries a single empty typeless slice. Yet you can still write "int[][] a = [[]];" -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 21 2012