Zero fields before running field initializers in struct constructor with default : this() initializer#60471
Conversation
RikkiGibson
left a comment
There was a problem hiding this comment.
LGTM, however we did discuss offline whether it's possible to make the change simpler by keeping the existing constructor initializer code path the same and adjusting the path that adds field initializers to the body to do a special check for the default parameterless constructor. Would like to see whether any changes are made as a result of that exploration before signing off.
| comp.VerifyDiagnostics( | ||
| // (10,12): error CS0171: Field 'S1.y' must be fully assigned before control is returned to the caller | ||
| // public S1() { } | ||
| Diagnostic(ErrorCode.ERR_UnassignedThis, "S1").WithArguments("S1.y").WithLocation(10, 12), |
There was a problem hiding this comment.
Let's make sure we keep an eye out after this is merged to update the test baselines when this flows forward to 17.3/main-vs-deps.
| Diagnostic(ErrorCode.ERR_FieldInitRefNonstatic, "y1").WithArguments("S1.y1").WithLocation(3, 14), | ||
| // (3,14): error CS0170: Use of possibly unassigned field 'y1' | ||
| // int x1 = y1 + 1; | ||
| Diagnostic(ErrorCode.ERR_UseDefViolationField, "y1").WithArguments("y1").WithLocation(3, 14), |
There was a problem hiding this comment.
Many of the new [Theory] tests will have divergent diagnostics when this flows to main-vs-deps. The tests can still be written this way, just wanted to call it out.
There was a problem hiding this comment.
It looks like there are 5 or so tests that will be affected. But it might simpler if I leave these combined for now, then split them when merging into main.
| bodyBinder.GetDeclaredLocalsForScope(constructor), | ||
| skipInitializer ? new BoundNoOpStatement(constructor, NoOpStatementFlavor.Default) | ||
| : initializer == null ? null : bodyBinder.BindConstructorInitializer(initializer, diagnostics), | ||
| initializer == null ? null : bodyBinder.BindConstructorInitializer(initializer, diagnostics), |
The current approach combines the constructor initializer and body (into a In reply to: 925601353 |
|
I also like the clean-up in the Binder and prefer if we go with that. In reply to: 1083707550 |
| { | ||
| int x = 1; | ||
| int y; | ||
| public S(int y) : this() |
There was a problem hiding this comment.
Yes, previously:
(6,12): error CS0171: Field 'S.y' must be fully assigned before control is returned to the caller
public S(int y) : this()
(15,12): error CS0171: Field 'R.y' must be fully assigned before control is returned to the caller
public R(int y) : this()
…ros fields before field initializers
|
The failure in Test_Windows_Desktop_Spanish_Release_64 appears to be a known infrastructure issue. |
From the dotnet/csharplang proposal:
Fixes #58790