-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Create synthesized record constructor #40625
Conversation
59e8ec1
to
95a6de9
Compare
https://github.com/dotnet/csharplang/blob/master/proposals/records-wip.md doesn't say anything about a constructor. |
}"); | ||
comp.VerifyDiagnostics(); | ||
var c = comp.GlobalNamespace.GetTypeMember("C"); | ||
var ctors = c.GetMembers(".ctor"); |
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.
Assert ctors.Length
? #Resolved
Spec work at dotnet/csharplang#3076 |
src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
Show resolved
Hide resolved
src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
Show resolved
Hide resolved
@dotnet/roslyn-compiler for one more review |
@@ -1,5 +1,7 @@ | |||
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | |||
|
|||
#nullable enable |
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.
In the future, please consider doing any nullable changes for a full file as a separate commit, so it's easy to see what's nullable annotation changes and the actual work being done in the PR.
@@ -199,7 +201,7 @@ public bool SetNullableContext(byte? value) | |||
_flags = new Flags(specialType, typeKind); | |||
|
|||
var containingType = this.ContainingType; | |||
if ((object)containingType != null && containingType.IsSealed && this.DeclaredAccessibility.HasProtected()) | |||
if (containingType?.IsSealed == true && this.DeclaredAccessibility.HasProtected()) |
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.
Nit: Our general approach to nullable annotating has been to keep changes minimal. If you're going to go as far as to use ?.
, you may was well go all the way to pattern matching.
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.
This is minimal only because the conversion was producing a nullable warning.
@@ -1528,7 +1531,7 @@ private void CheckMemberNameConflicts(DiagnosticBag diagnostics) | |||
|
|||
var conversion = symbol as SourceUserDefinedConversionSymbol; | |||
var method = symbol as SourceMemberMethodSymbol; | |||
if ((object)conversion != null) | |||
if (!(conversion is null)) |
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.
!(conversion is null) [](start = 24, length = 21)
Consider is object
instead.
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.
Never!
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.
When you say never, you're being inconsistent with the rest of the compiler codebase.
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 am not convinced by the assertion that is object
is a clear and straightforward way to test for null.
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.
There are plenty of places we don't use is object
in the code base today. Until we settle on a single pattern, any of them are acceptable.
@@ -1559,7 +1562,7 @@ private void CheckMemberNameConflicts(DiagnosticBag diagnostics) | |||
// Do not add the conversion to the set of previously-seen methods; that set | |||
// is only non-conversion methods. | |||
} | |||
else if ((object)method != null) | |||
else if (!(method is null)) |
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.
Same here.
{ | ||
diagnostics.Add(ErrorCode.ERR_PartialMethodMustHaveLatent, method.Locations[0], method); | ||
} | ||
else if ((object)method.OtherPartOfPartial != null && MemberSignatureComparer.ConsideringTupleNamesCreatesDifference(method, method.OtherPartOfPartial)) | ||
else if (!(method.OtherPartOfPartial is null) && MemberSignatureComparer.ConsideringTupleNamesCreatesDifference(method, method.OtherPartOfPartial)) |
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.
is object
src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedRecordConstructor.cs
Show resolved
Hide resolved
Done review pass (commit 4) |
@agocke still waiting for this to be addressed before approving: #40625 (comment) |
@333fred done |
@@ -1303,14 +1306,14 @@ private MembersAndInitializers GetMembersAndInitializers() | |||
AddDeclarationDiagnostics(diagnostics); | |||
diagnostics.Free(); | |||
|
|||
return membersAndInitializers; | |||
return _lazyMembersAndInitializers!; |
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.
_lazyMembersAndInitializers [](start = 19, length = 27)
Was this change needed?
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.
Probably not. I think I misread the early return there.
var memberSignatures = new HashSet<Symbol>(members, MemberSignatureComparer.DuplicateSourceComparer); | ||
|
||
var ctor = new SynthesizedRecordConstructor(this, binder, paramList, diagnostics); | ||
if (!memberSignatures.Contains(ctor)) |
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.
Rather than constructing a HashSet<>
, would it be more efficient to just call members.Contains(ctor)
?
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.
But I don't want to know if it has the exact symbol, I want to know if it has any symbol with a conflicting signature.
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.
members.Contains(ctor, MemberSignatureComparer.DuplicateSourceComparer)
In reply to: 367670582 [](ancestors = 367670582)
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.
Right, a linear walk. But this is just the ctor. I'm also gonna need to query for the other methods, like the generated properties, equals, hashcode, etc.
|
||
namespace Microsoft.CodeAnalysis.CSharp.UnitTests | ||
{ | ||
public class RecordTests : CompilingTestBase |
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.
RecordTests [](start = 17, length = 11)
Why create a new class rather than adding to Semantics.RecordTests
?
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 splitting apart the checks of the symbol API from behavioral checks.
This just adds a synthesized symbol (no body) for the constructor
Relates to #40726 (test plan for records)