digitalmars.D.learn - Unexpected range assignment behaviour
- Lewis (15/15) Jul 19 ```
- H. S. Teoh (10/26) Jul 19 Sounds like a bug. First, there's an incompatibility between AA value
- Dennis (19/22) Jul 19 The range `0 .. 3` has compile time known length, so it gets
- matheus (6/28) Jul 19 Hi Dennis, I undestood your explanation, and based on that
- Dennis (6/8) Jul 19 The RangeError is only thrown when at runtime, the key doesn't
- H. S. Teoh (13/21) Jul 19 IMO, implicit slicing of static arrays ought to be killed with fire.
- Jonathan M Davis (28/45) Jul 19 wrote:
- Lance Bachmeier (19/34) Jul 19 The simplest solution is to keep them consistent:
``` string[3][string] lookup; string[] dynArray = ["d", "e", "f"]; lookup["test"] = dynArray[0..$]; ``` This fails at runtime with RangeError. But if I change that last line to: ``` lookup["test"] = dynArray[0..3]; ``` then it works. But the value of $ here is 3. Why do I get a RangeError at runtime even though the slice is the correct size (and the same size as the hardcoded one that works)? I would have expected to only get a RangeError if at runtime the value turned out to be wrong.
Jul 19
On Fri, Jul 19, 2024 at 09:34:13AM +0000, Lewis via Digitalmars-d-learn wrote:``` string[3][string] lookup; string[] dynArray = ["d", "e", "f"]; lookup["test"] = dynArray[0..$]; ``` This fails at runtime with RangeError. But if I change that last line to: ``` lookup["test"] = dynArray[0..3]; ``` then it works. But the value of $ here is 3. Why do I get a RangeError at runtime even though the slice is the correct size (and the same size as the hardcoded one that works)? I would have expected to only get a RangeError if at runtime the value turned out to be wrong.Sounds like a bug. First, there's an incompatibility between AA value type and the type being assigned: the value type of `lookup` is a static array, whereas a slice is a dynamic array. But since the compiler allows this assignment, it should work. I suspect there's a frontend bug somewhere in how assignments of slices to static arrays are implemented. T -- MAS = Mana Ada Sistem?
Jul 19
On Friday, 19 July 2024 at 09:34:13 UTC, Lewis wrote:But the value of $ here is 3. Why do I get a RangeError at runtime even though the slice is the correct size (and the same size as the hardcoded one that works)?The range `0 .. 3` has compile time known length, so it gets converted to string[3]: ```D lookup["test"] = dynArray[0 .. 3]; // becomes lookup["test"] = cast(string[3]) dynArray[0 .. 3]; ``` The key "test" doesn't exist yet, but because it's an assignment, it gets created. However, `0 .. $` depends on a run-time variable here, so it doesn't convert to a static array and does slice assignment: ```D lookup["test"] = dynArray[0 .. $]; // becomes lookup["test"][0 .. $] = dynArray[0 .. $]; ``` Now, you get a range error because "test" doesn't exist in `lookup`, and slice assignment doesn't create a new entry.
Jul 19
On Friday, 19 July 2024 at 15:33:34 UTC, Dennis wrote:On Friday, 19 July 2024 at 09:34:13 UTC, Lewis wrote:Hi Dennis, I undestood your explanation, and based on that couldn't this case for example be caught during the compiling time? Thanks, Matheus.But the value of $ here is 3. Why do I get a RangeError at runtime even though the slice is the correct size (and the same size as the hardcoded one that works)?The range `0 .. 3` has compile time known length, so it gets converted to string[3]: ```D lookup["test"] = dynArray[0 .. 3]; // becomes lookup["test"] = cast(string[3]) dynArray[0 .. 3]; ``` The key "test" doesn't exist yet, but because it's an assignment, it gets created. However, `0 .. $` depends on a run-time variable here, so it doesn't convert to a static array and does slice assignment: ```D lookup["test"] = dynArray[0 .. $]; // becomes lookup["test"][0 .. $] = dynArray[0 .. $]; ``` Now, you get a range error because "test" doesn't exist in `lookup`, and slice assignment doesn't create a new entry.
Jul 19
On Friday, 19 July 2024 at 17:20:22 UTC, matheus wrote:couldn't this case for example be caught during the compiling time?The RangeError is only thrown when at runtime, the key doesn't exist, so that can't be caught. The real problem is implicit slicing of static arrays, which I'm not a fan of, but removing it is a breaking change. So perhaps Associative Arrays should be enhanced to create keys on slice assignment.
Jul 19
On Fri, Jul 19, 2024 at 05:48:37PM +0000, Dennis via Digitalmars-d-learn wrote:On Friday, 19 July 2024 at 17:20:22 UTC, matheus wrote:IMO, implicit slicing of static arrays ought to be killed with fire. This is not the first time it has caused problems. In the past it used to cause issues with the implicit slice escaping the scope of the original static array, leading to dangling pointers and subsequent memory corruption / UB. With -dip1000 the situation has somewhat improved, but not entirely. It still causes nasty surprises when a slice was implicitly taken where it was unexpected. This case here is another example of the problems that it causes. T -- I don't trust computers, I've spent too long programming to think that they can get anything right. -- James Millercouldn't this case for example be caught during the compiling time?The RangeError is only thrown when at runtime, the key doesn't exist, so that can't be caught. The real problem is implicit slicing of static arrays, which I'm not a fan of, but removing it is a breaking change. So perhaps Associative Arrays should be enhanced to create keys on slice assignment.
Jul 19
On Friday, July 19, 2024 12:02:55 PM MDT H. S. Teoh via Digitalmars-d-learn wrote:On Fri, Jul 19, 2024 at 05:48:37PM +0000, Dennis via Digitalmars-d-learnwrote:Very, very hot fire. :) IIRC, Atila has indicated that he would like to kill implicit slicing of static arrays (though that's going to require that we have actually started doing Editions first), so we may end up finally getting rid of it. I don't know how much convincing it will take for Walter though. I actually brought this up with Walter years ago at one of the dconfs in Berlin, suggesting that it was a big safety mistake, but he preferred the idea of improving the language to catch escaping over removing the implicit slicing (which is probably part of why DIP 1000 and the related changes have unfortunately become a thing). Regardless of DIP 1000 though, IMHO, the implicit slicing just causes confusion and invisible behavior simply so that you can avoid using an explicit [] - and some of that isn't even related to bugs per se. For instance, plenty of folks end up trying to pass a static array to a range-based function and get confused when that doesn't work, since if the function took a dynamic array, it would work (and that also makes it more problematic to change a function so that it takes a range instead of a dynamic array). It's one of those features that seems like it's a nice usability improvement at first glance but which ultimately is a footgun. And when you get a more complex example like the one in this thread, it's that much worse, since even if you know enough to suspect that something along those lines might be the problem, I bet that most of us would not immediately come to that conclusion. It's just too subtle. And all to avoid typing a couple of characters. - Jonathan M DavisOn Friday, 19 July 2024 at 17:20:22 UTC, matheus wrote:IMO, implicit slicing of static arrays ought to be killed with fire. This is not the first time it has caused problems. In the past it used to cause issues with the implicit slice escaping the scope of the original static array, leading to dangling pointers and subsequent memory corruption / UB. With -dip1000 the situation has somewhat improved, but not entirely. It still causes nasty surprises when a slice was implicitly taken where it was unexpected. This case here is another example of the problems that it causes.couldn't this case for example be caught during the compiling time?The RangeError is only thrown when at runtime, the key doesn't exist, so that can't be caught. The real problem is implicit slicing of static arrays, which I'm not a fan of, but removing it is a breaking change. So perhaps Associative Arrays should be enhanced to create keys on slice assignment.
Jul 19
On Friday, 19 July 2024 at 09:34:13 UTC, Lewis wrote:``` string[3][string] lookup; string[] dynArray = ["d", "e", "f"]; lookup["test"] = dynArray[0..$]; ``` This fails at runtime with RangeError. But if I change that last line to: ``` lookup["test"] = dynArray[0..3]; ``` then it works. But the value of $ here is 3. Why do I get a RangeError at runtime even though the slice is the correct size (and the same size as the hardcoded one that works)? I would have expected to only get a RangeError if at runtime the value turned out to be wrong.The simplest solution is to keep them consistent: ``` string[3][string] lookup; string[3] dynArray = ["d", "e", "f"]; ``` or ``` string[][string] lookup; string[] dynArray = ["d", "e", "f"]; ``` Avoid the temptation to mix static and dynamic arrays and your life will be easier. If you run into a situation where it's tough to avoid, use an explicit conversion: ``` lookup["test"] = dynArray.to!(string[3])[0..$]; ``` (I don't know all the complicated under the hood stuff as others do, but I know what works and why.)
Jul 19