Issue 8486 - Possibly wrong interaction of Variant and const arrays
Summary: Possibly wrong interaction of Variant and const arrays
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: phobos (show other issues)
Version: D2
Hardware: All All
: P3 normal
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-07-31 12:36 UTC by cybevnm
Modified: 2024-12-01 16:15 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description cybevnm 2012-07-31 12:36:58 UTC
During initializing Variant, D discards top level const of array, which 
leads to little unintuitive behaviour. Consider code:

import std.stdio;
import std.variant;
void main()
{
  const int[] arr;
  Variant v = Variant( arr );
  writeln( v.peek!( typeof( arr ) )() );
  writeln( v.peek!( const(int)[] )() );
  writeln( v.type() );
}

...and output:
%dmd main.d && ./main.d
null
7FFF358AE298
const(int)[]

As you can see peek works successfully not for original array type, but 
for type without top level const. Is Variant supposed to work in that way ?
Comment 1 David Nadlinger 2012-07-31 13:07:32 UTC
Variant should generally ignore top-level const for »value types« (i.e. array slices, pointers, integral types, …).
Comment 2 David Nadlinger 2012-07-31 13:09:26 UTC
… the point being that this is, if anything, analogous to the constness of the Variant instance itself, not the contained type.
Comment 3 cybevnm 2012-08-01 12:58:14 UTC
(In reply to comment #2)
> … the point being that this is, if anything, analogous to the constness of the
> Variant instance itself, not the contained type.

Unfortunately, Variant's handling of arrays is different to handling of class references. So we have next situtation:

import std.variant;
class C { }
void main()
{
  {
    const C c;
    Variant v = Variant( c );
    assert( v.peek!( typeof(c) )() != null );
  }
  {
    const C[] cs;
    Variant v = Variant( cs );
    assert( v.peek!( typeof(cs) )() == null );
 }
}
But array top-level const cutting is understandable, it's the way it works in all other places...
Comment 4 David Nadlinger 2012-08-01 13:08:10 UTC
I meant that Variant should regard e.g. const(T[]) and const(T)[] or const(T*) and const(T)* equivalent, i.e. allow implicit conversion between them.

The fact that const is automatically stripped from arrays is not Variant-specific, template functions generally work like that in D.
Comment 5 cybevnm 2012-08-01 13:43:19 UTC
(In reply to comment #4)
> I meant that Variant should regard e.g. const(T[]) and const(T)[] or const(T*)
> and const(T)* equivalent, i.e. allow implicit conversion between them.

Agree, it will resolve the problem.
Comment 6 berni44 2019-10-18 12:12:52 UTC
This seems not to be a Phobos bug:

import std.stdio;

void main()
{
    const int[] arr;
    writeln(typeof(arr).stringof);
    Test(arr);
}

struct Test
{
    this(T)(T value)
    {
        writeln(T.stringof);
    }
}

writes:

const(int[])
const(int)[]

For me the question remains: Is this intentional (for reasons I don't understand yet) or a language bug?
Comment 7 David Nadlinger 2019-10-18 12:17:48 UTC
(In reply to berni44 from comment #6)
> For me the question remains: Is this intentional (for reasons I don't
> understand yet) or a language bug?

Removal of "head const", i.e. the outer layer, is intentional. This avoid duplicate template instantiations for code that has identical semantics anyway (like for a const int parameter, where it is copied anyway even if non-const, so from the caller side, there isn't a difference), and allows range functions to work in a natural way with constness (where, again, the slice is copied anyway, so const or not isn't visible to the caller).
Comment 8 berni44 2019-10-18 19:51:14 UTC
(In reply to David Nadlinger from comment #7)
> Removal of "head const", i.e. the outer layer, is intentional.
OK. In that case this is a Phobos bug. The solution would be to make peek remove "head const" on the given type und check if that's the type of the Variant. I've got too few experience on const, so I cannot fix this. I tried to add a small template which returns what it get's (just out of curiosity, if that could work). With this, peek could compare the type of the returned value to the value of the Variant. But this did not work out well. Partly, because the template needs to be given a value and not a type, partly because of inout gets in the way.

I don't know if it's of much use, because this can be easily derived from the post above, but I created this unittest which currently does not pass but a corrected version of peek should pass:

unittest
{
    const int[] arr;
    Variant a = Variant(arr);
    assert(a.peek!(typeof(arr)) !is null);
}
Comment 9 dlangBugzillaToGithub 2024-12-01 16:15:23 UTC
THIS ISSUE HAS BEEN MOVED TO GITHUB

https://github.com/dlang/phobos/issues/9931

DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB