Skip to content

Commit

Permalink
Fix #20601.
Browse files Browse the repository at this point in the history
hasIndirections doesn't handle static arrays of length 0 correctly (they
don't actually have any indirections), because operator precedence
resulted in the check for 0 length static arrays having no actual
effect.

I also copied the test for
https://issues.dlang.org/show_bug.cgi?id=12000 from std.traits to here,
because it's really a compiler bug that's being tested rather than
hasIndirections itself (so being in the compiler repo arguably makes
more sense), and it also arguably makes more sense to put it next to the
actual implementation than in std.traits where it's been.
  • Loading branch information
jmdavis committed Dec 25, 2024
1 parent 31bc99f commit d55d9df
Showing 1 changed file with 102 additions and 1 deletion.
103 changes: 102 additions & 1 deletion druntime/src/core/internal/traits.d
Original file line number Diff line number Diff line change
Expand Up @@ -543,13 +543,114 @@ template hasIndirections(T)
else static if (__traits(isAssociativeArray, T) || is(T == class) || is(T == interface))
enum hasIndirections = true;
else static if (is(T == E[N], E, size_t N))
enum hasIndirections = T.sizeof && is(E == void) ? true : hasIndirections!(BaseElemOf!E);
enum hasIndirections = T.sizeof && (is(E == void) || hasIndirections!(BaseElemOf!E));
else static if (isFunctionPointer!T)
enum hasIndirections = false;
else
enum hasIndirections = isPointer!T || isDelegate!T || isDynamicArray!T;
}

@safe unittest
{
static assert(!hasIndirections!int);
static assert(!hasIndirections!(const int));

static assert( hasIndirections!(int*));
static assert( hasIndirections!(const int*));

static assert( hasIndirections!(int[]));
static assert(!hasIndirections!(int[42]));
static assert(!hasIndirections!(int[0]));

static assert( hasIndirections!(int*));
static assert( hasIndirections!(int*[]));
static assert( hasIndirections!(int*[42]));
static assert(!hasIndirections!(int*[0]));

static assert( hasIndirections!string);
static assert( hasIndirections!(string[]));
static assert( hasIndirections!(string[42]));
static assert(!hasIndirections!(string[0]));

static assert( hasIndirections!(void[]));
static assert( hasIndirections!(void[17]));
static assert(!hasIndirections!(void[0]));

static assert( hasIndirections!(string[int]));
static assert( hasIndirections!(string[int]*));
static assert( hasIndirections!(string[int][]));
static assert( hasIndirections!(string[int][12]));
static assert(!hasIndirections!(string[int][0]));

static assert(!hasIndirections!(int function(string)));
static assert( hasIndirections!(int delegate(string)));
static assert(!hasIndirections!(const(int function(string))));
static assert( hasIndirections!(const(int delegate(string))));
static assert(!hasIndirections!(immutable(int function(string))));
static assert( hasIndirections!(immutable(int delegate(string))));

static class C {}
static assert( hasIndirections!C);

static interface I {}
static assert( hasIndirections!I);

{
static struct S {}
static assert(!hasIndirections!S);
}
{
static struct S { int i; }
static assert(!hasIndirections!S);
}
{
static struct S { C c; }
static assert( hasIndirections!S);
}
{
static struct S { int[] arr; }
static assert( hasIndirections!S);
}
{
int local;
struct S { void foo() { ++local; } }
static assert( hasIndirections!S);
}

{
static union U {}
static assert(!hasIndirections!U);
}
{
static union U { int i; }
static assert(!hasIndirections!U);
}
{
static union U { C c; }
static assert( hasIndirections!U);
}
{
static union U { int[] arr; }
static assert( hasIndirections!U);
}
}

// https://issues.dlang.org/show_bug.cgi?id=12000
@safe unittest
{
static struct S(T)
{
static assert(hasIndirections!T);
}

static class A(T)
{
S!A a;
}

A!int dummy;
}

template hasUnsharedIndirections(T)
{
static if (is(T == immutable))
Expand Down

0 comments on commit d55d9df

Please sign in to comment.