Thread overview
[Issue 15542] pure function with no argument returning different values (with void-initialized static array)
Jan 19, 2016
Marc Schütz
Nov 23, 2017
RazvanN
Nov 23, 2017
Jonathan M Davis
Nov 23, 2017
Jonathan M Davis
Nov 23, 2017
ag0aep6g@gmail.com
Nov 23, 2017
Jonathan M Davis
Nov 27, 2017
ag0aep6g@gmail.com
Jan 05, 2023
ag0aep6g
Jun 28, 2023
RazvanN
January 19, 2016
https://issues.dlang.org/show_bug.cgi?id=15542

Marc Schütz <schuetzm@gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |schuetzm@gmx.net

--- Comment #1 from Marc Schütz <schuetzm@gmx.net> ---
Quoting https://dlang.org/spec/declaration.html#VoidInitializer :
"If the Initializer is void, however, the variable is not initialized. If its
value is used before it is set, undefined program behavior will result."

Note how it says "undefined program behavior", not even "undefined value". So technically, the current behaviour is within the spec.

--
November 23, 2017
https://issues.dlang.org/show_bug.cgi?id=15542

RazvanN <razvan.nitu1305@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |razvan.nitu1305@gmail.com

--- Comment #2 from RazvanN <razvan.nitu1305@gmail.com> ---
Maybe void initialization should be disallowed in pure functions.

--
November 23, 2017
https://issues.dlang.org/show_bug.cgi?id=15542

Jonathan M Davis <issues.dlang@jmdavisProg.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |issues.dlang@jmdavisProg.co
                   |                            |m

--- Comment #3 from Jonathan M Davis <issues.dlang@jmdavisProg.com> ---
I would argue that this simply isn't a bug. void initializers are an @system way to allow you to delay initialization so that you don't default-initialize a variable and then assign to it again shortly thereafter. You're never supposed to actually use the value of a void initialized variable any more than it's advised to use a variable in C/C++ that you didn't initialize and thus is filled with garbage. The fact that the pure function returns different values for different calls is simply a result of failing to do your due diligence with an @system function and make sure that it's actually @safe in spite of the @system operations that it's doing. You'd have the same problem if you made it do pointer arithmetic that made it point past the end of a buffer. There are plenty of other ways to end up pointing to varying things whenever you violate @safe. There's nothing particularly special about the void initializer in that regard. You'd basically have to force all pure functions to be @safe if you wanted to avoid this problem.

--
November 23, 2017
https://issues.dlang.org/show_bug.cgi?id=15542

Jonathan M Davis <issues.dlang@jmdavisProg.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |issues.dlang@jmdavisProg.co
                   |                            |m

--- Comment #3 from Jonathan M Davis <issues.dlang@jmdavisProg.com> ---
I would argue that this simply isn't a bug. void initializers are an @system way to allow you to delay initialization so that you don't default-initialize a variable and then assign to it again shortly thereafter. You're never supposed to actually use the value of a void initialized variable any more than it's advised to use a variable in C/C++ that you didn't initialize and thus is filled with garbage. The fact that the pure function returns different values for different calls is simply a result of failing to do your due diligence with an @system function and make sure that it's actually @safe in spite of the @system operations that it's doing. You'd have the same problem if you made it do pointer arithmetic that made it point past the end of a buffer. There are plenty of other ways to end up pointing to varying things whenever you violate @safe. There's nothing particularly special about the void initializer in that regard. You'd basically have to force all pure functions to be @safe if you wanted to avoid this problem.

--
November 23, 2017
https://issues.dlang.org/show_bug.cgi?id=15542

ag0aep6g@gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ag0aep6g@gmail.com

