Report error if 'record struct' constructor calls default parameterless constructor#58339
Report error if 'record struct' constructor calls default parameterless constructor#58339cston merged 2 commits intodotnet:mainfrom
Conversation
|
|
||
| [Fact] | ||
| [WorkItem(58328, "https://github.com/dotnet/roslyn/issues/58328")] | ||
| public void ExplicitConstructors_05() |
| ERR_NewlinesAreNotAllowedInsideANonVerbatimInterpolatedString = 8967, | ||
| ERR_AttrTypeArgCannotBeTypeVar = 8968, | ||
| // WRN_AttrDependentTypeNotAllowed = 8969, // Backed out of of warning wave 6, may be reintroduced later | ||
| ERR_RecordStructConstructorCallsDefaultConstructor = 8969, // Added in 17.1 for an invalid C#10 scenario. |
There was a problem hiding this comment.
Is reusing the warning number okay here? #Resolved
There was a problem hiding this comment.
Maybe, but reusing seems unnecessary. Updated.
| bodyBinder.BindExpressionBodyAsBlock(constructor.ExpressionBody, | ||
| constructor.Body == null ? diagnostics : BindingDiagnosticBag.Discarded)); | ||
|
|
||
| bool hasAnyRecordConstructors() => |
| <value>A lambda expression with attributes cannot be converted to an expression tree</value> | ||
| </data> | ||
| <data name="ERR_RecordStructConstructorCallsDefaultConstructor" xml:space="preserve"> | ||
| <value>A 'this' initializer for a 'record struct' constructor must call the primary constructor or an explicitly declared constructor.</value> |
There was a problem hiding this comment.
A 'this' initializer for a 'record struct' constructor must call the primary constructor or an explicitly declared constructor.
The wording looks too general. The requirement is only for records with primary constructors, I think the message should reflect that. See, for example, how we do that for UnexpectedOrMissingConstructorInitializerInRecord:
<data name="ERR_UnexpectedOrMissingConstructorInitializerInRecord" xml:space="preserve">
<value>A constructor declared in a record with parameter list must have 'this' constructor initializer.</value>
</data>
``` #Closed
| && thisInitializer | ||
| && ContainingType.IsDefaultValueTypeConstructor(initializer); | ||
|
|
||
| if (skipInitializer && |
| } | ||
| record struct S4(char A, char B) | ||
| { | ||
| public S4(object o) : this() { } |
| && thisInitializer | ||
| && ContainingType.IsDefaultValueTypeConstructor(initializer); | ||
|
|
||
| if (skipInitializer && |
There was a problem hiding this comment.
The fact that skipInitializer depends on includesFieldInitializers looks suspicious. I think it is technically possible to have a primary constructor and no initializers. It would be good trying to construct a scenario like that. Consider instead using condition thisInitializer && ContainingType.IsDefaultValueTypeConstructor(initializer), I think that would exactly reflect the condition that design requires us to check.
#Closed
|
Done with review pass (commit 2) |
|
Responded to additional feedback in #58430. |
…implicit parameterless constructor (#59055) * Report error if 'record struct' constructor calls default parameterless constructor (#58339) * Improve error reporting for 'this()' initializer from 'record struct' constructor * Require definite assignment of all fields if struct includes any field initializers (#57925)
Confirmed with C# LDT:
In a
record structwith a primary constructor, explicit constructors require athis()initializer that invokes the primary constructor or another explicitly declared constructor.Fixes #58328