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

Add public IsInitOnly API and use it to fix code generation of 'init' #44077

Merged
merged 10 commits into from
May 13, 2020

Conversation

jcouv
Copy link
Member

@jcouv jcouv commented May 8, 2020

Question on compiler API:

  • Should the set accessor of an invalid property static int Property { get; init; } have IsInitOnly true or false? Currently, it is false, to be consistent with behavior when loading such property from PE.

IDE scenarios supported by this API: generate override, generate implementation, view metadata-as-source.

Relates to #40726 (test plan for records/init-only)

@jcouv jcouv self-assigned this May 8, 2020
@jcouv jcouv mentioned this pull request May 8, 2020
@jcouv jcouv force-pushed the init-api branch 2 times, most recently from 41f4f81 to 8c9ac79 Compare May 8, 2020 18:08
@jcouv jcouv marked this pull request as ready for review May 8, 2020 21:29
@jcouv jcouv requested review from a team as code owners May 8, 2020 21:29
@gafter
Copy link
Member

gafter commented May 8, 2020

initonly is an existing concept in ECMA-335. Unless this represents the same concept, please rename it.

@jcouv
Copy link
Member Author

jcouv commented May 9, 2020

Tagging @jaredpar since any decision we make for public API should preferably align with the language spec

initonly is an existing concept in ECMA-335. Unless this represents the same concept, please rename it.

Yes, the runtime has the concept of initonly, but C# only has the concept of readonly (ECMA-334 only mentions readonly, not initonly). It is sad that the names don't align, but I don't think it precludes the best name available at the C# level for this feature.

FWIW, I also considered IsInit and IsExternalInit (to match the modreq type). But "init-only" is the way LDM and the spec described such members (we had an explicit discussion about why the "only" part is useful/meaningful). init accessors were thought of as a shorthand for initonly set, and we may still introduce the initonly modifier methods (question is queued).

Suggestions welcome.
I will gladly leave a question open or PROTOTYPE marker to move forward.

}

[Fact]
public void ConstructorAndDestructorAreNotInitOnly()
Copy link
Contributor

@AlekseyTs AlekseyTs May 9, 2020

Choose a reason for hiding this comment

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

ConstructorAndDestructorAreNotInitOnly [](start = 20, length = 38)

Could also cover operators #Closed

var sourceModule = compilation.SourceModule;
var sourceAssembly = (SourceAssemblySymbol)sourceModule.ContainingAssembly;

var retargetingAssembly = new RetargetingAssemblySymbol(sourceAssembly, isLinked: false);
Copy link
Contributor

@AlekseyTs AlekseyTs May 9, 2020

Choose a reason for hiding this comment

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

var retargetingAssembly = new RetargetingAssemblySymbol(sourceAssembly, isLinked: false); [](start = 12, length = 89)

Please do not use this legacy way of testing retargeting. Create a scenario when the system itself creates one, a real scenario and test that. #Closed

Copy link
Member Author

Choose a reason for hiding this comment

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

I've looked at more recent retargeting tests (Fred's recent PRs) but could not figure out the key to triggering retargeting logic to kick in. I tried tracing it back (seems to be triggered in ReferenceManager?).
What's a simple/modern test you'd recommend as a model for retargeting?


In reply to: 422534751 [](ancestors = 422534751)

Copy link
Contributor

Choose a reason for hiding this comment

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

What's a simple/modern test you'd recommend as a model for retargeting?

For example, look at CodeGenTests.CustomFields_01. The 7th compilation, the commented out, is supposed to use retargeting symbols for comp1. The change in the target framework does the trick.


In reply to: 422651853 [](ancestors = 422651853,422534751)

Copy link
Member Author

@jcouv jcouv May 11, 2020

Choose a reason for hiding this comment

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

Thanks a lot. Changed the retargeting test to use that model. #Resolved

@@ -120,6 +121,39 @@ class C
RetargetingSymbolChecker.CheckSymbols(sourceNamespace.GetMember<NamedTypeSymbol>("C"), retargetingNamespace.GetMember<NamedTypeSymbol>("C"));
}

[Fact, CompilerTrait(CompilerFeature.InitOnlySetters)]
public void RetargetProperties_WithInitOnlySetter()
Copy link
Contributor

@AlekseyTs AlekseyTs May 9, 2020

