Re: T[] opIndex() Error: .. signal 11

2023-10-05 Thread Steven Schveighoffer via Digitalmars-d-learn

On 10/5/23 1:49 AM, ag0aep6g wrote:

For some further reading, there's an open issue about the unexpected 
slicing: https://issues.dlang.org/show_bug.cgi?id=14619


Thank you I had forgotten about that issue!

-Steve


Re: T[] opIndex() Error: .. signal 11

2023-10-04 Thread ag0aep6g via Digitalmars-d-learn

On 03.10.23 20:26, Paul Backus wrote:
Naturally, this lowering is completely absent from [the language spec's 
section on `foreach`.][1] According to the spec, the only ways to 
iterate over a `struct` type are `opApply` and the input range interface.


I think it would probably be less confusing to have both `opApply` and 
`empty`/`front`/`popFront` take precedence over this lowering, but I 
have no idea how much existing code would be broken by such a change. At 
the very least, though, this needs to be documented.


[1]: https://dlang.org/spec/statement.html#foreach-statement


For some further reading, there's an open issue about the unexpected 
slicing: https://issues.dlang.org/show_bug.cgi?id=14619


Re: T[] opIndex() Error: .. signal 11

2023-10-03 Thread Paul Backus via Digitalmars-d-learn
On Tuesday, 3 October 2023 at 17:05:46 UTC, Steven Schveighoffer 
wrote:

```d
void main()
{
S s = 0;
{
scope int[] __r3 = s.opIndex()[];
ulong __key4 = 0LU;
for (; __key4 < __r3.length; __key4 += 1LU)
{
int x = __r3[__key4];
}
}
return 0;
}
```

Note the difference in how the foreach code is lowered. Inside 
`opIndex`, it's lowered to the range functions. Outside, it 
uses the slice operator to switch to iterating a `scope int[]`.


Naturally, this lowering is completely absent from [the language 
spec's section on `foreach`.][1] According to the spec, the only 
ways to iterate over a `struct` type are `opApply` and the input 
range interface.


I think it would probably be less confusing to have both 
`opApply` and `empty`/`front`/`popFront` take precedence over 
this lowering, but I have no idea how much existing code would be 
broken by such a change. At the very least, though, this needs to 
be documented.


[1]: https://dlang.org/spec/statement.html#foreach-statement


Re: T[] opIndex() Error: .. signal 11

2023-10-03 Thread Steven Schveighoffer via Digitalmars-d-learn

On 10/3/23 11:12 AM, Joel wrote:
The following program crashes, but doesn’t if I change (see title) T[] 
to auto. The program doesn’t even use that method/function. What’s the 
story?


It's a stack overflow.

when doing foreach on your type, the compiler *always* uses a slice 
first if it compiles and is a valid range.


So `foreach(x; ints)` really translates to `foreach(x; ints[])`.

Normally not a problem. But your `opIndex()` is calling `this.array`. 
What does `this.array` do? a foreach on your type. Which calls 
`opIndex`, which calls `array`, which calls `opIndex`, etc.


When you make it auto, well, then inside the `array` function, it won't 
use the `opIndex` (because clearly, the type hasn't been determined). 
And so it goes with the range functions without first doing a slice.


But then outside the type, now that `opIndex` type has been inferred, it 
can now use `foreach(x; ints[])`, and that goes back to the regular 
mechanism.


A minimized case is here:

```d
struct S
{
int front() => 1;
void popFront() {}
bool empty() => true;

auto opIndex() {
foreach(x; this) {}
return int[].init;
}
}

void main()
{
S s;
foreach(x; s) {}
}
```

If you run this on run.dlang.io, and click the "AST" button, you will 
get this for the type and the main function:


```d
import object;
struct S
{
int front()
{
return 1;
}
void popFront()
{
}
bool empty()
{
return true;
}
auto @system int[] opIndex()
{
{
S __r2 = this;
for (; !__r2.empty(); __r2.popFront())
{
int x = __r2.front();
}
}
return null;
}
}
void main()
{
S s = 0;
{
scope int[] __r3 = s.opIndex()[];
ulong __key4 = 0LU;
for (; __key4 < __r3.length; __key4 += 1LU)
{
int x = __r3[__key4];
}
}
return 0;
}
```

Note the difference in how the foreach code is lowered. Inside 
`opIndex`, it's lowered to the range functions. Outside, it uses the 
slice operator to switch to iterating a `scope int[]`.


If you now switch the `auto` to `int[]`, it's a segfault, because now 
the `opIndex` has a concrete return type, and it *can* use the 
`opIndex`, inside `opIndex`.


I really think the implicit slice should be revisited. It shouldn't 
happen in this case.


-Steve


Re: T[] opIndex() Error: .. signal 11

2023-10-03 Thread ryuukk_ via Digitalmars-d-learn

On Tuesday, 3 October 2023 at 15:12:34 UTC, Joel wrote:
The following program crashes, but doesn’t if I change (see 
title) T[] to auto. The program doesn’t even use that 
method/function. What’s the story?


```d
// Adding program - literal functions

import std;

struct List(T) {
class Node {
T data;
Node next;
this(T data) {
this.data=data;
}
}
string title;
size_t length;
Node head;
this(string title, T[] data...) {
this.title=title;
length=data.length;
if (length) {
head=new Node(data[0]);
auto cur=head;
data[1..$].each!((d) {
cur.next=new Node(d);
cur=cur.next;
});
}
}
bool empty() { return head is null; }
auto ref front() { return head.data; }
void popFront() { head=head.next; }
T[] opIndex() {
return this.array;
}
auto opDollar() {
return length;
}
}

void main(string[] args) {
args.popFront;
List!int ints;
if (args.length) {
ints=List!int(args[0], args[1..$].to!(int[]));
} else{
ints=List!int("Car, and Date numbers", 1979,9,3,4,5);
}
stdout.write(ints.title, ": ");
ints.each!((i, d) {
stdout.write(d, i+1

Remove:
It didn't segfault for me, but it still didn't print what's in 
the ``ints``, but if you remove the following code:




```
   T[] opIndex() {
return this.array;
}
auto opDollar() {
return length;
}
```

..then it'll work

Sounds like a bug.. i don't use these D features, maybe someone 
else have more insights?


Either way, what a terrible experience



T[] opIndex() Error: .. signal 11

2023-10-03 Thread Joel via Digitalmars-d-learn
The following program crashes, but doesn’t if I change (see 
title) T[] to auto. The program doesn’t even use that 
method/function. What’s the story?


```d
// Adding program - literal functions

import std;

struct List(T) {
class Node {
T data;
Node next;
this(T data) {
this.data=data;
}
}
string title;
size_t length;
Node head;
this(string title, T[] data...) {
this.title=title;
length=data.length;
if (length) {
head=new Node(data[0]);
auto cur=head;
data[1..$].each!((d) {
cur.next=new Node(d);
cur=cur.next;
});
}
}
bool empty() { return head is null; }
auto ref front() { return head.data; }
void popFront() { head=head.next; }
T[] opIndex() {
return this.array;
}
auto opDollar() {
return length;
}
}

void main(string[] args) {
args.popFront;
List!int ints;
if (args.length) {
ints=List!int(args[0], args[1..$].to!(int[]));
} else{
ints=List!int("Car, and Date numbers", 1979,9,3,4,5);
}
stdout.write(ints.title, ": ");
ints.each!((i, d) {
stdout.write(d, i+1