Re: Limits of implicit conversion of class arrays

2024-03-31 Thread Per Nordlöw via Digitalmars-d-learn
On Thursday, 28 March 2024 at 01:53:52 UTC, Steven Schveighoffer 
wrote:

```d
class Base {}
class Derived : Base {}

@safe pure nothrow unittest {
Base b;
Derived d;
b = d; // pass

Base[] bs;
Derived[] ds;
bs ~= ds; // pass
bs = ds; // fail [1], should pass
bs = cast(Base[])ds; // fail [2], should pass
}
```


Yes, it's unsafe, as you can replace an element of `ds` with 
something that has no relation to `Derived`.


This is a suggested change that when _applied_ will make the code 
unsafe yes. But the code in its current form is safe and the 
compiler could be extended to prove it.


Re: Limits of implicit conversion of class arrays

2024-03-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On Monday, 25 March 2024 at 07:16:35 UTC, Per Nordlöw wrote:
On Saturday, 23 March 2024 at 11:04:04 UTC, Dmitry Olshansky 
wrote:

The first and second is unsound (infamously allowed in Java).


In the general case, yes. But, do you see any errors with the 
code


```d
class Base {}
class Derived : Base {}

@safe pure nothrow unittest {
Base b;
Derived d;
b = d; // pass

Base[] bs;
Derived[] ds;
bs ~= ds; // pass
bs = ds; // fail [1], should pass
bs = cast(Base[])ds; // fail [2], should pass
}
```


Yes, it's unsafe, as you can replace an element of `ds` with 
something that has no relation to `Derived`.




Once you cast the slice you can populate it with Derived2 
objects that are not Derived, hence breaking type safety of 
the ds slice.


Again, in the general case, yes.

So what is different in this code example compared to the 
general case? Hint: this has overlaps with a missing compiler 
optimization in dmd (and many other statically typed languages) 
enabled by a specific kind of data flow analysis. Which one?


If there is a way to end up with a `Derived` reference to point 
at something that is not a `Derived` *without a cast* in system 
code, or *even with a cast* in safe code, then it is an error. It 
doesn't matter if you aren't actually doing it.


If you know you are not making that mistake, change it to system, 
and cast to inform the compiler that you "know what you are 
doing".


-Steve


Re: Limits of implicit conversion of class arrays

2024-03-25 Thread Per Nordlöw via Digitalmars-d-learn
On Saturday, 23 March 2024 at 11:04:04 UTC, Dmitry Olshansky 
wrote:

The first and second is unsound (infamously allowed in Java).


In the general case, yes. But, do you see any errors with the code

```d
class Base {}
class Derived : Base {}

@safe pure nothrow unittest {
Base b;
Derived d;
b = d; // pass

Base[] bs;
Derived[] ds;
bs ~= ds; // pass
bs = ds; // fail [1], should pass
bs = cast(Base[])ds; // fail [2], should pass
}
```

Once you cast the slice you can populate it with Derived2 
objects that are not Derived, hence breaking type safety of the 
ds slice.


Again, in the general case, yes.

So what is different in this code example compared to the general 
case? Hint: this has overlaps with a missing compiler 
optimization in dmd (and many other statically typed languages) 
enabled by a specific kind of data flow analysis. Which one?


Re: Limits of implicit conversion of class arrays

2024-03-23 Thread FeepingCreature via Digitalmars-d-learn
On Saturday, 23 March 2024 at 11:04:04 UTC, Dmitry Olshansky 
wrote:

On Saturday, 23 March 2024 at 09:08:45 UTC, Per Nordlöw wrote:

Is there a reason why

```d
class Base {}
class Derived : Base {}

@safe pure nothrow unittest {
Base b;
Derived d;
b = d; // pass

Base[] bs;
Derived[] ds;
bs ~= ds; // pass
bs = ds; // fail [1], should pass
bs = cast(Base[])ds; // fail [2], should pass
}
```

fails as

[1]: cannot implicitly convert expression `ds` of type 
`Derived[]` to `Base[]`

[2]: cast from `Derived[]` to `Base[]` not allowed in safe code

?


The first and second is unsound (infamously allowed in Java). 
Once you cast the slice you can populate it with Derived2 
objects that are not Derived, hence breaking type safety of the 
ds slice.


—
Dmitry Olshansky
CEO @ Glow labs
https://olshansky.me


Note that it works if the classes are const:

```d
const(Base)[] bs;
const(Derived)[] ds;
bs ~= ds; // pass
bs = ds; // pass
bs = cast(const(Base)[])ds; // pass
```

Exactly because you can't replace existing entries.


Re: Limits of implicit conversion of class arrays

2024-03-23 Thread Dmitry Olshansky via Digitalmars-d-learn

On Saturday, 23 March 2024 at 09:08:45 UTC, Per Nordlöw wrote:

Is there a reason why

```d
class Base {}
class Derived : Base {}

@safe pure nothrow unittest {
Base b;
Derived d;
b = d; // pass

Base[] bs;
Derived[] ds;
bs ~= ds; // pass
bs = ds; // fail [1], should pass
bs = cast(Base[])ds; // fail [2], should pass
}
```

fails as

[1]: cannot implicitly convert expression `ds` of type 
`Derived[]` to `Base[]`

[2]: cast from `Derived[]` to `Base[]` not allowed in safe code

?


The first and second is unsound (infamously allowed in Java). 
Once you cast the slice you can populate it with Derived2 objects 
that are not Derived, hence breaking type safety of the ds slice.


—
Dmitry Olshansky
CEO @ Glow labs
https://olshansky.me



Limits of implicit conversion of class arrays

2024-03-23 Thread Per Nordlöw via Digitalmars-d-learn

Is there a reason why

```d
class Base {}
class Derived : Base {}

@safe pure nothrow unittest {
Base b;
Derived d;
b = d; // pass

Base[] bs;
Derived[] ds;
bs ~= ds; // pass
bs = ds; // fail [1], should pass
bs = cast(Base[])ds; // fail [2], should pass
}
```

fails as

[1]: cannot implicitly convert expression `ds` of type 
`Derived[]` to `Base[]`

[2]: cast from `Derived[]` to `Base[]` not allowed in safe code

?