Test case: import std.range; enum table = [2, 3, 5, 7, 11]; uint lookup(uint k) { auto tab = assumeSorted(table); tab.equalRange(k); //changing it to lowerBound works assert(!tab.empty); return 42; } enum t = lookup(7); invking dmd: dmd2/linux/bin/../../src/phobos/std/range.d(5572): Error: cannot evaluate this.length() at compile time dmd2/linux/bin/../../src/phobos/std/range.d(5620): Error: cannot evaluate this.getTransitionIndex(v) at compile time dmd2/linux/bin/../../src/phobos/std/range.d(5620): Error: cannot evaluate this.opSlice(0LU,this.getTransitionIndex(v)) at compile time dmd2/linux/bin/../../src/phobos/std/range.d(5693): Error: cannot evaluate this.opSlice(first,it).lowerBound(value) at compile time Segmentation fault (core dumped)
Reduced test case (which doesn't trigger the ICE, but should have the same cause): --------------------- struct Bug6418 { size_t length2() { return 1; } size_t length() { return 1; } } static assert(Bug6418.init.length2 == 1); // <-- ok static assert(Bug6418.init.length == 1); // <-- error --------------------- x.d(6): Error: cannot evaluate Bug6418().length() at compile time x.d(6): Error: static assert (Bug6418().length() == 1u) is not evaluatable at compile time --------------------- Temporary workaround to Phobos is to change all 'length' to '_input.length': diff --git a/std/range.d b/std/range.d index 622f7b8..a8e4e4e 100644 --- a/std/range.d +++ b/std/range.d @@ -5618,7 +5618,7 @@ if (isRandomAccessRange!Range) private size_t getTransitionIndex(SearchPolicy sp, alias test, V)(V v) if (sp == SearchPolicy.trotBackwards || sp == SearchPolicy.gallopBackwards) { - immutable count = length; + immutable count = _input.length; if (empty || !test(back, v)) return count; if (count == 1) return 0; size_t below = count - 2, above = count - 1, step = 2; @@ -5690,7 +5690,7 @@ if (isRandomAccessRange!Range) if (is(V : ElementType!Range)) { ElementType!Range v = value; - return this[getTransitionIndex!(sp, gt)(v) .. length]; + return this[getTransitionIndex!(sp, gt)(v) .. _input.length]; } // equalRange @@ -5739,12 +5739,12 @@ if (isRandomAccessRange!Range) // Gallop towards the left end as it's likely nearby immutable left = first + this[first .. it] - .lowerBound!(SearchPolicy.gallopBackwards)(value).length; + .lowerBound!(SearchPolicy.gallopBackwards)(value)._input.length; first += count; // Gallop towards the right end as it's likely nearby immutable right = first - this[it + 1 .. first] - .upperBound!(SearchPolicy.gallop)(value).length; + .upperBound!(SearchPolicy.gallop)(value)._input.length; return this[left .. right]; } }
There are two bugs here. The segfault has a completely different cause from the rejects-valid bug.
https://github.com/D-Programming-Language/dmd/commit/9318dc44c3e9aa75907966b9fd122c0cc6700891 https://github.com/D-Programming-Language/dmd/commit/571661646ca420aa4c3fb348e86e35ed8faae624