Jump to page: 1 24  
Page
Thread overview
November 29

I don’t know how many times I get caught with size_t indexes but I want them to be int or uint. It’s especially painful in my class that I’m teaching where I don’t want to yet explain why int doesn’t work there and have to introduce casting or use to!int. All for the possibility that I have an array larger than 2 billion elements.

I am forgetting why we removed this in the first place.

Can we have the compiler insert an assert at the loop start that the bounds are in range when you use a smaller int type? Clearly the common case is that the array is small enough for int indexes.

-Steve

November 29

On Wednesday, 29 November 2023 at 14:56:50 UTC, Steven Schveighoffer wrote:

>

I don’t know how many times I get caught with size_t indexes but I want them to be int or uint. It’s especially painful in my class that I’m teaching where I don’t want to yet explain why int doesn’t work there and have to introduce casting or use to!int. All for the possibility that I have an array larger than 2 billion elements.

I am forgetting why we removed this in the first place.

Can we have the compiler insert an assert at the loop start that the bounds are in range when you use a smaller int type? Clearly the common case is that the array is small enough for int indexes.

For those who are unaware, this used to work:

auto arr = [1, 2, 3];
foreach(int idx, v; arr) {
    ...
}

But was removed at some point. I think it should be brought back (we are bringing stuff back now, right? Like hex strings?)

-Steve

November 29

On Wednesday, 29 November 2023 at 15:48:25 UTC, Steven Schveighoffer wrote:

>

On Wednesday, 29 November 2023 at 14:56:50 UTC, Steven Schveighoffer wrote:

>

I don’t know how many times I get caught with size_t indexes but I want them to be int or uint. It’s especially painful in my class that I’m teaching where I don’t want to yet explain why int doesn’t work there and have to introduce casting or use to!int. All for the possibility that I have an array larger than 2 billion elements.

I am forgetting why we removed this in the first place.

Can we have the compiler insert an assert at the loop start that the bounds are in range when you use a smaller int type? Clearly the common case is that the array is small enough for int indexes.

For those who are unaware, this used to work:

auto arr = [1, 2, 3];
foreach(int idx, v; arr) {
    ...
}

But was removed at some point. I think it should be brought back (we are bringing stuff back now, right? Like hex strings?)

-Steve

Along the same lines, this won't even compile:

foreach(int idx; 0..arr.length) {
}

Apparently someone decided the explicit int is an implicit conversion.

November 29

On Wednesday, 29 November 2023 at 16:06:32 UTC, bachmeier wrote:

>

Along the same lines, this won't even compile:

foreach(int idx; 0..arr.length) {
}

Apparently someone decided the explicit int is an implicit conversion.

I don't think that ever compiled, even in D1 (64-bit). What happens here is the two ends are converted to a common type (in this case size_t), and you can't assign size_t to int.

But it's easy to fix, just change the top condition via a cast or conversion. The same is not available to a foreach over an array with an index.

I would be fine fixing this to work in the same way as I suggested (with a pre-loop assert that it will work). It makes sense that it should act the same.

-Steve

November 29

On Wednesday, 29 November 2023 at 14:56:50 UTC, Steven Schveighoffer wrote:

>

I don’t know how many times I get caught with size_t indexes but I want them to be int or uint. It’s especially painful in my class that I’m teaching where I don’t want to yet explain why int doesn’t work there and have to introduce casting or use to!int. All for the possibility that I have an array larger than 2 billion elements.

I am forgetting why we removed this in the first place.

Can we have the compiler insert an assert at the loop start that the bounds are in range when you use a smaller int type? Clearly the common case is that the array is small enough for int indexes.

-Steve

It cannot work in the general case, slice's size is a size_t .

But if the compiler can prove it fits in 32bits, then there should be no problem. VRP could do that.

November 29

On Wednesday, 29 November 2023 at 16:56:54 UTC, deadalnix wrote:

>

It cannot work in the general case, slice's size is a size_t .

But if the compiler can prove it fits in 32bits, then there should be no problem. VRP could do that.

