www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Deprecate assigning a slice to a static array?

reply Nick Treleaven <nick geany.org> writes:
I didn't know initializing a static array from a slice of unknown 
length was allowed until I saw:
https://dlang.org/blog/2022/06/21/dip1000-memory-safety-in-a-modern-system-programming-language-pt-1/

     // allocated in static program memory
     auto hello1 = "Hello world!";
     // allocated on the stack, copied from hello1
     immutable(char)[12] hello2 = hello1;

How does the compiler know `hello1.length` at compile-time for 
the initialisation of the static array? It doesn't - there is a 
runtime check. I think it's better to require slicing of either 
the static array or the slice to make that clear:

     int[] s = ...;
     int[2] a;
     a[] = s; // copy slice to slice, checking lengths match
     a = s[0..2]; // copy 2 elements, no runtime check

(The last line is recognised as a slice of compile-time known 
length - described here:
https://dlang.org/spec/expression.html#slice_to_static_array).

For just `a = s;`, the programmer may have accidentally assumed 
`s` was a static array, or forgot to slice it to match the static 
array size. I think it's bug prone. It's also hard to detect if 
the slice normally has a matching length but in some weird 
runtime condition it doesn't and it throws. It's also a hidden 
runtime check that could hurt performance.

Note this doesn't seem to be documented in the spec yet:
[1] https://dlang.org/spec/arrays.html#assignment
[2] https://dlang.org/spec/arrays.html#array-copying
[3] https://dlang.org/spec/arrays.html#array-initialization

[1] actually has:

     //s = a; // error, as a's length is not known at compile-time

I added that to the docs but it's wrong (if this feature is to 
stay I will make a PR to fix that line).

[2] only talks about slices. [3] doesn't mention initializing 
from an lvalue. *AssignExpression* just links to Array Copying 
[2] and Array Setting (for assigning a single element).

Would deprecating this break much code? Perhaps an exploratory 
dmd PR could be made to see if it breaks any of the tested key 
projects?
Aug 31 2022
next sibling parent Nick Treleaven <nick geany.org> writes:
On Wednesday, 31 August 2022 at 12:04:10 UTC, Nick Treleaven 
wrote:
     a = s[0..2]; // copy 2 elements, no runtime check
Here of course there is a runtime check that `s.length >= 2`. But it is clearer the check is happening and the user could avoid that check with `.ptr`.
Aug 31 2022
prev sibling parent reply Salih Dincer <salihdb hotmail.com> writes:
On Wednesday, 31 August 2022 at 12:04:10 UTC, Nick Treleaven 
wrote:
 I didn't know initializing a static array from a slice of 
 unknown length was allowed until I saw:
 https://dlang.org/blog/2022/06/21/dip1000-memory-safety-in-a-modern-system-programming-language-pt-1/
The reverse is also possible and note that .capacity is 0 in any case. ```d // D 2.0.83 import std.stdio; void main() { int[4] abcd = [0, 1, 2, 3]; int[] slice = abcd[]; slice.writeln(": ", slice.capacity); int[] dcba = [ 7, 6, 5, 4, 3, 2, 1, 0]; int[4] arr = dcba[4..$]; arr.writeln(": ", arr.capacity); arr = dcba[0..4]; arr.writeln(": ", arr.capacity); }/* [0, 1, 2, 3]: 0 [3, 2, 1, 0]: 0 [7, 6, 5, 4]: 0 Process finished. */ ``` SDB 79
Aug 31 2022
next sibling parent reply Salih Dincer <salihdb hotmail.com> writes:
On Wednesday, 31 August 2022 at 15:36:54 UTC, Salih Dincer wrote:
 The reverse is also possible and note that .capacity is 0 in 
 any case.
So is `slice` really a slice? SDB 79
Aug 31 2022
parent bauss <jacobbauss gmail.com> writes:
On Wednesday, 31 August 2022 at 15:41:14 UTC, Salih Dincer wrote:
 On Wednesday, 31 August 2022 at 15:36:54 UTC, Salih Dincer 
 wrote:
 The reverse is also possible and note that .capacity is 0 in 
 any case.
So is `slice` really a slice? SDB 79
Yes, because a slice isn't a type but a concept.
Aug 31 2022
prev sibling parent Nick Treleaven <nick geany.org> writes:
On Wednesday, 31 August 2022 at 15:36:54 UTC, Salih Dincer wrote:
   int[] dcba = [ 7, 6, 5, 4, 3, 2, 1, 0];
   int[4] arr = dcba[4..$];
The above conversion would also be deprecated because `dcba[4..$]` is not one of the slice expression forms with compile-time known length (the compiler doesn't know what `$` is). `dcba[4..8]` could be used instead. In case the runtime matching length check is desired with static array initialization (i.e. check `dcba.length` is not > 8), it would be written as: int[4] arr; // optimizer can remove `= 0` arr[] = dcba[4..$]; // matching length check now more obvious
   arr = dcba[0..4];
That is fine as I mentioned, it's one of the forms recognised.
Aug 31 2022