Choose a reason for hiding this comment

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

RetargetProperties_WithInitOnlySetter [](start = 20, length = 37)

I suggest that we keep this test next to other InitOnly tests. #Closed

@AlekseyTs
Copy link
Contributor

AlekseyTs commented May 9, 2020

Done with review pass (iteration 3) #Closed

@@ -48,6 +48,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.NavigationBar
modifiers:=New DeclarationModifiers(isOverride:=True),
returnType:=compilation.GetSpecialType(SpecialType.System_Void),
refKind:=RefKind.None,
isInitOnly:=False,
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi May 9, 2020

Choose a reason for hiding this comment

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

this feels weird. how do we do other accessors? isn't this just a certain type of accessor, not a method? #Resolved

@@ -114,6 +114,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
modifiers: new DeclarationModifiers(isStatic, isAsync: declaredSymbol.IsAsync),
returnType: declaredSymbol.ReturnType,
refKind: default,
isInitOnly: false,
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi May 9, 2020

Choose a reason for hiding this comment

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

not really getting how methods are init-only. #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

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

Currently, only accessors can be init-only. But accessors are methods.
We have a discussion queued to discuss init-only methods more generally, but that should not affect this PR (assume that we don't have generalized init-only methods).

I can make the parameter optional, so it's not in your face at most places where it could not legitimately be set to true. Would that resolve your concern?


In reply to: 422535858 [](ancestors = 422535858)

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi May 10, 2020

Choose a reason for hiding this comment

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

Isn't init a different type of accessor entirely. I.e. a property would have three potential accessors? GetMethod/SetMethod/InitMethod? #Resolved

Copy link
Member Author

@jcouv jcouv May 10, 2020

Choose a reason for hiding this comment

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

No, it's best thought of as a modifier on set. But we shortened initonly set to init.
https://github.com/dotnet/csharplang/blob/master/proposals/init.md #Resolved

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi May 10, 2020

Choose a reason for hiding this comment

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

got it 👍 can you make it a default value? thanks! #Resolved

@CyrusNajmabadi
Copy link
Member

CyrusNajmabadi commented May 9, 2020

done with IDE pass. very large question about the design here. #Resolved

@@ -13,6 +13,7 @@
using Roslyn.Test.Utilities;
using Xunit;
using Utils = Microsoft.CodeAnalysis.CSharp.UnitTests.CompilationUtils;
using Microsoft.CodeAnalysis.Test.Utilities;
Copy link
Contributor

@AlekseyTs AlekseyTs May 11, 2020

Choose a reason for hiding this comment

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

This looks like an unnecessary change, consider reverting the file. #Closed

@AlekseyTs
Copy link
Contributor

AlekseyTs commented May 11, 2020

Done with review pass (iteration 4) #Closed

Copy link
Contributor

@AlekseyTs AlekseyTs left a comment

Choose a reason for hiding this comment

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

LGTM (iteration 5).

@jcouv
Copy link
Member Author

jcouv commented May 11, 2020

I've added a follow-up item to the test plan to resolve the naming question in API and spec.

@@ -140,6 +140,12 @@ public interface IMethodSymbol : ISymbol
/// </summary>
bool IsReadOnly { get; }

/// <summary>
/// 'init' set accessors can only be invoked during construction or in the initialization phase
Copy link
Member

Choose a reason for hiding this comment

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

set [](start = 19, length = 3)

It isn't clear if this is intended to apply only to set accessors, or if other methods may be so flagged.

Copy link
Member

@gafter gafter left a comment

Choose a reason for hiding this comment

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

:shipit:

@jcouv
Copy link
Member Author

jcouv commented May 12, 2020

FYI @AlekseyTs I made minor change to retargeting test to reflect different verification behavior on desktop versus Core

@jcouv
Copy link
Member Author

jcouv commented May 12, 2020

@CyrusNajmabadi Please take another look when you can. Thanks

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi left a comment

Choose a reason for hiding this comment

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

IDE side lgtm.

@jcouv jcouv closed this May 12, 2020
@jcouv jcouv reopened this May 12, 2020
@jcouv jcouv merged commit 6e262ac into dotnet:features/records May 13, 2020
@jcouv jcouv deleted the init-api branch May 13, 2020 20:15
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.

4 participants