--- Comment #4 from ag0aep6g@gmail.com ---
(In reply to Marc Schütz from comment #1)
> Note how it says "undefined program behavior", not even "undefined value". So technically, the current behaviour is within the spec.

(In reply to Jonathan M Davis from comment #3)
> You'd basically have to force all pure functions to be @safe if you wanted to avoid this problem.

Note that the test code still compiles even when you add `@safe`. Void initialization of value types is considered `@safe`.

--
November 23, 2017
https://issues.dlang.org/show_bug.cgi?id=15542

--- Comment #5 from Jonathan M Davis <issues.dlang@jmdavisProg.com> ---
(In reply to ag0aep6g from comment #4)
> Note that the test code still compiles even when you add `@safe`. Void initialization of value types is considered `@safe`.

Hmmm. I'm inclined to think that that's a bug, but I suppose that it depends on what types it lets you void initialize. I guess that if it's just ints and floats and whatnot in the struct, then that doesn't actually pose a memory safety problem and wouldn't need to be marked @system, but it still seems wrong.

Either way, I think that it's pretty clear that you're dealing with undefined behavior if you use a void-initialized object before giving it a proper value, and I don't see any reason to treat pure as special in that regard. As long as the variable is given a proper value, then there is no purity issue, and regardless of  whether @safety concerns really apply in all cases with void-inialization, the concept is basically the same. When the programmer void-initializes something, they're essentially promising that they'll do the right thing and give the variablie a value before using it so that the normal guarantees are in place.

--
November 24, 2017
https://issues.dlang.org/show_bug.cgi?id=15542

Steven Schveighoffer <schveiguy@yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |schveiguy@yahoo.com
         Resolution|---                         |INVALID

--- Comment #6 from Steven Schveighoffer <schveiguy@yahoo.com> ---
(In reply to Jonathan M Davis from comment #5)
> (In reply to ag0aep6g from comment #4)
> > Note that the test code still compiles even when you add `@safe`. Void initialization of value types is considered `@safe`.
> 
> Hmmm. I'm inclined to think that that's a bug, but I suppose that it depends on what types it lets you void initialize. I guess that if it's just ints and floats and whatnot in the struct, then that doesn't actually pose a memory safety problem and wouldn't need to be marked @system, but it still seems wrong.

That particular case is not a bug. It's perfectly memory safe to look at/use your own stack frame without initialization, as long as data doesn't contain a reference.

> Either way, I think that it's pretty clear that you're dealing with undefined behavior if you use a void-initialized object before giving it a proper value, and I don't see any reason to treat pure as special in that regard.

Agree. This is not a bug, just bad code.

--
November 27, 2017
https://issues.dlang.org/show_bug.cgi?id=15542

--- Comment #7 from ag0aep6g@gmail.com ---
(In reply to Steven Schveighoffer from comment #6)
> It's perfectly memory safe to look at/use
> your own stack frame without initialization, as long as data doesn't contain
> a reference.

It still has undefined behavior, and `@safe` is supposed to rule out undefined behavior. So, according to the spec, `@safe` should prevent the code from compiling.

This is all about `@safe` and has nothing to do with `pure`, though. I've filed a new issue: issue 18016.

--
January 05, 2023
https://issues.dlang.org/show_bug.cgi?id=15542

ag0aep6g <ag0aep6g@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|INVALID                     |---

--- Comment #8 from ag0aep6g <ag0aep6g@gmail.com> ---
This issue was closed because the presented program was invalid at the time. It was invalid because using the value of an uninitialized variable used to trigger undefined behavior. Walter has since changed the spec, allowing such use of uninitialized variables [1].

The presented program does not trigger undefined behavior anymore, at least not in the way it did when the issue was closed. So the reason for closing is no longer true. Reopening.


[1] https://github.com/dlang/dlang.org/pull/2260

--
June 28, 2023
https://issues.dlang.org/show_bug.cgi?id=15542

RazvanN <razvan.nitu1305@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jeff@thefirst.org

--- Comment #9 from RazvanN <razvan.nitu1305@gmail.com> ---
*** Issue 14823 has been marked as a duplicate of this issue. ***

--