The code below fails to compile. This is the minimum reduction I could find. The `arrayCtfe` function is the static if branch in std.array.array for __ctfe. This particular example can be fixed with an alternative implementation that calls the range API directly like so:
------
while(!range.empty) {
result ~= range.front;
range.popFront;
}
return result;
------
Unfortunately trying to do this in std.array results in compilation failures for other ranges, and checking that this implementation is valid for the range in question with `is(typeof)` or `__traits(compiles)` crashes the compiler.
Offending code:
-----
struct Target {
string[] strings() @safe pure return scope const {
return [];
}
}
auto maybeAddDependencies(in Target target, in string projectPath) @safe pure {
Target[] targets;
scope srcs = targets.filter!(a => true);
return srcs
.map!(t => t.strings[0])
.arrayCtfe
;
}
// this is the implementation in std.array.array guarded by `if(__ctfe)`
auto arrayCtfe(R)(auto ref R range) {
import std.traits: ForeachType;
ForeachType!R[] result; // string[]
foreach (ref e; range) {
result ~= e;
}
return result;
}
-----
Comment #1 by bugzilla — 2024-05-10T01:53:11Z
Unfortunately, the example provided is incomplete and not compilable.
Comment #2 by bugzilla — 2024-05-10T02:12:37Z
I need a file, say, test.d, that when compiled with specific switches reproduces the error.
Comment #3 by nick — 2024-05-10T10:56:45Z
It compiles with:
import std.algorithm : filter, map;
Adding -dip1000 gives:
arrayctfe.d(14): Error: scope variable `srcs` assigned to non-scope parameter `range` calling `arrayCtfe`
arrayctfe.d(28): which is not `scope` because of `__r115 = range`
Replacing the foreach statement with the while code in comment #0 does compile with -dip1000.
Comment #4 by robert.schadek — 2024-12-13T19:35:01Z