diff --git a/compiler/src/dmd/mustuse.d b/compiler/src/dmd/mustuse.d index fc7618bfc0e..8ad89ebbad4 100644 --- a/compiler/src/dmd/mustuse.d +++ b/compiler/src/dmd/mustuse.d @@ -38,7 +38,10 @@ bool checkMustUse(Expression e, Scope* sc) { auto sd = sym.isStructDeclaration(); // isStructDeclaration returns non-null for both structs and unions - if (sd && hasMustUseAttribute(sd, sc) && !isAssignment(e) && !isIncrementOrDecrement(e)) + if (sd && hasMustUseAttribute(sd, sc) + && !isAssignment(e) + && !isCtorAssignment(e) + && !isIncrementOrDecrement(e)) { error(e.loc, "ignored value of `@%s` type `%s`; prepend a `cast(void)` if intentional", Id.udaMustUse.toChars(), e.type.toPrettyChars(true)); @@ -104,6 +107,25 @@ private bool isAssignment(Expression e) return false; } +/** + * Returns: true if `e` is + * `(this.field = typeof(this.field).init, this.field.__ctor(arg))` + */ +private bool isCtorAssignment(Expression e) +{ + import dmd.id : Id; + + auto comma = e.isCommaExp(); + if (!comma) + return false; + if (!isAssignment(comma.e1)) + return false; + auto call = comma.e2.isCallExp(); + if (!call) + return false; + return call.f.ident == Id.ctor; +} + /** * Returns: true if id is the identifier of an assignment operator overload. */ diff --git a/compiler/test/compilable/must_use_assign.d b/compiler/test/compilable/must_use_assign.d index bd1983a40e6..6fae4a5e423 100644 --- a/compiler/test/compilable/must_use_assign.d +++ b/compiler/test/compilable/must_use_assign.d @@ -7,3 +7,17 @@ void test() S a, b; a = b; } + +@mustuse struct Inner +{ + this(int n) {} +} + +struct Outer +{ + Inner inner; + this(int n) + { + this.inner = n; + } +}