Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Allowwith on anonymous types#53248

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
jcouv merged 13 commits intodotnet:mainfromjcouv:with-anonymous
May 21, 2021
Merged

Allowwith on anonymous types#53248

jcouv merged 13 commits intodotnet:mainfromjcouv:with-anonymous
May 21, 2021

Conversation

@jcouv
Copy link
Member

@jcouvjcouv commentedMay 7, 2021
edited
Loading

Test plan:#51199

Also includes:

  • disallowwith on pointer types
  • don't produce an invalid operation inwith on structures

@jcouvjcouv added this to theC# 10 milestoneMay 7, 2021
@jcouvjcouv mentioned this pull requestMay 7, 2021
92 tasks
@Youssef1313
Copy link
Member

Youssef1313 commentedMay 7, 2021
edited by jcouv
Loading

Should targetmain instead per#53125 (comment)?

We won't be usingfeatures/compiler anymore in the foreseeable future.


In reply to:834059406

@jcouvjcouv changed the base branch fromfeatures/compiler tomainMay 7, 2021 04:41
@jcouv
Copy link
MemberAuthor

jcouv commentedMay 7, 2021
edited
Loading

Indeed. This can go inmain now.


In reply to:834059943


In reply to:834059943

@CyrusNajmabadi
Copy link
Member

CyrusNajmabadi commentedMay 7, 2021
edited by jcouv
Loading

Can you check if the 'with' keyword recommender and intellisense for properties both work here? thanks!


In reply to:834646583


In reply to:834646583

Comment on lines +87 to 88
||symbol.ContainingType.IsAnonymousType
||CanSupportObjectInitializer(symbol);
Copy link
Member

Choose a reason for hiding this comment

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

Not sure if the new check should be moved toCanSupportObjectInitializer?

Choose a reason for hiding this comment

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

i'm fine with either approach.

@jcouvjcouv marked this pull request as ready for reviewMay 11, 2021 04:56
@jcouvjcouv requested review froma team ascode ownersMay 11, 2021 04:56
@jcouvjcouv self-assigned thisMay 11, 2021
/// - Regions group blocks together and represent the lifetime of locals and captures, loosely similar to scopes in C#.
/// There are different kinds of regions, <see cref="ControlFlowRegionKind"/>.
/// - <see cref="ControlFlowGraphBuilder.SpillEvalStack"/> converts values on the stack into captures. It should be
/// called before entering a new region (to avoid doing it later thus giving those captures an incorrect lifetime).
Copy link
Contributor

@AlekseyTsAlekseyTsMay 11, 2021
edited
Loading

Choose a reason for hiding this comment

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

I do not think this is 100% accurate. I suggest removing this statement. What is the "correct" lifetime region depends on particular situation. #Closed

