digitalmars.D - Did the implicit conversion from special slice expression to static
- Quirin Schroll (45/48) Sep 22 2022 And you find this table (assuming `e` is an expression that
- Nick Treleaven (22/53) Sep 22 2022 The problem is that you can initialize a static array from (or
- Nick Treleaven (4/20) Sep 22 2022 Or rather *cannot be* statically known. I.e. `int[1] = da;` is
- Quirin Schroll (24/82) Sep 22 2022 I think this is the reason the assignment compiles anyways. This
- Nick Treleaven (12/21) Sep 22 2022 Well I said a const runtime value should work (not just a
- Nick Treleaven (12/13) Sep 23 2022 It looks like the docs were merged but the compiler pull was not
- Nick Treleaven (4/7) Sep 24 2022 Commented out those docs & fixed other examples:
In the [Expression § Slice Conversion to Static Array](https://dlang.org/spec/expression.html#slice_to_static_array), at the end of the section, it says:Certain other forms of slice expression can be implicitly converted to a static array when the slice length can be known at compile-time.And you find this table (assuming `e` is an expression that contains no side effects and `a` and `b` are compile-time known integers): | Form | The length calculated at compile time | |-------------------|---------------------------------------| | `arr[]` | `arr.length` if known at compile-time | | `arr[a .. b]` | `b - a` | | `arr[e-a .. e]` | `a` | | `arr[e .. e+b]` | `b` | | `arr[e-a .. e+b]` | `a + b` | | `arr[e+a .. e+b]` | `b - a` if `a` ≤ `b` | | `arr[e-a .. e-b]` | `a - b` if `a` ≥ `b` | Has it ever worked? Expanding on the code example ```d 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. On the other hand, I tried with this code: ```d 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](https://run.dlang.io/) (LDC and any DMD since 2.064, including beta and nightly). 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.
Sep 22 2022
On Thursday, 22 September 2022 at 10:50:28 UTC, Quirin Schroll wrote:Has it ever worked? Expanding on the code example ```d 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 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: ```d 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](https://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.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.
Sep 22 2022
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:Or rather *cannot be* statically known. I.e. `int[1] = da;` is allowed.```d 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 ```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.
Sep 22 2022
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: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: ```d 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.Has it ever worked? Expanding on the code example ```d 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.orgI 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.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.On the other hand, I tried with this code: ```d 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](https://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.+1 to that.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.
Sep 22 2022
On Thursday, 22 September 2022 at 14:31:46 UTC, Quirin Schroll wrote:On Thursday, 22 September 2022 at 12:48:18 UTC, Nick Treleaven wrote:Well I said a const runtime value should work (not just a compile-time constant as works now). const there would make it easy for the compiler to tell there are no side effects. I think you are right that a mutable variable simple lvalue should work as well. Some expressions do have side effects and to ensure every kind of non-side effect expression might require an optimization pass. I found this is in bugzilla where `m_data[offset .. offset + 14];` is not recognised: https://issues.dlang.org/show_bug.cgi?id=9165#c1If 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.
Sep 22 2022
On Thursday, 22 September 2022 at 10:50:28 UTC, Quirin Schroll wrote:Has it ever worked?It looks like the docs were merged but the compiler pull was not merged: https://github.com/dlang/dmd/pull/4209#issuecomment-74065882 Before I found that I implemented `arr[e .. e+b]` for a simple variable `e`: https://github.com/ntrel/dmd/commits/slice-size I think at least that should be supported, probably the most common of all the non-constant index forms. But the original pull works for lots of other side-effect free expressions, besides the other forms.
Sep 23 2022
On Friday, 23 September 2022 at 13:35:31 UTC, Nick Treleaven wrote:It looks like the docs were merged but the compiler pull was not merged: https://github.com/dlang/dmd/pull/4209#issuecomment-74065882Commented out those docs & fixed other examples: https://github.com/dlang/dlang.org/pull/3416
Sep 24 2022