Bug 24833 – enums with a base type with a copy / postblit ctor, opAssign, or dtor should either use them or be disallowed

Status
NEW
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2024-10-25T04:01:18Z
Last change time
2024-12-13T19:38:17Z
Keywords
safe, wrong-code
Assigned to
No Owner
Creator
Jonathan M Davis
Moved to GitHub: dmd#20538 →

Comments

Comment #0 by issues.dlang — 2024-10-25T04:01:18Z
At present, enums with a base type that has a copy constructor, postblit constructor, overloaded assignment operator, and/or destructor completely ignore those functions. E.G. --- void main() { import std.traits; static struct S { int i; void opAssign()(auto ref S rhs) { this.i = rhs.i; } this(this) { } ~this() { } } enum E : S { a = S(42) } static assert(hasElaborateAssign!S); static assert(hasElaborateCopyConstructor!S); static assert(hasElaborateDestructor!S); // These pass but should not static assert(!hasElaborateAssign!E); static assert(!hasElaborateCopyConstructor!E); static assert(!hasElaborateDestructor!E); } --- This is fundamentally broken, because any type that has any of those functions clearly was designed to have them and almost certainly will not work correctly if they are not called. I do not really see any real argument for why the current behavior is reasonable, and I expect that it's an oversight in the enum implementation, and it hasn't come up more simply because it's not very common in D to declare enums which are structs. The spec does currently mention that they are not called - https://dlang.org/spec/enum.html#enum_copying_and_assignment. However, as I understand it, that's simply because Paul Backus decided to document the current behavior rather than it being purposefully decided by someone like Walter. Now, there are obviously some complications with these functions and enum types (particularly the assignment operator) given that they're written to deal with the base type, not the enum type, requiring conversions. So, I don't know how reasonable it is to support them with enums. However, if it's not reasonable to support them, then IMHO, such structs should simply be disallowed as the base type of enums, since they cannot function properly if those functions are not called properly like they would be with the base type. A related issue is: https://issues.dlang.org/show_bug.cgi?id=24225
Comment #1 by issues.dlang — 2024-11-23T04:20:34Z
I would note that this is also a memory safety issue, since it's quite possible for the assignment operator, copy / postblit constructor, or destructor (or move constructor once we get those) to be doing something with regards to memory safety, and @trusted code within a type could depend on those functions being called. For instance, skipping these functions would screw up reference counting and potentially result in memory being freed prematurely - thus leading to freed memory being accessed. Related: https://issues.dlang.org/show_bug.cgi?id=24874
Comment #2 by robert.schadek — 2024-12-13T19:38:17Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/20538 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB