-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Extended property patterns: IOperation and Symbols #53082
Extended property patterns: IOperation and Symbols #53082
Conversation
259e110
to
70a124a
Compare
if (this is { Prop.Prop: null }) | ||
{ | ||
this.Prop.ToString(); | ||
this.Prop.Prop.ToString(); // 1 | ||
} |
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 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's keep a PROTOTYPE marker here then. Thanks
} | ||
|
||
[Fact] | ||
public void ExtendedPropertyPatterns_Nullability() |
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.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's also verify the control flow graph with VerifyFlowGraphAndDiagnosticsForTest
(for a positive case above). PROTOTYPE for follow-up is okay too. #Closed
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.
Done with review pass (iteration 12)
src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs
Outdated
Show resolved
Hide resolved
@@ -2029,6 +2033,10 @@ private static bool IsUserDefinedTrueOrFalse(BoundUnaryOperator @operator) | |||
pattern.InputType, pattern.NarrowedType, nullability: default, convertedNullability: default, | |||
Compilation.Conversions.ClassifyBuiltInConversion(pattern.InputType, pattern.NarrowedType, ref discardedUseSiteInfo)); | |||
} | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
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.
The logic is unchanged from before but it sounds like the check is actually redundant. Remove?
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 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is the one: RecursivePatternNullInferenceWithDowncast_01
but now it's green.
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 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should use StrippedType here. Maybe only if this is a nested member?
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 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
BoundPropertySubpattern
andBoundPositionalSubpattern
BoundPropertySubpatternMember
to keep track of symbol/syntax mapping