Extended property patterns: IOperation and Symbols#53082
Extended property patterns: IOperation and Symbols#53082jcouv merged 18 commits intodotnet:features/extended-property-patternsfrom
Conversation
259e110 to
70a124a
Compare
There was a problem hiding this comment.
I have no idea why this works already. There's no changes to account for nested members in this PR.
| Symbol last = subpattern.Symbols.Last(); | ||
| // PROTOTYPE(extended-property-patterns) For a chain of members, the input type is no longer `inputType` | ||
| if (last.ContainingType.Equals(inputType, TypeCompareKind.AllIgnoreOptions)) | ||
| if (subpattern.Member is { Symbol: Symbol symbol, Receiver: var receiver } member && |
There was a problem hiding this comment.
I didn't understand how the nullability analysis of the chain of accesses falls out from this implementation. I would have expected we'd analyze the nullability of the receiver first (the chain of receivers is not null) then learn that the current member/symbol is also not null.
nit: please use an explicit type here for readability #Closed
There was a problem hiding this comment.
Me neither. I'll have to investigate to see where the state is produced.
nit: please use an explicit type here for readability
We don't want the null check here. Filed a suggestion to address this: dotnet/csharplang#4724
There was a problem hiding this comment.
Let's keep a PROTOTYPE marker here then. Thanks
| } | ||
|
|
||
| [Fact] | ||
| public void ExtendedPropertyPatterns_Nullability() |
There was a problem hiding this comment.
Could you add a simliar test with two types (each having a property/field)?
class C1 { C2? Prop1 { get; } }
class C2 { object? Prop2 { get; } }
``` #Closed
| Console.WriteLine(p is { X.Y: {}, Y.X: {} }); | ||
| } | ||
| } | ||
| class P |
There was a problem hiding this comment.
It would be better to split this type into two (one containing X and one for Y) #Closed
| AssertEmpty(model.GetSymbolInfo(subpatterns[0])); | ||
| AssertEmpty(model.GetSymbolInfo(subpatterns[0].ExpressionColon)); | ||
| var xy = subpatterns[0].ExpressionColon.Expression; | ||
| var xySymbol = model.GetSymbolInfo(xy); |
There was a problem hiding this comment.
Please also verify GetTypeInfo on those various pieces of syntax. #Closed
| Diagnostic(ErrorCode.ERR_PropertyLacksGet, "action").WithArguments("action").WithLocation(8, 38) | ||
| }; | ||
|
|
||
| VerifyOperationTreeAndDiagnosticsForTest<IsPatternExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics, parseOptions: TestOptions.RegularWithExtendedPropertyPatterns); |
There was a problem hiding this comment.
Let's also verify the control flow graph with VerifyFlowGraphAndDiagnosticsForTest (for a positive case above). PROTOTYPE for follow-up is okay too. #Closed
jcouv
left a comment
There was a problem hiding this comment.
Done with review pass (iteration 12)
src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs
Outdated
Show resolved
Hide resolved
| } | ||
| if (lowestBoundNode is BoundPropertySubpatternMember member) | ||
| { | ||
| return new CSharpTypeInfo(member.Type, member.Type, nullability: default, convertedNullability: default, Conversion.Identity); |
There was a problem hiding this comment.
I guess we want to return the unwrapped type + nullable conversion if this is a nested member? If so, we probably need to capture this info from binding. Also I'm not sure what is the expected NullabilityInfo here.
There was a problem hiding this comment.
Sounds like GetTypeInfo on subpattern name wasn't handled before or am I missing something?
| if (last.ContainingType.Equals(inputType, TypeCompareKind.AllIgnoreOptions)) | ||
| // PROTOTYPE(extended-property-patterns): Investigate if we need to visit nested members; is there a test gap? | ||
| if (subpattern.Member is { Symbol: Symbol symbol, Receiver: var receiver } member && | ||
| symbol.ContainingType.Equals(receiver is not null ? receiver.Type : inputType, TypeCompareKind.AllIgnoreOptions)) |
There was a problem hiding this comment.
There was a problem hiding this comment.
The logic is unchanged from before but it sounds like the check is actually redundant. Remove?
There was a problem hiding this comment.
I do recall one or two tests failing without the check but I couldn't find it now. I'll remove it to see if CI fails.
There was a problem hiding this comment.
If no tests fail without this check, is there a simple test with a derived type that we could add that would demonstrate the difference in behavior?
There was a problem hiding this comment.
I think this is the one: RecursivePatternNullInferenceWithDowncast_01 but now it's green.
There was a problem hiding this comment.
I actually went back to main and rechecked. No test fails. I might be missing something though.
src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs
Outdated
Show resolved
Hide resolved
| property.GetPublicSymbol(), ImmutableArray<IArgumentOperation>.Empty, createReceiver(), _semanticModel, nameSyntax, property.Type.GetPublicSymbol(), | ||
| isImplicit: isImplicit); | ||
| return new PropertyReferenceOperation(property.GetPublicSymbol(), ImmutableArray<IArgumentOperation>.Empty, | ||
| createReceiver(), _semanticModel, member.Syntax, property.Type.StrippedType().GetPublicSymbol(), isImplicit: false); |
There was a problem hiding this comment.
I don't think we should use StrippedType here. Maybe only if this is a nested member?
jcouv
left a comment
There was a problem hiding this comment.
LGTM Thanks (iteration 17). Will merge as soon as CI is green.
|
I think both #53082 (comment) and #53082 (comment) need to be revised based on the expected behavior. |
|
@RikkiGibson Integration legs are consistently failing on x86. Is this normal? |
|
azp /run |
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
Test plan: #52468
BoundPropertySubpatternandBoundPositionalSubpatternBoundPropertySubpatternMemberto keep track of symbol/syntax mapping