Skip to content

Make IPropertySubpattern Internal#33178

Merged
333fred merged 4 commits intodotnet:masterfrom
333fred:rpatterns-33018
Feb 7, 2019
Merged

Make IPropertySubpattern Internal#33178
333fred merged 4 commits intodotnet:masterfrom
333fred:rpatterns-33018

Conversation

@333fred
Copy link
Member

@333fred 333fred commented Feb 6, 2019

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.

@333fred 333fred requested review from a team and AlekseyTs February 6, 2019 19:40
@333fred 333fred requested a review from a team as a code owner February 6, 2019 19:40
return ValueUsageInfo.Write;

case IRecursivePatternOperation _:
case IOperation iop when iop.GetType().GetInterfaces().Any(i => i.Name == "IRecursivePatternOperation"):
Copy link
Contributor

@mavasani mavasani Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for updating this. Can you also file a tracking issue to revert this IDE change? #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a note to #33175.


In reply to: 254423185 [](ancestors = 254423185)

constantValue: default, isImplicit: isImplicit);
}
case null:
return null;
Copy link
Contributor

@mavasani mavasani Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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,
Copy link
Contributor

@AlekseyTs AlekseyTs Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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));
Copy link
Contributor

@AlekseyTs AlekseyTs Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(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

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a note to #33175 to follow up.


In reply to: 254440669 [](ancestors = 254440669)


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')
Copy link
Contributor

@AlekseyTs AlekseyTs Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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;
Copy link
Contributor

@AlekseyTs AlekseyTs Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
Copy link
Contributor

@AlekseyTs AlekseyTs Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
Copy link
Contributor

@AlekseyTs AlekseyTs Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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,
Copy link
Contributor

@AlekseyTs AlekseyTs Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ImmutableArray.Empty [](start = 48, length = 40)

In an error case, could we ran into a parameterized property? #Closed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Copy link
Contributor

@AlekseyTs AlekseyTs Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
Copy link
Contributor

@AlekseyTs AlekseyTs Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assert.True(operation.Member is IMemberReferenceOperation); [](start = 12, length = 59)

What about error cases? #Closed

@AlekseyTs
Copy link
Contributor

AlekseyTs commented Feb 6, 2019

Done with review pass (iteration 2) #Closed

@333fred
Copy link
Member Author

333fred commented Feb 6, 2019

@AlekseyTs addressed feedback.


In reply to: 461185324 [](ancestors = 461185324)

@333fred
Copy link
Member Author

333fred commented Feb 6, 2019

@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);
Copy link
Contributor

@AlekseyTs AlekseyTs Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
Copy link
Contributor

@AlekseyTs AlekseyTs Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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')
Copy link
Contributor

@AlekseyTs AlekseyTs Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>*/;
Copy link
Contributor

@AlekseyTs AlekseyTs Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prop[1] [](start = 32, length = 7)

Consider adding a test without indexing, just the property name #Closed

internal override void VisitPropertySubpattern(IPropertySubpatternOperation operation)
{
Assert.True(operation.Member is IMemberReferenceOperation || operation.Member is IInvalidOperation);
var member = (IMemberReferenceOperation)operation.Member;
Copy link
Contributor

@AlekseyTs AlekseyTs Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(IMemberReferenceOperation)operation.Member; [](start = 25, length = 44)

Is this going to throw when operation.Member is IInvalidOperation? #Closed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this not getting caught by tests? Even when IOperation hook is enabled?


In reply to: 254480084 [](ancestors = 254480084)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

@AlekseyTs
Copy link
Contributor

AlekseyTs commented Feb 6, 2019

It looks like there are legitimate test failures. #Closed

@AlekseyTs
Copy link
Contributor

AlekseyTs commented Feb 6, 2019

Done with review pass (iteration 3) #Closed

@333fred
Copy link
Member Author

333fred commented Feb 6, 2019

There were on the first run, second run hasn't completed yet.


In reply to: 461217005 [](ancestors = 461217005)

@333fred
Copy link
Member Author

333fred commented Feb 6, 2019

@AlekseyTs addressed feedback.


In reply to: 461217061 [](ancestors = 461217061)

{
case IFieldSymbol field:
case IPropertySymbol prop:
case IErrorTypeSymbol error:
Copy link
Contributor

@AlekseyTs AlekseyTs Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

case IErrorTypeSymbol error: [](start = 16, length = 28)

This is probably not a valid case any more. #Resolved

Copy link
Contributor

@AlekseyTs AlekseyTs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (iteration 4), assuming the tests are passing.

SyntaxNode syntax,
bool isImplicit,
IOperation member,
IPatternOperation pattern)
Copy link
Contributor

@cston cston Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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;
Copy link
Contributor

@cston cston Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(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);
Copy link
Contributor

@cston cston Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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(
Copy link
Contributor

@cston cston Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Copy link
Contributor

@cston cston Feb 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

internal [](start = 8, length = 8)

Is this change necessary? #Resolved

@333fred 333fred closed this Feb 7, 2019
@333fred 333fred reopened this Feb 7, 2019
@333fred
Copy link
Member Author

333fred commented Feb 7, 2019

@cston none of these comments seem blocking, so I've added notes to #33175 to follow up. #Resolved

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IRecursivePattern Changes

5 participants