publicoverrideIOperationVisitFlowCaptureReference(IFlowCaptureReferenceOperationoperation,int?captureIdForResult)
{
throwExceptionUtilities.Unreachable;
Debug.Assert(operation.ParentisSimpleAssignmentOperationassignment
Copy link
Contributor

@AlekseyTsAlekseyTsMay 11, 2021
edited
Loading

Choose a reason for hiding this comment

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

Debug.Assert(operation.Parent is SimpleAssignmentOperation assignment

Is this code still reachable? #Closed

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Good catch. Restored exception.

IOperationcloned;
if(operation.Type.IsValueType)
{
cloned=visitedInstance;
Copy link
Contributor

@AlekseyTsAlekseyTsMay 11, 2021
edited
Loading

Choose a reason for hiding this comment

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

cloned = visitedInstance

Is this also implementing supprt forwith on structures? It doesn't look like PR's description mentions that. #Closed

Copy link
MemberAuthor

@jcouvjcouvMay 11, 2021
edited
Loading

Choose a reason for hiding this comment

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

Yes, I noticed that for structures we were producing an invalid operation because no clone method is available. I added a test and fixed it here, but forgot to add to description.

Updated description.

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Also includes fix forwith on pointer types.

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

I'm thinking this fix may be incorrect though :-/ Do we need to capture it instead? I'll add some tests with control flow and invocations on value types....

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Never mind. I recall thatHandleObjectOrCollectionInitializer handles that.
I'll add the tests though


staticboolsetAllProperties(ImmutableArray<IOperation>initializers,ImmutableArray<IPropertySymbol>properties)
{
varset=PooledHashSet<string>.GetInstance();
Copy link
Contributor

@AlekseyTsAlekseyTsMay 11, 2021
edited
Loading

Choose a reason for hiding this comment

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

string

Why use name as the key instead of the property symbol? #Closed

Copy link
Contributor

Choose a reason for hiding this comment

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

Is it possible to have duplicate names in some error situations?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Name seems simpler.
Yes, it's possible to have duplicate names in error scenarios and this code handles that (we ignore the return value fromAdd andRemove)

Copy link
Contributor

Choose a reason for hiding this comment

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

Name seems simpler.
Yes, it's possible to have duplicate names in error scenarios and this code handles that (we ignore the return value from Add and Remove)

Does that mean that we will ignore the fact that the duplicate property isn't initialized? And perhaps not include its copy into the AnonymousObjectCreationOperation, thus failing to match the shape of the constructor?

// calls to Visit may enter regions, so we reset things
LeaveRegionsUpTo(innerCaptureRegion);

varexplicitProperties=PooledDictionary<string,IOperation>.GetInstance();
Copy link
Contributor

@AlekseyTsAlekseyTsMay 11, 2021
edited
Loading

Choose a reason for hiding this comment

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

string

Using names as keys feels fragile, I think we should use property symbols for that. #Closed

simpleAssignment.Targetis notInvalidOperation)
{
varpropertyReference=(IPropertyReferenceOperation)simpleAssignment.Target;
_=set.Remove(propertyReference.Property);
Copy link
Contributor

@AlekseyTsAlekseyTsMay 12, 2021
edited
Loading

Choose a reason for hiding this comment

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

set.Remove(propertyReference.Property);

It looks like we are making an assumption that a property that we get here belongs to the Anonymous Type that is cloned (otherwise we might be allocating captures that won't be used at the end). I think it is a valid assumption to make, but it might be worth adding an assert about that several lines above, where we asert other aspects of each property reference. Based on that assumption, consider if it is worth reducing the amount of HashSet operations (additions/removals) that we perform. For example, instead of first adding all properties into the set and then removing those that we run into, we could start with an empty set, add properties that we run into and at the end check if the count of items in the set equals to the count of properties in the type. #Closed

@AlekseyTs
Copy link
Contributor

AlekseyTs commentedMay 12, 2021
edited
Loading

    public void WithExprOnStruct_ControlFlow_NestedInitializer()

I think we would actually want to see what happens with the Control Flow Graph for this error scenario. My understanding is that the purpose of the test is to make sure the builder doesn't crash and the graph looks reasonable.


In reply to:839812576


In reply to:839812576


Refers to: src/Compilers/CSharp/Test/Semantic/Semantics/RecordStructTests.cs:6596 inf930d4b. [](commit_id =f930d4b, deletion_comment = False)

@AlekseyTs
Copy link
Contributor

AlekseyTs commentedMay 12, 2021
edited by jcouv
Loading

    var b = a with { Error = Identity(20) };

Consider testing a scenario when the target of an assignment is a name of a function that actually exists in the type. "ToString" for example.


In reply to:839819415


In reply to:839819415


In reply to:839819415


Refers to: src/Compilers/CSharp/Test/Semantic/Semantics/RecordStructTests.cs:8998 inf930d4b. [](commit_id =f930d4b, deletion_comment = False)

@AlekseyTs
Copy link
Contributor

AlekseyTs commentedMay 12, 2021
edited
Loading

    public void WithExpr_AnonymousType_NestedInitializer()

I think we would actually want to see what happens with the Control Flow Graph for this error scenario.


In reply to:839819719


Refers to: src/Compilers/CSharp/Test/Semantic/Semantics/RecordStructTests.cs:9103 inf930d4b. [](commit_id =f930d4b, deletion_comment = False)

@AlekseyTs
Copy link
Contributor

AlekseyTs commentedMay 12, 2021
edited
Loading

    public void WithExpr_AnonymousType_IndexerAccess()

I think we would actually want to see what happens with the Control Flow Graph for this error scenario.


In reply to:839820875


In reply to:839820875


In reply to:839820875


Refers to: src/Compilers/CSharp/Test/Semantic/Semantics/RecordStructTests.cs:9266 inf930d4b. [](commit_id =f930d4b, deletion_comment = False)

}
LeaveRegionsUpTo(outerCaptureRegion);

returnnewAnonymousObjectCreationOperation(initializerBuilder.ToImmutableAndFree(),semanticModel:null,operation.Syntax,operation.Type,operation.IsImplicit);
Copy link
Contributor

@AlekseyTsAlekseyTsMay 12, 2021
edited by jcouv
Loading

Choose a reason for hiding this comment

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

initializerBuilder

Consider adding an assert that the amount of initializers matches the amount of properties. #Pending

&&withExpr.Initializer.Expressions.Any()
&&withExpr.Expression==(object)syntax)
{
returntrue;
Copy link
Contributor

@AlekseyTsAlekseyTsMay 12, 2021
edited
Loading

Choose a reason for hiding this comment

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

return true;

This is for scenarios like WithExprOnStruct_ControlFlow_WithCoalescingExpressionForValue so that the verifier won't complain about the long-lived capture with "Operation [{operationIndex}] in [{getBlockId(block)}] uses capture [{id.Value}] from another region. Should the regions be merged?" assertion above.

This would be more informative if the memo actually included the actual ids so that we could look at the graph and confirm that we indeed want to suppress the assertion. #Closed

@AlekseyTs
Copy link
Contributor

AlekseyTs commentedMay 12, 2021
edited
Loading

                    IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: B, IsImplicit) (Syntax: 'Identity(this)')

Is this the capture reference that ControlFlowGraphVerifier was complaining about?


In reply to:839841592


In reply to:839841592


In reply to:839841592


Refers to: src/Compilers/CSharp/Test/Semantic/Semantics/RecordStructTests.cs:6953 inf930d4b. [](commit_id =f930d4b, deletion_comment = False)

@AlekseyTs
Copy link
Contributor

Done with review pass (commit 9)

@jcouv
Copy link
MemberAuthor

                    IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: B, IsImplicit) (Syntax: 'Identity(this)')

Yes (capture 0 used in B5)


In reply to:839841592


Refers to: src/Compilers/CSharp/Test/Semantic/Semantics/RecordStructTests.cs:6953 inf930d4b. [](commit_id =f930d4b, deletion_comment = False)

Copy link
Contributor

@AlekseyTsAlekseyTs left a comment

Choose a reason for hiding this comment

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

LGTM (commit 10)

@jcouv
Copy link
MemberAuthor

@dotnet/roslyn-compiler for a second review. Thanks

staticboolisAllowedDespiteReadonly(BoundExpressionreceiver)
{
// ok: anonymousType with { Property = ... }
if(receiverisBoundObjectOrCollectionValuePlaceholder&&receiver.Type.IsAnonymousType)
Copy link
Member

Choose a reason for hiding this comment

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

nit: it feels like the&& can be collapsed into a single recursive pattern and this can be inlined at the call site :)

ImmutableArray<BoundExpression>getAnonymousTypeValues(BoundWithExpressionwithExpr,BoundExpressionoldValue,AnonymousTypeManager.AnonymousTypePublicSymbolanonymousType,
ArrayBuilder<BoundExpression>sideEffects,ArrayBuilder<LocalSymbol>temps)
{
vardictionary=PooledDictionary<PropertySymbol,BoundExpression>.GetInstance();
Copy link
Member

@RikkiGibsonRikkiGibsonMay 18, 2021
edited by jcouv
Loading

Choose a reason for hiding this comment

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

nit: it feels like in this scenario we could use an ArrayBuilder which maps theAnonymousTypePropertySymbol.MemberIndexOpt.Value to aBoundLocal?. Also could consider exposing a member on AnonymousTypePropertySymbol likeint MemberIndex => _index. #Resolved

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Made the change. Thanks

{
vartree=compilation.SyntaxTrees[0];
SyntaxNodesyntaxNode=GetSyntaxNodeOfTypeForBinding<TSyntaxNode>(GetSyntaxNodeList(tree));
Debug.Assert(syntaxNodeis notnull,"Did you forget to place /*<bind>*/ comments in your source?");
Copy link
Member

@RikkiGibsonRikkiGibsonMay 18, 2021
edited by jcouv
Loading

Choose a reason for hiding this comment

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

Thank you for this. #Closed

Debug.Assert(left.MemberSymbolis notnull);

// We evaluate the values provided in source first
BoundLocalvalueTemp=_factory.StoreToTemp(assignment.Right,outBoundAssignmentOperatorboundAssignmentToTemp);
Copy link
Member

@RikkiGibsonRikkiGibsonMay 18, 2021
edited by jcouv
Loading

Choose a reason for hiding this comment

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

nit: it feels like it's possible to avoid storing to temps when the assignments occur in the same order as the constructor parameters, similar to the way method call arguments are rewritten during lowering. However, I don't think it's necessary to implement this optimization in this PR. #WontFix

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Agreed. Also, the cases where this optimization could actually play out aren't the common case so it seems fine to punt.

/// There are different kinds of regions, <see cref="ControlFlowRegionKind"/>.
/// - <see cref="ControlFlowGraphBuilder.SpillEvalStack"/> converts values on the stack into captures.
/// - Error scenarios from initial binding need to be handled.
/// </summary>
Copy link
Member

@RikkiGibsonRikkiGibsonMay 18, 2021
edited by jcouv
Loading

Choose a reason for hiding this comment

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

Thanks for this. It helped me review this PR and I'm sure it will help future readers. #Closed

Copy link
Member

@CyrusNajmabadiCyrusNajmabadi 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 lgmt.

@jcouv
Copy link
MemberAuthor

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@jcouvjcouv merged commit828c0a0 intodotnet:mainMay 21, 2021
@ghostghost modified the milestones:C# 10,NextMay 21, 2021
@jcouvjcouv deleted the with-anonymous branchMay 21, 2021 03:48
333fred added a commit that referenced this pull requestMay 24, 2021
…ures/interpolated-string* upstream/main: (92 commits)  Keep casts when necessary to prefer a constant pattern over a type pattern  Remove SyntaxKind.DataKeyword (#53614)  Display 'readonly' for record structs (#53634)  Update Building, Debugging, and Testing on Windows.md (#53543)  Update dependencies fromhttps://github.com/dotnet/arcade build 20210521.3 (#53617)  Introduce resx for BuildValidator and MS.CA.Rebuild to allow localization (#53447)  Report obsoletion diagnostics for slice and indexer (#53463)  Update BasicGenerateConstructorDialog.cs  Add searchbox in generate overrides dialog  Allow `with` on anonymous types (#53248)  Report diagnostic on correct node (#53538)  Fix NotNullIfNotNull delegate conversion (#53409)  Verify quick info session in InvokeQuickInfo  Remove unnecessary retry  Ensure no navbar IO on the UI thread  Enable nullable reference types  Fix timeout behavior in GetQuickInfo  Add a semantic model based GetQuickInfoAsync entry point into QuickInfoServiceWithProviders  Move semantic model based quick info API up to CommonQuickInfoProvider type  Fix dnceng build by forcing the use of xcopy msbuild  ...
@RikkiGibsonRikkiGibson modified the milestones:Next,17.0.P2Jun 29, 2021
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@CyrusNajmabadiCyrusNajmabadiCyrusNajmabadi approved these changes

@RikkiGibsonRikkiGibsonRikkiGibson approved these changes

@AlekseyTsAlekseyTsAlekseyTs approved these changes

+1 more reviewer

@Youssef1313Youssef1313Youssef1313 left review comments

Reviewers whose approvals may not affect merge requirements

Projects

None yet

Milestone

17.0.P2

Development

Successfully merging this pull request may close these issues.

5 participants

@jcouv@Youssef1313@CyrusNajmabadi@AlekseyTs@RikkiGibson

[8]ページ先頭

©2009-2025 Movatter.jp