-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support SetsRequiredMembersAttribute #60392
Support SetsRequiredMembersAttribute #60392
Conversation
@RikkiGibson @jcouv please take a look. |
The SetsRequiredMembersAttribute prevents the compiler from checking the required member list of a type when calling that constructor, and suppresses any errors from a base type's list being invalid. Specification: https://github.com/dotnet/csharplang/blob/main/proposals/required-members.md Test plan: dotnet#57046
3d01290
to
7761d6b
Compare
@jcouv @RikkiGibson please take a look |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just had a few comments so far. Haven't looked at the tests yet--possible those will hold answers to some of the questions anyway. Will review the tests a little later this afternoon.
src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbolBase.cs
Show resolved
Hide resolved
src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbolBase.cs
Show resolved
Hide resolved
src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbolBase.cs
Show resolved
Hide resolved
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordCopyCtor.cs
Show resolved
Hide resolved
@RikkiGibson @jcouv please take a look. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM aside from some minor comments.
@jcouv for the second review please. |
src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordCopyCtor.cs
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done with review pass (iteration 7)
Just curious, what was the problem you ran into that the used assemblies leg detected? In reply to: 1083559918 |
d9da29b. It wasn't happy about mismatched collection of dependencies. |
…operties should be considered initialized.
@RikkiGibson @jcouv please take another look. |
src/Compilers/CSharp/Test/Symbol/Symbols/RequiredMembersTests.cs
Outdated
Show resolved
Hide resolved
I was contemplating whether it's reasonable for constructors to delegate to 'SetRequiredMembers' constructors, without being 'SetsRequiredMembers' themselves. For example, test class Base
{
public required string Prop1 { get; set; }
[SetsRequiredMembers]
public Base() { Prop1 = "a"; }
public Base(int unused) { }
}
class Derived : Base
{
public required string Prop2 { get; set; }
// maybe compiler needs to emit [SetsRequiredMembersOf(typeof(Base))] here?
public Derived() : base() { }
// maybe compiler needs to emit [SetsRequiredMembersOf(typeof(Base))] here?
public Derived(int unused) : this() { }
}
class Program
{
static void Main()
{
// how do we realize the user doesn't need to set Prop1?
var derived = new Derived() { Prop2 = "a" };
// we seem even more at sea here :)
var derived2 = new Derived(1) { Prop2 = "a" };
}
} The metadata encoding spec doesn't appear to be able to represent this as written. Did I miss something? I could imagine complex type hierarchies peppering in 'SetsRequiredMembers' at arbitrary levels. It feels like representing that accurately would require tracking the most-derived type in the hierarchy which has the attribute. When the compiler binds a constructor it can determine which base constructor it ultimately delegates to, perhaps using a similar mechanism as is currently used to prevent cycles in constructor initializers. However, it feels to me like it would be a very reasonable starting place to require any constructors which delegate to a 'SetsRequiredMembers' constructor to also have 'SetsRequiredMembers'. This would make it an all-or-nothing thing down the hierarchy to start with, and I think it leaves the space open for us to add something like what I described above later on. |
@RikkiGibson we could do that. My initial thought was, however, not to do any form of restrictions. In short, in your example, there is no way to know that |
…o setsrequiredmembers * upstream/features/required-members: (808 commits) Update for definite assignment changes Remove duplicate package references (dotnet#60658) Formatting and code generation options (dotnet#60127) Trim unnessasary leading lines when removing usings (dotnet#60672) Pass options to FixAllAsync, simplify CodeAction registration (dotnet#60665) Fallout Lint Restore CodeStyle test projects Update struct field definite assignment tests Global indentation options - take 2 (dotnet#60565) Run continuation to dispose of cancellation token source (dotnet#60653) Fixup Update tests Cleanup Cleanup move properties Delay starting the work to scan for todo-items Simplify Clean up syntax context Clean up syntax context ...
…n chaining to a constructor with the attribute. Add more tests.
@RikkiGibson @jcouv please take another look. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM Thanks (iteration 12)
…o setsrequiredmembers * upstream/features/required-members: (66 commits) Fix dotnet#55183: Add SymbolVisitor<TArgument, TResult> (dotnet#56530) Simplifier options (dotnet#60174) Remove duplicated asset Do not try to refcount solution syncing when communicating with OOP Delay symbol-search index updating until solution is fully loaded. add more miscellaneous tests for checked operators (dotnet#60727) Support checked operators in explicit interface implementation (dotnet#60715) Avoid formatting diagnostics with raw strings (dotnet#60655) Make heading levels for warning waves documentation consistent (dotnet#60721) Clean up IDiagnosticService extension methods Remove #nullable enable Add integration test to flag MEF composition breaks Generate static abstract interface members correctly (dotnet#60618) Merge release/dev17.2 to main (dotnet#60682) Fix FAR on checked operators (dotnet#60698) Add implement interface support for checked operators and cast operators (dotnet#60719) Update csc.dll path in launch.json (dotnet#60663) Grab bag of UTF8 string support in IDE features (dotnet#60599) Allow code actions to retrieve options for any language (dotnet#60697) Fix flaky VSTypeScriptHandlerTests (dotnet#60706) ...
} | ||
else if (initializerKind == (int)SyntaxKind.BaseConstructorInitializer) | ||
{ | ||
// If we chained to a `base` constructor, a SetsRequiredMembers attribute applies to the base type's required members only, and the current type's required members |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like the code paths which handle SetsRequiredMembers on base
but not this
could be eliminated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what you mean by this? Can you elaborate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wrong about this. I recall now that you're still expected to get a different initial state when the 'this()' constructor you chain to has SetsRequiredMembers, versus the 'base()' constructor you chain to having it.
For some reason I expected a further simplification in NullableWalker to fall out of the decision to require SetsRequiredMembers to be used on constructors which chaining to a SetsRequiredMembers constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with one comment which can be addressed in a subsequent PR if you prefer.
The SetsRequiredMembersAttribute prevents the compiler from checking the required member list of a type when calling that constructor, and suppresses any errors from a base type's list being invalid.
Specification: https://github.com/dotnet/csharplang/blob/main/proposals/required-members.md
Test plan: #57046