Skip to content
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

Merged
merged 8 commits into from
Jan 17, 2020

Conversation

agocke
Copy link
Member

@agocke agocke commented Dec 27, 2019

This just adds a synthesized symbol (no body) for the constructor

Relates to #40726 (test plan for records)

@agocke agocke force-pushed the record-ctor branch 3 times, most recently from 59e8ec1 to 95a6de9 Compare January 2, 2020 04:47
@agocke agocke marked this pull request as ready for review January 5, 2020 23:25
@agocke agocke requested review from a team as code owners January 5, 2020 23:25
@gafter
Copy link
Member

gafter commented Jan 6, 2020

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");
Copy link
Member

@gafter gafter Jan 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assert ctors.Length? #Resolved

@agocke
Copy link
Member Author

agocke commented Jan 6, 2020

Spec work at dotnet/csharplang#3076

@agocke agocke requested a review from a team January 10, 2020 01:51
@agocke
Copy link
Member Author

agocke commented Jan 13, 2020

@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
Copy link
Member

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())
Copy link
Member

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.

Copy link
Member Author

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.

@333fred
Copy link
Member

333fred commented Jan 15, 2020

    internal override void ForceComplete(SourceLocation locationOpt, CancellationToken cancellationToken)

Should be annotated.


Refers to: src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs:429 in 2f48801. [](commit_id = 2f48801, deletion_comment = False)

@@ -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))
Copy link
Member

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never!

Copy link
Member

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.

Copy link
Member

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.

Copy link
Member Author

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))
Copy link
Member

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))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is object

@333fred
Copy link
Member

333fred commented Jan 15, 2020

Done review pass (commit 4)

@333fred
Copy link
Member

333fred commented Jan 16, 2020

@agocke still waiting for this to be addressed before approving: #40625 (comment)

@agocke
Copy link
Member Author

agocke commented Jan 16, 2020

@333fred done

@@ -1303,14 +1306,14 @@ private MembersAndInitializers GetMembersAndInitializers()
AddDeclarationDiagnostics(diagnostics);
diagnostics.Free();

return membersAndInitializers;
return _lazyMembersAndInitializers!;
Copy link
Member

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?

Copy link
Member Author

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))
Copy link
Member

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)?

Copy link
Member Author

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.

Copy link
Member

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)

Copy link
Member Author

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.

@cston
Copy link
Member

cston commented Jan 16, 2020

[CompilerTrait(CompilerFeature.ReadOnlyReferences)]

Is this correct?


Refers to: src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs:9 in 8d91657. [](commit_id = 8d91657, deletion_comment = False)


namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public class RecordTests : CompilingTestBase
Copy link
Member

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?

Copy link
Member Author

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.

@agocke agocke closed this Jan 17, 2020
@agocke agocke reopened this Jan 17, 2020
@agocke agocke merged commit 28b8eb5 into dotnet:features/records Jan 17, 2020
@agocke agocke deleted the record-ctor branch January 17, 2020 06:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants