digitalmars.D.learn - Limits of implicit conversion of class arrays
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (20/20) Mar 23 Is there a reason why
- Dmitry Olshansky (8/28) Mar 23 The first and second is unsound (infamously allowed in Java).
- FeepingCreature (11/46) Mar 23 Note that it works if the classes are const:
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (22/26) Mar 25 In the general case, yes. But, do you see any errors with the code
- Steven Schveighoffer (11/38) Mar 27 Yes, it's unsafe, as you can replace an element of `ds` with
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (5/23) Mar 31 This is a suggested change that when _applied_ will make the code
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 ?
Mar 23
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
Mar 23
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: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.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
Mar 23
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?
Mar 25
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:Yes, it's unsafe, as you can replace an element of `ds` with something that has no relation to `Derived`.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 } ```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". -SteveOnce 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?
Mar 27
On Thursday, 28 March 2024 at 01:53:52 UTC, Steven Schveighoffer wrote: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.```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`.
Mar 31