how is this array subtyping inside struct (bug?) possible?

mw mingwu at gmail.com
Mon Aug 10 18:29:56 UTC 2020


On Monday, 10 August 2020 at 12:03:06 UTC, Paul Backus wrote:
> On Monday, 10 August 2020 at 02:50:20 UTC, mw wrote:
>> On Monday, 10 August 2020 at 02:38:55 UTC, RazvanN wrote:
>>> On Sunday, 9 August 2020 at 21:12:58 UTC, mw wrote:
>>>
>>>> I'm *directly* access the underlying array, so why its 
>>>> length changed to 0 after writeln?
>>>>
>>> You are accessing the underlying array after it was consumed. 
>>> The line writeln(s0.fns) passes class, if you want to pass 
>>> the underlying array you should type `writeln(so.fns.array)` 
>>> and then it will not consume the array.
>>
>> I know that; and that's exactly I call it a subtyping bug: 
>> i.e. directly access & access via subtyping behave differently:
>
> You are subtyping a value type (array) with a reference type 
> (class). So when you directly access it, it's passed by value, 
> but when you pass the subtype, it's passed by reference.
>
> In other words, using `alias this` does not create a *true* 
> subtype (according to the Liskov substitution principle), 
> because it allows you to change the way the type is copied from 
> by-value to by-reference.

https://dlang.org/spec/arrays.html#dynamic-arrays

"Dynamic arrays consist of a length and a pointer to the array 
data."

I've thought, D's dynamic array is implemented as:

```  /* this is C code */
struct {
   T* ptr;
   size_t length;
}
```

And now, it shows the length is changeable via its range 
interface: so where on this range doc page this behavior on 
length is mentioned?

https://dlang.org/phobos/std_range_primitives.html

"It defines the bidirectional and forward range primitives for 
arrays: empty, front, back, popFront, popBack and save."

and where in this doc on range:

https://tour.dlang.org/tour/en/basics/ranges

it is mentioned that: the length property of the range will be 
changed after the range is "consumed" by foreach loop?

```
foreach (element; range)
{
     // Loop body...
}
it's internally rewritten similar to the following:

for (auto __rangeCopy = range;
      !__rangeCopy.empty;
      __rangeCopy.popFront())
  {
     auto element = __rangeCopy.front;
     // Loop body...
}
```




More information about the Digitalmars-d mailing list