July 26, 2019
On 26.07.19 16:47, FeepingCreature wrote:
> On Friday, 26 July 2019 at 14:19:11 UTC, ag0aep6g wrote:
[...]
>> The pain points:
>> 1) The spec doesn't say clearly when union fields are considered initialized.
>> 2) DMD allows @safe access of (uninitialized) immutable union fields.
>> 3) __ctor can be called on an existing instance in @safe code. That's clearly a bug.
> 
> I think you are just seriously overestimating the D spec.

Overestimating? I'm saying that it's not good enough.

> Note that undefined behavior is a term of art arising from C/C++, referring to behavior explicitly called out as open to the compiler implementation. __ctor is not undefined behavior; I'd call it "unofficial behavior". The spec doesn't mention it.

Undefined behavior isn't something to be filled by an implementation. Undefined behavior is given to operations that are specced as invalid. If you rely on undefined behavior, you don't have a valid program in the specced language anymore.

An implementation is of course free to assign meaning to an originally invalid operation, but in doing so it creates a (superset) dialect of the language.

And sure, you can write invalid programs that seem to happen to work as you want when compiled with DMD/LDC/GDC. I don't think that should be considered good or normal. If relying on undefined behavior is necessary, that just shows that D still has a long way to go.

> It so happens that defining a constructor, which validly initializes an immutable field, also defines a magical added function __ctor, on which the spec says nothing, but which happens to have the same effect as the constructor. Such a function could not be written normally, but it appears anyways.

As shown initially, if you don't mind relying on UB, you can also just cast.
July 26, 2019
On Friday, 26 July 2019 at 15:32:49 UTC, ag0aep6g wrote:
> As shown initially, if you don't mind relying on UB, you can also just cast.

As *immediately answered*, no you *can't*. You can't write a generic function that assigns a new value to a pointer with cast, because the immutable may be on a field, and in any case the value may have assignment disabled.
July 26, 2019
On 26.07.19 17:35, FeepingCreature wrote:
> On Friday, 26 July 2019 at 15:32:49 UTC, ag0aep6g wrote:
>> As shown initially, if you don't mind relying on UB, you can also just cast.
> 
> As *immediately answered*, no you *can't*. You can't write a generic function that assigns a new value to a pointer with cast, because the immutable may be on a field, and in any case the value may have assignment disabled.
struct S { immutable int i; @disable void opAssign(S); }
void f(S* ptr)
{
    * cast(ubyte[S.sizeof]*) ptr = cast(ubyte[S.sizeof]) S(5);
}
July 26, 2019
On Friday, 26 July 2019 at 15:55:14 UTC, ag0aep6g wrote:
> On 26.07.19 17:35, FeepingCreature wrote:
>> On Friday, 26 July 2019 at 15:32:49 UTC, ag0aep6g wrote:
>>> As shown initially, if you don't mind relying on UB, you can also just cast.
>> 
>> As *immediately answered*, no you *can't*. You can't write a generic function that assigns a new value to a pointer with cast, because the immutable may be on a field, and in any case the value may have assignment disabled.
> struct S { immutable int i; @disable void opAssign(S); }
> void f(S* ptr)
> {
>     * cast(ubyte[S.sizeof]*) ptr = cast(ubyte[S.sizeof]) S(5);
> }

Ah, good point. I believe this is approximately what moveEmplace does anyways. (Except with a memcpy.)
1 2
Next ›   Last »