- Notifications
You must be signed in to change notification settings - Fork4.2k
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
Uh oh!
There was an error while loading.Please reload this page.
Conversation
Youssef1313 commentedMay 7, 2021 • edited by jcouv
Loading Uh oh!
There was an error while loading.Please reload this page.
edited by jcouv
Uh oh!
There was an error while loading.Please reload this page.
Should target
In reply to:834059406 |
jcouv commentedMay 7, 2021 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
CyrusNajmabadi commentedMay 7, 2021 • edited by jcouv
Loading Uh oh!
There was an error while loading.Please reload this page.
edited by jcouv
Uh oh!
There was an error while loading.Please reload this page.
| ||symbol.ContainingType.IsAnonymousType | ||
| ||CanSupportObjectInitializer(symbol); |
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.
Not sure if the new check should be moved toCanSupportObjectInitializer?
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 fine with either approach.
| /// - 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). |
AlekseyTsMay 11, 2021 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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 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 |
AlekseyTsMay 11, 2021 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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 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.
Good catch. Restored exception.
| IOperationcloned; | ||
| if(operation.Type.IsValueType) | ||
| { | ||
| cloned=visitedInstance; |
AlekseyTsMay 11, 2021 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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 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.
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.
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.
Also includes fix forwith on pointer types.
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 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....
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 mind. I recall thatHandleObjectOrCollectionInitializer handles that.
I'll add the tests though
| staticboolsetAllProperties(ImmutableArray<IOperation>initializers,ImmutableArray<IPropertySymbol>properties) | ||
| { | ||
| varset=PooledHashSet<string>.GetInstance(); |
AlekseyTsMay 11, 2021 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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 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 it possible to have duplicate names in some error situations?
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.
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)
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.
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(); |
AlekseyTsMay 11, 2021 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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.
| simpleAssignment.Targetis notInvalidOperation) | ||
| { | ||
| varpropertyReference=(IPropertyReferenceOperation)simpleAssignment.Target; | ||
| _=set.Remove(propertyReference.Property); |
AlekseyTsMay 12, 2021 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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 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 commentedMay 12, 2021 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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 commentedMay 12, 2021 • edited by jcouv
Loading Uh oh!
There was an error while loading.Please reload this page.
edited by jcouv
Uh oh!
There was an error while loading.Please reload this page.
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 commentedMay 12, 2021 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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 commentedMay 12, 2021 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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); |
AlekseyTsMay 12, 2021 • edited by jcouv
Loading Uh oh!
There was an error while loading.Please reload this page.
edited by jcouv
Uh oh!
There was an error while loading.Please reload this page.
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.
| &&withExpr.Initializer.Expressions.Any() | ||
| &&withExpr.Expression==(object)syntax) | ||
| { | ||
| returntrue; |
AlekseyTsMay 12, 2021 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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 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 commentedMay 12, 2021 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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 commentedMay 12, 2021
Done with review pass (commit 9) |
jcouv commentedMay 12, 2021
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) |
AlekseyTs left a comment
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 (commit 10)
jcouv commentedMay 12, 2021
@dotnet/roslyn-compiler for a second review. Thanks |
| staticboolisAllowedDespiteReadonly(BoundExpressionreceiver) | ||
| { | ||
| // ok: anonymousType with { Property = ... } | ||
| if(receiverisBoundObjectOrCollectionValuePlaceholder&&receiver.Type.IsAnonymousType) |
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: 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(); |
RikkiGibsonMay 18, 2021 • edited by jcouv
Loading Uh oh!
There was an error while loading.Please reload this page.
edited by jcouv
Uh oh!
There was an error while loading.Please reload this page.
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: 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
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.
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?"); |
RikkiGibsonMay 18, 2021 • edited by jcouv
Loading Uh oh!
There was an error while loading.Please reload this page.
edited by jcouv
Uh oh!
There was an error while loading.Please reload this page.
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.
Thank you for this. #Closed
| Debug.Assert(left.MemberSymbolis notnull); | ||
| // We evaluate the values provided in source first | ||
| BoundLocalvalueTemp=_factory.StoreToTemp(assignment.Right,outBoundAssignmentOperatorboundAssignmentToTemp); |
RikkiGibsonMay 18, 2021 • edited by jcouv
Loading Uh oh!
There was an error while loading.Please reload this page.
edited by jcouv
Uh oh!
There was an error while loading.Please reload this page.
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: 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
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.
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> |
RikkiGibsonMay 18, 2021 • edited by jcouv
Loading Uh oh!
There was an error while loading.Please reload this page.
edited by jcouv
Uh oh!
There was an error while loading.Please reload this page.
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.
Thanks for this. It helped me review this PR and I'm sure it will help future readers. #Closed
CyrusNajmabadi left a comment
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.
ide side lgmt.
jcouv commentedMay 20, 2021
/azp run |
| Azure Pipelines successfully started running 3 pipeline(s). |
…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 ...
Uh oh!
There was an error while loading.Please reload this page.
Test plan:#51199
Also includes:
withon pointer typeswithon structures