On Thursday, 22 September 2022 at 12:48:18 UTC, Nick Treleaven wrote:
> On Thursday, 22 September 2022 at 10:50:28 UTC, Quirin Schroll wrote:
> Has it ever worked?
Expanding on the code example
int[] da = [1, 2, 3];
int i = da[0]; // runtime variable
int[2] sa2 = da[i .. i + 2];
assert(sa2 == [2, 3]);
// my tests
int[1] sa1 = da[i .. i + 2]; // core.exception.RangeError
int[3] sa3 = da[i .. i + 2]; // core.exception.RangeError
It seems like there is not attempt made to check the lengths at compile-time. The specification in a sense promised me a compile error here.
The problem is that you can initialize a static array from (or assign to) a slice, even when the slice length is not statically known. I started a thread on that:
https://forum.dlang.org/post/kqolsorsdmlshxhdqbpq@forum.dlang.org
I think this is the reason the assignment compiles anyways. This is however not the reason why there is no compile error pointing out a length mismatch. The spec says that both lengths are known at compile-time; thus, if equal, good, if not, it’s an error:
int i = 1;
int[3] xs = [ 0, i, i+1, i+3 ]; // compile-error (length mismatch)
The literal is not a constant (it includes run-time values). However, the length is statically known and mismatches.
> I did then update the docs to document that:
https://dlang.org/spec/arrays.html#assignment
I think this is surprising because a slice does not implicitly convert to a static array in general, e.g. when passing one to a static array function parameter.
> On the other hand, I tried with this code:
void f(T, size_t n)(T[n] array) { }
void main()
{
int[] xs = [1,2,3,4,5,6];
size_t i = 2;
f(xs[i .. i+3]); // compile error
}
It did not work with any compiler supported by run.dlang.io (LDC and any DMD since 2.064, including beta and nightly).
If you make i
const, it does work, but it has to be initialized from a compile-time expression too. It should work with a runtime initializer so long as i
is const.
This misses the point entirely. The spec is about run-time expressions. It is very clear about that implicitly using the phrase “no side effects”. Reading a compile-time constant is a very special case of no side effects.
Effectively, the idea is that there’s a run-time value involved, but it serves only as the offset and does not change the length of the segment being sliced (because the values cancel). The whole thing would be trivial if syntax existed for it, e.g. slice[i: 3]
for slice[i..i+3]
where i
would only be evaluated once. We could simply say: If the length is a compile-time constant, there it is.
> > If it does work in other contexts, either this feature should be removed (it does not work consistently) or be improved so that it lives up to its promise. If nothing like that is implemented, the section should be removed from the spec.
Aside from breakage, assignment from a slice of unknown compile-time length could be illegal - the user could easily write arr[] = slice
instead.
That makes it clear that slice copying is happening, which has a runtime check for matching lengths.
For initialization, statically-known slice length could be required. Failing that, at least requiring slice[]
on an lvalue initializer would make it clear it is initialization from a slice.
+1 to that.