D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 3567 - std.traits: Unqual strips qualifiers on structs with references that would break const/immutable.
Summary: std.traits: Unqual strips qualifiers on structs with references that would br...
Status: REOPENED
Alias: None
Product: D
Classification: Unclassified
Component: phobos (show other issues)
Version: D2
Hardware: All All
: P2 major
Assignee: No Owner
URL:
Keywords: safe
: 8338 (view as issue list)
Depends on:
Blocks:
 
Reported: 2009-12-02 12:35 UTC by Luther Tychonievich
Modified: 2024-12-01 16:13 UTC (History)
5 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Luther Tychonievich 2009-12-02 12:35:58 UTC
Phobos' traits.d's Unqual! template (needed for several of its other templates) does not handle arrays well:

writeln(Unqual!(const(int[])).stringof); // writes const(int)[] not int[]

Adding the following near line 1188 of traits.d solves this problem:

template Unqual(T : U[], U) { alias U[] Unqual; }
Comment 1 David Simcha 2009-12-02 12:39:37 UTC
This behavior is by design.  Unqual is supposed to shallowly strip const, etc, not deeply strip it.
Comment 2 Luther Tychonievich 2009-12-02 12:46:35 UTC
Then I propose this design decision ought to be made explicit in the documentation; "removes all qualifiers" seemed, to me, to imply removing *all* qualifiers, not just the top level.
Comment 3 FeepingCreature 2018-06-18 07:25:35 UTC
This bug needs a second look.

Consider this code:

struct S
{
  int* ipointer;
}

pragma(msg, (Unqual!(const S)).stringof);

As can be seen, Unqual has just deeply stripped const, not shallowly.

Either Unqual must be made to error when passed a const struct with reference, or Unqual must leave const(int[]) as int[].

The current state is broken.
Comment 4 Steven Schveighoffer 2018-06-18 14:37:57 UTC
This is likely going to be disruptive to fix, so many things use Unqual. But nonetheless, it's an important bug.
Comment 5 Timoses 2018-07-12 08:56:15 UTC
The fact the Unqual only "shallowly" unqualifies a type can be pretty annoying when dealing with templates and inout functions.


struct S
{
    int[] vals;   
}

template Temp(T)
{
    class Temp
    {
        T t;
        
        this(T t)
        { this.t = t; }
        
        auto get() inout
        {
            static if (is(T == S))
            {
                import std.traits : Unqual;
                alias tType = Unqual!(typeof(t.vals));
                pragma(msg, tType); // inout(int)[]
                return new inout Temp!tType(t.vals); // ERROR: Can't create class Temp!(inout(int)[])
            }
        }
    }
}

unittest
{
    auto t = Temp!S;
    t.get();
}

Error: variable `onlineapp.Temp!(inout(int)[]).Temp.t` only parameters or stack based variables can be inout
Error: template instance `onlineapp.Temp!(inout(int)[])` error instantiating


In this case a complete stripping of qualifiers is required!

Related discussion: https://forum.dlang.org/post/enwkjtdqivjldqpzzqrw@forum.dlang.org
Comment 6 Steven Schveighoffer 2018-07-12 12:28:57 UTC
Note, the bug here in FeepingCreature's case is that it strips more than it should. It is supposed to be safe to use Unqual.

So the expectation that Unqual should remove all mutability modifiers is incorrect.

I'm changing the title accordingly. Perhaps we should actually close this bug and open another, as the whole issue has really been flipped around?
Comment 7 Timoses 2018-07-12 14:36:46 UTC
(In reply to Steven Schveighoffer from comment #6)
> I'm changing the title accordingly. Perhaps we should actually close this
> bug and open another, as the whole issue has really been flipped around?

Perhaps you're looking for this? https://issues.dlang.org/show_bug.cgi?id=8338
Comment 8 Timoses 2018-07-12 15:02:58 UTC
(In reply to Steven Schveighoffer from comment #6)
> Note, the bug here in FeepingCreature's case is that it strips more than it
> should. It is supposed to be safe to use Unqual.
> 
> So the expectation that Unqual should remove all mutability modifiers is
> incorrect.

Tried to find examples where a complete stripping of qualifiers would break something. I guess here it is really required that it only strips the "head" qualifier:

https://github.com/dlang/phobos/blob/90a8fc387f25f9bdfc2c6ad4508da63c523be670/std/array.d#L1465

Though this is not the subject of this issue.. Should I perhaps create a new issue for https://issues.dlang.org/show_bug.cgi?id=3567#c5 ? Perhaps asking for a new trait?
Comment 9 Steven Schveighoffer 2018-07-12 15:11:44 UTC
I think a trait "ForceUnqual" may be needed in some cases, but "Unqual" I have always expected to behave the way it does (except in the case of structs containing references, for which it should not strip anything).

Man, it would be nice to have a tail-modifier in D...
Comment 10 berni44 2019-12-12 11:45:34 UTC
*** Issue 8338 has been marked as a duplicate of this issue. ***
Comment 11 dlangBugzillaToGithub 2024-12-01 16:13:17 UTC
THIS ISSUE HAS BEEN MOVED TO GITHUB

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

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