December 14, 2021

On Tuesday, 14 December 2021 at 16:45:20 UTC, Stanislav Blinov wrote:

>

On Tuesday, 14 December 2021 at 16:17:30 UTC, user1234 wrote:

>

There no issue there, this not used at all. Segfaults will start to happen, as expected, when trying to access a member variable.

No, they wouldn't, per current spec.

https://dlang.org/spec/declaration.html#void_init
https://dlang.org/spec/function.html#safe-functions

Per that, this is @safe:

import core.sys.linux.fcntl;
import core.sys.linux.unistd;

struct MMap
{
    private int fd;
    @disable this();
    @disable this(this);
    // ...
    ~this() @trusted {
        if (isValid) {
            auto msg = "closed";
            size_t len = msg.length;
            write(fd, &len, len.sizeof);
            write(fd, msg.ptr, len);
            close(fd);
        }
    }

    private bool isValid() const @trusted {
        import core.stdc.errno;
        return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
    }
}

void main() @safe
{
    // ...
    MMap mm = void; // currently allowed because MMap doesn't contain indirections
    // ...

} // nothing may happen, or may crash, or may write into someone else's memory, or to stdout...

Prolly should make an enhancement request for spec of @safe to disallow void initialization altogether.

This is one of the problems that DIP 0135 (@system variables) aims to solve. Specifically, it is the same class of problem described in the ShortString example, where memory safety relies on the integrity of non-pointer data.

December 15, 2021

On Tuesday, 14 December 2021 at 15:51:58 UTC, Atila Neves wrote:

>

On Tuesday, 14 December 2021 at 12:14:52 UTC, Tejas wrote:

>

On Thursday, 11 November 2021 at 09:24:17 UTC, Atila Neves wrote:

>

On Wednesday, 10 November 2021 at 13:52:26 UTC, deadalnix wrote:

>

[...]

@disable this();, but you knew that. It's true that requiring a programmer to do something to prevent bugs is a terrible idea. Sigh.

