From 09d5630cc064129c9595f4a7b7e6a99c4b9a9584 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Sat, 13 Dec 2025 13:17:26 +0000 Subject: [PATCH 1/2] [spec/legacy] Assigning to struct rvalue --- spec/legacy.dd | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/spec/legacy.dd b/spec/legacy.dd index 89b7670d63..f8cb8b2b26 100644 --- a/spec/legacy.dd +++ b/spec/legacy.dd @@ -24,6 +24,8 @@ $(COMMENT $(TROW Escaping $(DDSUBLINK spec/attribute, scope, `scope`) data, `scope` is $(LINK2 https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1000.md, enforced) in `@safe` code, 2024) + $(TROW $(RELATIVE_LINK2 struct-assign, Assigning to struct rvalue), + Disallow for structs which overload e.g. `opAssign`, 2024) $(COMMENT Not enforced yet) $(TROW `alias` target first syntax, use `alias name = target` instead.) @@ -93,6 +95,35 @@ struct Foo } --- +$(H2 $(LNAME2 struct-assign, Assigning to struct rvalue)) + + $(P It has always been an error for POD structs to assign from an rvalue. + From the 2024 edition, it is also an error to assign from a struct rvalue when + it would call `opAssign`, `opOpAssign`, `opUnary!"++"`, or `opUnary!"--"`.) + +--- +struct S +{ + int i; + void opAssign(S s); +} + +S foo() => S.init; + +void main() +{ + foo() = S(2); // no-op +} +--- + $(P Unless an overloaded assignment has side-effects, the assignment + will have no effect and indicates a bug.) + +$(H3 Corrective Action) + + $(P If side-effects are needed, call e.g. + `opAssign` directly. Note: Calling a non-const method on a struct rvalue + $(DDSUBLINK spec/struct, member-functions, is allowed).) + $(SPEC_SUBNAV_PREV_NEXT glossary, Glossary, editions, Editions) ) From 8e9d1bd092f47f6c2fbd56ee6abd5887c324593e Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Wed, 7 Jan 2026 10:40:25 +0000 Subject: [PATCH 2/2] Restrict error to discarded assignment to struct without pointers --- spec/legacy.dd | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/spec/legacy.dd b/spec/legacy.dd index f8cb8b2b26..138ee672bc 100644 --- a/spec/legacy.dd +++ b/spec/legacy.dd @@ -97,31 +97,37 @@ struct Foo $(H2 $(LNAME2 struct-assign, Assigning to struct rvalue)) - $(P It has always been an error for POD structs to assign from an rvalue. - From the 2024 edition, it is also an error to assign from a struct rvalue when - it would call `opAssign`, `opOpAssign`, `opUnary!"++"`, or `opUnary!"--"`.) + $(P It has always been an error for $(DDSUBLINK spec/struct, POD, POD) structs + to assign from an rvalue.) + + $(P From the 2024 edition, it is an error to discard the result of an + assignment from a struct rvalue when it would call `opAssign`, `opOpAssign`, + `opUnary!"++"`, or `opUnary!"--"` and the struct has no pointer + fields:) --- struct S { int i; + void opAssign(S s); } -S foo() => S.init; +S foo(); void main() { - foo() = S(2); // no-op + foo() = S(2); // Error, possible no-op } --- - $(P Unless an overloaded assignment has side-effects, the assignment + $(P Above, unless `opAssign` mutates global data, the assignment in `main` will have no effect and indicates a bug.) $(H3 Corrective Action) - $(P If side-effects are needed, call e.g. - `opAssign` directly. Note: Calling a non-const method on a struct rvalue + $(P If a struct rvalue assignment is needed to mutate global state, either + call the operator overload method directly or use an lvalue. + Note: Calling a non-const method on a struct rvalue $(DDSUBLINK spec/struct, member-functions, is allowed).)