Summary: handles[patch] std.traits.hasIndirections incorrectly
                    handels static arrays
           Product: D
           Version: D2
          Platform: Other
        OS/Version: Windows
            Status: NEW
          Keywords: patch
          Severity: critical
          Priority: P1
         Component: Phobos

--- Comment #0 from Rob Jacques <> 2011-03-23 22:05:38 PDT ---
std.traits.hasIndirections currently does not return true for static arrays of
types with indirections. More fundamentally, it's unit tests do not verify it's
output for all template instances. I've set the priority of this bug based on
the fact that manual memory allocation routines are apt to utilize
hasIndirections to determine whether or not to apply the no scan GC attribute
and getting this wrong results in memory stomping/corruption. 

I've added detection and handling of static arrays to hasIndirectionsImpl.
Also, to prevent future unforeseen corner cases, I've added a private template,
hasIndirectionsUnittest, which allows each instance of hasIndirections!T to
generate a unit test which verifies the value of hasIndirections!T against T's
runtime GC flags. Also, a specific unit test for static arrays was added.

Patch: (Based on DMD 2.052)

Returns $(D true) if and only if $(D T)'s representation includes at
least one of the following: $(OL $(LI a raw pointer $(D U*);) $(LI an
array $(D U[]);) $(LI a reference to a class type $(D C).)
$(LI an associative array.) $(LI a delegate.))

template hasIndirections(T)
    enum hasIndirections = hasIndirectionsUnittest!T.implementation;

// Tests hasIndirections against the GC's runtime info for every T
private template hasIndirectionsUnittest(T)
    enum implementation = hasIndirectionsImpl!(RepresentationTypeTuple!T);

    unittest {
        assert( hasIndirections!T == (typeid(T[]).next.flags & 1) );

template hasIndirectionsImpl(T...)
    static if (!T.length)
        enum hasIndirectionsImpl = false;
    else static if(isFunctionPointer!(T[0]))
        enum hasIndirectionsImpl = hasIndirectionsImpl!(T[1 .. $]);
    else static if(isStaticArray!(T[0]))
        enum hasIndirectionsImpl = hasIndirectionsImpl!(T[1 .. $]) ||
        enum hasIndirectionsImpl = isPointer!(T[0]) || isDynamicArray!(T[0]) ||
            is (T[0] : const(Object)) || isAssociativeArray!(T[0]) ||
            isDelegate!(T[0]) || is(T[0] == interface)
            || hasIndirectionsImpl!(T[1 .. $]);

    struct S1 { int a; Object b; }
    static assert(hasIndirections!(S1));
    struct S2 { string a; }
    static assert(hasIndirections!(S2));
    struct S3 { int a; immutable Object b; }
    static assert(hasIndirections!(S3));
    static assert(hasIndirections!(int[string]));
    static assert(hasIndirections!(void delegate()));

    interface I;
    static assert(hasIndirections!I);
    static assert(!hasIndirections!(void function()));
    static assert(hasIndirections!(void*[1]));
    static assert(!hasIndirections!(byte[1]));

Configure issuemail:
------- You are receiving this mail because: -------

Reply via email to