Sorry for reviving this thread, was just sifting through...
The following code also outputs dtor!, unfortunately :(


import std.stdio:writeln;

struct S{
	@disable this();
	~this(){
		writeln("dtor!");
	}
}	

void main(){
	S s = void;
}

Compiler :
LDC - the LLVM D compiler (1.25.0):
based on DMD v2.095.1 and LLVM 11.1.0

Is there an issue for this?

Apparently one will have to develop a program that will showcase UB with this type of code. Only then will a bug report be accepted.

And I lack the skill to do that :(

December 15, 2021

On Tuesday, 14 December 2021 at 12:14:52 UTC, Tejas wrote:

>

Sorry for reviving this thread, was just sifting through...
The following code also outputs dtor!, unfortunately :(


import std.stdio:writeln;

struct S{
	@disable this();
	~this(){
		writeln("dtor!");
	}
}	

void main(){
	S s = void;
}

Compiler :
LDC - the LLVM D compiler (1.25.0):
based on DMD v2.095.1 and LLVM 11.1.0

This has come up in the past and typically folks have agreed that once you used void initialization it is your problem to make sure that the object is valid before destruction. I, personally, do not agree with that; since you are bypassing construction, you should also bypass destruction, however, an argument can be made for both sides.

My perspective is that currently you have an easy way to bypass destruction but you need to do the union trick to bypass destruction. I would vote for having a dip that would somehow make it easy to express the intent that you want to avoid destruction for a specific object.

December 15, 2021

On Wednesday, 15 December 2021 at 08:27:25 UTC, RazvanN wrote:

>

On Tuesday, 14 December 2021 at 12:14:52 UTC, Tejas wrote:

>

[...]

This has come up in the past and typically folks have agreed that once you used void initialization it is your problem to make sure that the object is valid before destruction. I, personally, do not agree with that; since you are bypassing construction, you should also bypass destruction, however, an argument can be made for both sides.

My perspective is that currently you have an easy way to bypass destruction but you need to do the union trick to bypass destruction. I would vote for having a dip that would somehow make it easy to express the intent that you want to avoid destruction for a specific object.

Typo! The first sentence of the last paragraph should be: "My perspective is that currently you have an easy way to bypass
construction but you need to do the union trick to bypass destruction"

December 15, 2021
On Wednesday, 15 December 2021 at 08:27:25 UTC, RazvanN wrote:
> I would vote for having a dip that would somehow make it easy to express the intent that you want to avoid destruction for a specific object.

What about permitting 'union { S s; }' at function scope?  It is a slightly odd syntax; but it it consistent and, well, if you are trying to void initialise or bypass deconstruction, you are already plumbing dirty parts of the language.
December 15, 2021
On Wednesday, 15 December 2021 at 08:27:25 UTC, RazvanN wrote:
> My perspective is that currently you have an easy way to bypass destruction but you need to do the union trick to bypass destruction. I would vote for having a dip that would somehow make it easy to express the intent that you want to avoid destruction for a specific object.

(In particular, I agree with the other folks you cite that void-initialisation should not bypass destruction.  To me, void-initialisation is not a way of _bypassing_ construction, but is an _optimization_ you can apply when the compiler tried to construct some object more than once.

But I agree that it should be possible to bypass destruction.)
December 15, 2021
On 12/14/2021 7:51 AM, Atila Neves wrote:
> On Tuesday, 14 December 2021 at 12:14:52 UTC, Tejas wrote:
>> Sorry for reviving this thread, was just sifting through...
>> The following code also outputs `dtor!`, unfortunately :(
>>
>> ```d
>>
>> import std.stdio:writeln;
>>
>> struct S{
>>     @disable this();
>>     ~this(){
>>         writeln("dtor!");
>>     }
>> }
>>
>> void main(){
>>     S s = void;
>> }
>>
>> ```
>>
>> Compiler :
>> LDC - the LLVM D compiler (1.25.0):
>>   based on DMD v2.095.1 and LLVM 11.1.0
> 
> Is there an issue for this?

Should there be? Using void initialization means it's up to the user to initialize it properly before use.
December 15, 2021
On 12/14/2021 4:51 AM, Stanislav Blinov wrote:
>> That's what I did after reading your message, with the bonus of slapping @safe on `S.__dtor` as well ;)
>>
>> ```d
>> import std.stdio:writeln;
>>
>> struct S{
>>     @disable this();
>>     ~this()@safe/*now @safe*/{
>>         writeln("dtor!");
>>     }
>> }
>>
>> void main()@safe/* now @safe*/{
>>     S s = void;
>> }
>> ```
>>
>> It defeated `@safe` ;_;
> 
> Oh, right, S doesn't have any pointers. @safe only cares about void-initializing those.

@safe is about memory safety. The example code is not memory unsafe.
December 15, 2021
On 12/14/2021 6:05 AM, Paul Backus wrote:
> If you can find a way to actually cause UB in @safe code, you should post it on the bug tracker. However, this example does not qualify.

UB is not quite right. It's about memory unsafety. Another way to illustrate this is:

  import std.stdio;

  @safe void main() {
    int x = void;
    writeln(x);
  }

will print garbage, but it is not unsafe.
December 15, 2021
On Wednesday, 15 December 2021 at 10:17:49 UTC, Walter Bright wrote:
> On 12/14/2021 6:05 AM, Paul Backus wrote:
>> If you can find a way to actually cause UB in @safe code, you should post it on the bug tracker. However, this example does not qualify.
>
> UB is not quite right. It's about memory unsafety. Another way to illustrate this is:
>
>   import std.stdio;
>
>   @safe void main() {
>     int x = void;
>     writeln(x);
>   }
>
> will print garbage, but it is not unsafe.

A violation of memory unsafety is either (a) UB or (b) behavior that is not UB itself, but allows UB to occur in @safe code (i.e., it violates one of the language's safety invariants). So if you've found a memory safety violation, it is always possible to use it to create an example of UB in @safe code.

The above example is neither memory-unsafe nor UB. According to the spec, it prints an implementation-defined value of type int.