VRP does not work here. The array comes from anywhere and can have any length. It needs to be validated (if you insist) at runtime.

But it's very very VERY uncommon to have an array with 2 billion elements.

Note, this worked for years, pretty much without incident. I don't even remember why we removed it. It seems like one of those problems nobody had or was looking to solve. Yet, we solved it.

Actually, I just tested it out, and it gives a deprecation warning, but builds! This means it's actually quite easy to fix this, just remove the deprecation, and add the assert.

A great point from CyberShadow on the original PR that added the deprecation:

https://github.com/dlang/dmd/pull/8941#issuecomment-496306412

And note this was to "fix" an issue with foreach_reverse on int indexes, it was just snuck in there...

And here is another bug report that had a more detailed conversation (including from me): https://issues.dlang.org/show_bug.cgi?id=16149

-Steve

November 29

On Wednesday, 29 November 2023 at 16:25:55 UTC, Steven Schveighoffer wrote:

>

On Wednesday, 29 November 2023 at 16:06:32 UTC, bachmeier wrote:

> >

foreach(int idx; 0..arr.length) {
}


Apparently someone decided the explicit `int` is an implicit conversion.

I don't think that ever compiled, even in D1 (64-bit). What happens here is the two ends are converted to a common type (in this case size_t), and you can't assign size_t to int.

But it's easy to fix, just change the top condition via a cast or conversion. The same is not available to a foreach over an array with an index.

Yeah, but it's a matter of ugliness. This looks awful

foreach(idx; 0..(cast(int) arr.length)) {
}

In the case you're talking about, you could do

foreach(_idx, v; arr) {
  int idx = cast(int) _idx;
}

I don't mind ugly and verbose code if there's sufficient benefit. There's no benefit in this case.

November 29

On Wednesday, 29 November 2023 at 21:47:09 UTC, bachmeier wrote:

>

Yeah, but it's a matter of ugliness. This looks awful

foreach(idx; 0..(cast(int) arr.length)) {
}

In the case you're talking about, you could do

foreach(_idx, v; arr) {
  int idx = cast(int) _idx;
}

I don't mind ugly and verbose code if there's sufficient benefit. There's no benefit in this case.

Understand that I don't disagree with you. But my point is that foreach(int i; 0 .. arr.length) never compiled, whereas foreach(int i, v; arr) did compile (without deprecation) at some point.

This puts it in the category of "features that were removed", vs "features that should be added", and therefore gives a little less resistance to (re)allowing it.

-Steve

November 30

On Wednesday, 29 November 2023 at 22:30:30 UTC, Steven Schveighoffer wrote:

>

On Wednesday, 29 November 2023 at 21:47:09 UTC, bachmeier wrote:

>

Yeah, but it's a matter of ugliness. This looks awful

foreach(idx; 0..(cast(int) arr.length)) {
}

In the case you're talking about, you could do

foreach(_idx, v; arr) {
  int idx = cast(int) _idx;
}

I don't mind ugly and verbose code if there's sufficient benefit. There's no benefit in this case.

Understand that I don't disagree with you. But my point is that foreach(int i; 0 .. arr.length) never compiled, whereas foreach(int i, v; arr) did compile (without deprecation) at some point.

This puts it in the category of "features that were removed", vs "features that should be added", and therefore gives a little less resistance to (re)allowing it.

-Steve

I'm totally +1 on this: it's a VERY common case, and it's an explicit request done to the compiler.

Adding an assert instead of the deprecation it's fine, usually it's what we do right after the foreach statement to safely transform the ulong to an int.

November 30

On Wednesday, 29 November 2023 at 21:47:09 UTC, bachmeier wrote:

>

In the case you're talking about, you could do

foreach(_idx, v; arr) {
  int idx = cast(int) _idx;
}

I don't mind ugly and verbose code if there's sufficient benefit. There's no benefit in this case.

I don't understand why this is not an OK solution instead adding yet another lowering for the special case of using int instead of size_t. Right now in D indexes are size_t and should be the default.

This feels more like a D3 discussion if indexes should be int or size_t.

« First   ‹ Prev
1 2 3 4