Bug 24225 – @safe cast from base type to enum bypasses copy ctor, identity opAssign

Status
NEW
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2023-11-03T23:25:36Z
Last change time
2024-12-13T19:31:33Z
Keywords
safe
Assigned to
No Owner
Creator
Paul Backus
Moved to GitHub: dmd#18195 →

Comments

Comment #0 by snarwin+bugzilla — 2023-11-03T23:25:36Z
Enum types in D always have trivial copy and assignment operations, regardless of their base type. Normally this is ok, because enum members are required to be compile-time constants, and cannot own any resources that require lifetime management at runtime. However, this means that casting a value from the base type to the enum type allows any user-defined copy constructors and assignment operators (including @disabled ones) to be completely bypassed. Currently, this is allowed in @safe code, as the example program below demonstrates: --- import std.stdio; struct UniqueInt { @system int n; this(int n) @safe { writefln("Construct UniqueInt(%d)", n); this.n = n; } @disable this(ref inout UniqueInt) inout; ~this() @trusted { writefln("Destroy UniqueInt(%d)", this.n); this.n = 0; } } enum E : UniqueInt { _ = UniqueInt.init } void main() @safe { import core.lifetime; UniqueInt n = 12345; E en = cast(E) n; UniqueInt n2 = move(en); } --- When compiled (with -preview=systemVariables) and run, it produces the following output: --- Construct UniqueInt(12345) Destroy UniqueInt(12345) Destroy UniqueInt(12345) Destroy UniqueInt(12345) --- The same UniqueInt is destroyed 3 times, even though only one instance is ever constructed. To prevent @safe code from bypassing user-defined assignment and copy operations, which may be relied on to maintain an object's safety invariants, casting from an enum's base type to the enum type should be made @system.
Comment #1 by robert.schadek — 2024-12-13T19:31:33Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/18195 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB