Make IPropertySubpattern Internal#33178
Conversation
| return ValueUsageInfo.Write; | ||
|
|
||
| case IRecursivePatternOperation _: | ||
| case IOperation iop when iop.GetType().GetInterfaces().Any(i => i.Name == "IRecursivePatternOperation"): |
There was a problem hiding this comment.
Thanks for updating this. Can you also file a tracking issue to revert this IDE change? #Resolved
| constantValue: default, isImplicit: isImplicit); | ||
| } | ||
| case null: | ||
| return null; |
There was a problem hiding this comment.
Should this also return an invalid operation? At least the doc comment here indicates Member is always non-null. If we do decide to allow null, we should make this explicit in doc comments. #Resolved
| internal override IOperation VisitPropertySubpattern(IPropertySubpatternOperation operation, object argument) | ||
| { | ||
| return new PropertySubpatternOperation( | ||
| semanticModel: null, |
There was a problem hiding this comment.
semanticModel: null, [](start = 16, length = 20)
Semantic model should be preserved by the Cloner. #Closed
| operation.Syntax, | ||
| IsImplicit(operation), | ||
| Visit(operation.Member), | ||
| (IPatternOperation)Visit(operation.Pattern)); |
There was a problem hiding this comment.
(IPatternOperation)Visit(operation.Pattern) [](start = 16, length = 43)
It looks like in this case we are not setting the right substitution for the InstanceReferenceKind.PatternInput for the case when the operation.Pattern is a recursive pattern. Given that majority of nodes are internal, I'd suggest to not substitute InstanceReferenceKind.PatternInput with a capture in this PR and leave it as a regular node. We will have to figure out the right way to deal with this later. #Closed
|
|
||
| IPropertySubpatternOperation (OperationKind.None, Type: null) (Syntax: 'Item1: var z') | ||
| Member: | ||
| IFieldReferenceOperation: System.Int32 (System.Int32 X, System.Int32 Y).Item1 (OperationKind.FieldReference, Type: System.Int32, IsImplicit) (Syntax: 'Item1') |
There was a problem hiding this comment.
IsImplicit [](start = 163, length = 10)
Is this supposed to be implicit? #Closed
| internal IOperation CreatePropertySubpatternMember(Symbol symbol, SyntaxNode syntax) | ||
| { | ||
| var nameSyntax = (syntax is SubpatternSyntax subpatSyntax ? subpatSyntax.NameColon?.Name : null) ?? syntax; | ||
| bool isImplicit = nameSyntax != syntax; |
There was a problem hiding this comment.
nameSyntax != syntax [](start = 30, length = 20)
Should this condition be inversed? It looks like we are lacking a test that simply asserts IOperation tree shape for this code path, consider adding one. #Closed
| { | ||
| var constantValue = field.ConstantValue is null ? default(Optional<object>) : new Optional<object>(field.ConstantValue); | ||
| var receiver = new InstanceReferenceOperation( | ||
| InstanceReferenceKind.PatternInput, _semanticModel, nameSyntax, field.ContainingType, constantValue, isImplicit: true); |
There was a problem hiding this comment.
field.ContainingType [](start = 92, length = 20)
It feels like field.ContainingType is not always the right value to use. The field can come from a base type. I think we would want all PatternInputs within the same pattern to use the same type, matching the MatchedType. #Closed
| case PropertySymbol property: | ||
| { | ||
| var receiver = new InstanceReferenceOperation( | ||
| InstanceReferenceKind.PatternInput, _semanticModel, nameSyntax, property.ContainingType, constantValue: default, isImplicit: true); |
There was a problem hiding this comment.
property.ContainingType [](start = 92, length = 23)
Same comment. #Closed
| var receiver = new InstanceReferenceOperation( | ||
| InstanceReferenceKind.PatternInput, _semanticModel, nameSyntax, property.ContainingType, constantValue: default, isImplicit: true); | ||
| return new PropertyReferenceOperation( | ||
| property, receiver, ImmutableArray<IArgumentOperation>.Empty, _semanticModel, nameSyntax, property.Type.TypeSymbol, |
There was a problem hiding this comment.
ImmutableArray.Empty [](start = 48, length = 40)
In an error case, could we ran into a parameterized property? #Closed
There was a problem hiding this comment.
It does not appear so. The closest I could get was an IConstantPatternOperation child of the IPropertyPatternOperation. Using an indexer like below doesn't parse close to cleanly at all, it results in multiple IncompleteMembers on the class.
class C
{
(int x, int y) this[int i] { get => default; set {} }
void M(object o, bool b)
{
b = /*<bind>*/o is C { [1]: (var x, var y) }/*</bind>*/;
}
}In reply to: 254445327 [](ancestors = 254445327)
| BoundSubpattern subpattern, | ||
| SyntaxNode syntax, | ||
| SemanticModel semanticModel) | ||
| : base(semanticModel, syntax, false) |
There was a problem hiding this comment.
false [](start = 42, length = 5)
Is this for Implicit? Consider using named parameter. #Closed
|
|
||
| internal override void VisitPropertySubpattern(IPropertySubpatternOperation operation) | ||
| { | ||
| Assert.True(operation.Member is IMemberReferenceOperation); |
There was a problem hiding this comment.
Assert.True(operation.Member is IMemberReferenceOperation); [](start = 12, length = 59)
What about error cases? #Closed
|
Done with review pass (iteration 2) #Closed |
|
@AlekseyTs addressed feedback. In reply to: 461185324 [](ancestors = 461185324) |
|
@dotnet/roslyn-compiler for a second review. |
| public override ImmutableArray<IPropertySubpatternOperation> CreatePropertySubpatterns() | ||
| { | ||
| return _boundRecursivePattern.Properties.IsDefault ? ImmutableArray<IPropertySubpatternOperation>.Empty : | ||
| _boundRecursivePattern.Properties.SelectAsArray((p, fac) => fac.CreatePropertySubpattern(p, MatchedType), _operationFactory); |
There was a problem hiding this comment.
MatchedType [](start = 108, length = 11)
Is this going to prevent the lambda from caching the delegate? Consider passing it in a tuple parameter, together with operation factory. #Closed
| default: | ||
| // We should expose the symbol in this case somehow: | ||
| // https://github.com/dotnet/roslyn/issues/33175 | ||
| return OperationFactory.CreateInvalidOperation(_semanticModel, nameSyntax, ImmutableArray<IOperation>.Empty, isImplicit: true); |
There was a problem hiding this comment.
true [](start = 141, length = 4)
Should we use isImplicit instead of hard coding true? #Closed
| PropertySubpatterns (1): | ||
| IPropertySubpatternOperation (OperationKind.None, Type: null, IsInvalid) (Syntax: 'NotFound: int x') | ||
| Member: | ||
| IInvalidOperation (OperationKind.Invalid, Type: null, IsInvalid, IsImplicit) (Syntax: 'NotFound') |
There was a problem hiding this comment.
IsImplicit [](start = 79, length = 10)
It feels like this shouldn't be implicit. #Closed
| { | ||
| void M1(object o, bool b) | ||
| { | ||
| b = /*<bind>*/o is C1 { Prop[1]: var x }/*</bind>*/; |
There was a problem hiding this comment.
Prop[1] [](start = 32, length = 7)
Consider adding a test without indexing, just the property name #Closed
src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IIsPatternExpression.cs
Show resolved
Hide resolved
| internal override void VisitPropertySubpattern(IPropertySubpatternOperation operation) | ||
| { | ||
| Assert.True(operation.Member is IMemberReferenceOperation || operation.Member is IInvalidOperation); | ||
| var member = (IMemberReferenceOperation)operation.Member; |
There was a problem hiding this comment.
(IMemberReferenceOperation)operation.Member; [](start = 25, length = 44)
Is this going to throw when operation.Member is IInvalidOperation? #Closed
There was a problem hiding this comment.
Is this not getting caught by tests? Even when IOperation hook is enabled?
In reply to: 254480084 [](ancestors = 254480084)
There was a problem hiding this comment.
I should probably run these tests through the hook, I haven't. But no, this visitor isn't called on our regular IOperation tests.
In reply to: 254480510 [](ancestors = 254480510,254480084)
|
It looks like there are legitimate test failures. #Closed |
|
Done with review pass (iteration 3) #Closed |
|
There were on the first run, second run hasn't completed yet. In reply to: 461217005 [](ancestors = 461217005) |
|
@AlekseyTs addressed feedback. In reply to: 461217061 [](ancestors = 461217061) |
src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IIsPatternExpression.cs
Show resolved
Hide resolved
| { | ||
| case IFieldSymbol field: | ||
| case IPropertySymbol prop: | ||
| case IErrorTypeSymbol error: |
There was a problem hiding this comment.
case IErrorTypeSymbol error: [](start = 16, length = 28)
This is probably not a valid case any more. #Resolved
AlekseyTs
left a comment
There was a problem hiding this comment.
LGTM (iteration 4), assuming the tests are passing.
| SyntaxNode syntax, | ||
| bool isImplicit, | ||
| IOperation member, | ||
| IPatternOperation pattern) |
There was a problem hiding this comment.
Minor point: It looks like constructors for other IOperation implementations have child arguments before semanticModel, syntax, isImplicit arguments. #Resolved
|
|
||
| internal IOperation CreatePropertySubpatternMember(Symbol symbol, ITypeSymbol matchedType, SyntaxNode syntax) | ||
| { | ||
| var nameSyntax = (syntax is SubpatternSyntax subpatSyntax ? subpatSyntax.NameColon?.Name : null) ?? syntax; |
There was a problem hiding this comment.
(syntax is SubpatternSyntax subpatSyntax ? subpatSyntax.NameColon?.Name : null) [](start = 29, length = 79)
Could remove the : null with (syntax as SubpatternSyntax)?.NameColon?.Name. #Resolved
| { | ||
| case FieldSymbol field: | ||
| { | ||
| var constantValue = field.ConstantValue is null ? default(Optional<object>) : new Optional<object>(field.ConstantValue); |
There was a problem hiding this comment.
field.ConstantValue [](start = 123, length = 19)
Should this be field.ContantValue.Value?
If so, please use the helper method:
var constantValue = ConvertToOptional(field.ConstantValue);
Please add a test for a field with constant value if possible. #Resolved
| case FieldSymbol field: | ||
| { | ||
| var constantValue = field.ConstantValue is null ? default(Optional<object>) : new Optional<object>(field.ConstantValue); | ||
| var receiver = new InstanceReferenceOperation( |
There was a problem hiding this comment.
InstanceReferenceOperation [](start = 43, length = 26)
Are we testing with static fields and properties?
class C
{
static int F;
static void M(object o)
{
bool b = o is C { F: 1 } c;
}
}
``` #Resolved
| private static readonly IConvertibleConversion s_boxedIdentityConversion = Conversion.Identity; | ||
|
|
||
| private static Optional<object> ConvertToOptional(ConstantValue value) | ||
| internal static Optional<object> ConvertToOptional(ConstantValue value) |
There was a problem hiding this comment.
internal [](start = 8, length = 8)
Is this change necessary? #Resolved
Updates the structure of IPropertySubpattern to be what we decided in the IOperation design meeting, and makes the implementation internal until we finalize C# 8.
Fixes #33018.