From e7d058bcff9f1a83edbb8974c15f5773288a6636 Mon Sep 17 00:00:00 2001 From: Jonathan M Davis Date: Tue, 24 Dec 2024 17:26:51 -0700 Subject: [PATCH] Fix #20601. 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. --- druntime/src/core/internal/traits.d | 103 +++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/druntime/src/core/internal/traits.d b/druntime/src/core/internal/traits.d index 02898082e40..3748bfab977 100644 --- a/druntime/src/core/internal/traits.d +++ b/druntime/src/core/internal/traits.d @@ -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))