Fix GetDeconstructionInfo on converted deconstruction assignment#82324
Fix GetDeconstructionInfo on converted deconstruction assignment#82324jcouv merged 4 commits intodotnet:mainfrom
GetDeconstructionInfo on converted deconstruction assignment#82324Conversation
| var boundDeconstruction = GetUpperBoundNode(node) as BoundDeconstructionAssignmentOperator; | ||
| if (boundDeconstruction is null) | ||
| var upperNode = GetUpperBoundNode(node); | ||
| while (upperNode is BoundConversion conversion) |
There was a problem hiding this comment.
Would requesting the "lower" bound node work better?
There was a problem hiding this comment.
Would requesting the "lower" bound node work better?
Yes, I think that's better. Thanks
Could you provide more details about the tree shape that we are trying to accommodate with this change?
Here's the shape of the tree:
The bound node for the RHS assignment syntax is a conversion chain with a deconstructionAssignmentOperator.
Here's an extract:
│ └─assignmentOperator
│ ├─left
│ │ └─local
│ │ ├─localSymbol: c1
│ │ ├─declarationKind: None
│ │ ├─constantValueOpt
│ │ ├─isNullableUnknown: False
│ │ └─type: C
│ ├─right
│ │ └─conversion
│ │ ├─operand
│ │ │ └─conversion
│ │ │ ├─operand
│ │ │ │ └─deconstructionAssignmentOperator
Here's the full:
nonConstructorMethodBody
├─blockBody
│ └─block
│ ├─locals: {c1, c2}
│ ├─hasUnsafeModifier: False
│ ├─instrumentation
│ └─statements
│ ├─localDeclaration
│ │ ├─localSymbol: c1
│ │ ├─declaredTypeOpt
│ │ │ └─typeExpression
│ │ │ ├─typeWithAnnotations: C
│ │ │ └─type: C
│ │ ├─initializerOpt
│ │ │ └─objectCreationExpression
│ │ │ ├─constructor: C.C()
│ │ │ ├─constructorsGroup: {C.C()}
│ │ │ ├─arguments
│ │ │ ├─argumentNamesOpt: (null)
│ │ │ ├─argumentRefKindsOpt: (null)
│ │ │ ├─expanded: False
│ │ │ ├─argsToParamsOpt: (null)
│ │ │ ├─defaultArguments: Microsoft.CodeAnalysis.BitVector
│ │ │ ├─constantValueOpt
│ │ │ ├─initializerExpressionOpt
│ │ │ ├─wasTargetTyped: False
│ │ │ └─type: C
│ │ ├─argumentsOpt
│ │ └─inferredType: True
│ ├─localDeclaration
│ │ ├─localSymbol: c2
│ │ ├─declaredTypeOpt
│ │ │ └─typeExpression
│ │ │ ├─typeWithAnnotations: C
│ │ │ └─type: C
│ │ ├─initializerOpt
│ │ │ └─objectCreationExpression
│ │ │ ├─constructor: C.C()
│ │ │ ├─constructorsGroup: {C.C()}
│ │ │ ├─arguments
│ │ │ ├─argumentNamesOpt: (null)
│ │ │ ├─argumentRefKindsOpt: (null)
│ │ │ ├─expanded: False
│ │ │ ├─argsToParamsOpt: (null)
│ │ │ ├─defaultArguments: Microsoft.CodeAnalysis.BitVector
│ │ │ ├─constantValueOpt
│ │ │ ├─initializerExpressionOpt
│ │ │ ├─wasTargetTyped: False
│ │ │ └─type: C
│ │ ├─argumentsOpt
│ │ └─inferredType: True
│ └─expressionStatement
│ └─expression
│ └─assignmentOperator
│ ├─left
│ │ └─local
│ │ ├─localSymbol: c1
│ │ ├─declarationKind: None
│ │ ├─constantValueOpt
│ │ ├─isNullableUnknown: False
│ │ └─type: C
│ ├─right
│ │ └─conversion
│ │ ├─operand
│ │ │ └─conversion
│ │ │ ├─operand
│ │ │ │ └─deconstructionAssignmentOperator
│ │ │ │ ├─left
│ │ │ │ │ └─convertedTupleLiteral
│ │ │ │ │ ├─sourceTuple
│ │ │ │ │ │ └─tupleLiteral
│ │ │ │ │ │ ├─arguments
│ │ │ │ │ │ │ ├─discardExpression
│ │ │ │ │ │ │ │ ├─nullableAnnotation: Oblivious
│ │ │ │ │ │ │ │ ├─isInferred: True
│ │ │ │ │ │ │ │ └─type: int
│ │ │ │ │ │ │ └─discardExpression
│ │ │ │ │ │ │ ├─nullableAnnotation: Oblivious
│ │ │ │ │ │ │ ├─isInferred: True
│ │ │ │ │ │ │ └─type: string
│ │ │ │ │ │ ├─argumentNamesOpt: (null)
│ │ │ │ │ │ ├─inferredNamesOpt: (null)
│ │ │ │ │ │ └─type: (int, string)
│ │ │ │ │ ├─wasTargetTyped: False
│ │ │ │ │ ├─arguments
│ │ │ │ │ │ ├─discardExpression
│ │ │ │ │ │ │ ├─nullableAnnotation: Oblivious
│ │ │ │ │ │ │ ├─isInferred: True
│ │ │ │ │ │ │ └─type: int
│ │ │ │ │ │ └─discardExpression
│ │ │ │ │ │ ├─nullableAnnotation: Oblivious
│ │ │ │ │ │ ├─isInferred: True
│ │ │ │ │ │ └─type: string
│ │ │ │ │ ├─argumentNamesOpt: (null)
│ │ │ │ │ ├─inferredNamesOpt: (null)
│ │ │ │ │ └─type: (int, string)
│ │ │ │ ├─right
│ │ │ │ │ └─conversion
│ │ │ │ │ ├─operand
│ │ │ │ │ │ └─local
│ │ │ │ │ │ ├─localSymbol: c2
│ │ │ │ │ │ ├─declarationKind: None
│ │ │ │ │ │ ├─constantValueOpt
│ │ │ │ │ │ ├─isNullableUnknown: False
│ │ │ │ │ │ └─type: C
│ │ │ │ │ ├─conversion: Deconstruction
│ │ │ │ │ ├─isBaseConversion: False
│ │ │ │ │ ├─@checked: False
│ │ │ │ │ ├─explicitCastInCode: False
│ │ │ │ │ ├─constantValueOpt
│ │ │ │ │ ├─conversionGroupOpt
│ │ │ │ │ ├─inConversionGroupFlags: Unspecified
│ │ │ │ │ └─type: (int, string)
│ │ │ │ ├─isUsed: True
│ │ │ │ └─type: (int, string)
│ │ │ ├─conversion: Identity
│ │ │ ├─isBaseConversion: False
│ │ │ ├─@checked: False
│ │ │ ├─explicitCastInCode: False
│ │ │ ├─constantValueOpt
│ │ │ ├─conversionGroupOpt: Microsoft.CodeAnalysis.CSharp.ConversionGroup
│ │ │ ├─inConversionGroupFlags: UserDefinedFromConversion
│ │ │ └─type: (int i, string s)
│ │ ├─conversion: ImplicitUserDefined
│ │ ├─isBaseConversion: False
│ │ ├─@checked: False
│ │ ├─explicitCastInCode: False
│ │ ├─constantValueOpt
│ │ ├─conversionGroupOpt: Microsoft.CodeAnalysis.CSharp.ConversionGroup
│ │ ├─inConversionGroupFlags: UserDefinedOperator
│ │ └─type: C
│ └─type: C
└─expressionBody
|
Done with review pass (commit 2) |
GetDeconstructionInfo should dig through conversionsGetDeconstructionInfo should look through conversions
| { | ||
| var boundDeconstruction = GetUpperBoundNode(node) as BoundDeconstructionAssignmentOperator; | ||
| if (boundDeconstruction is null) | ||
| var upperNode = GetLowerBoundNode(node); |
|
Done with review pass (commit 3) |
|
@jcouv Consider adjusting the title to reflect the nature of the change |
|
@dotnet/roslyn-compiler for another review. Thanks |
I think " |
I don't think I agree. The problem being solved is to look at the right node. |
|
And the change, as it stands right now, is not looking through conversions |
GetDeconstructionInfo should look through conversionsGetDeconstructionInfo on converted deconstruction assignment
Fixes #68979