Address PR Feedback.

上级 d2523e59
......@@ -2009,36 +2009,34 @@ private IOperation CreateUsingLocalDeclarationsOperation(BoundUsingLocalDeclarat
isImplicit: false);
}
internal IPropertySubpatternOperation CreatePropertySubpattern(BoundSubpattern subpattern)
internal IPropertySubpatternOperation CreatePropertySubpattern(BoundSubpattern subpattern, ITypeSymbol matchedType)
{
SyntaxNode syntax = subpattern.Syntax;
return new CSharpLazyPropertySubpatternOperation(this, subpattern, syntax, _semanticModel);
return new CSharpLazyPropertySubpatternOperation(this, subpattern, matchedType, syntax, _semanticModel);
}
internal IOperation CreatePropertySubpatternMember(Symbol symbol, SyntaxNode syntax)
internal IOperation CreatePropertySubpatternMember(Symbol symbol, ITypeSymbol matchedType, SyntaxNode syntax)
{
var nameSyntax = (syntax is SubpatternSyntax subpatSyntax ? subpatSyntax.NameColon?.Name : null) ?? syntax;
bool isImplicit = nameSyntax != syntax;
bool isImplicit = nameSyntax == syntax;
switch (symbol)
{
case FieldSymbol field:
{
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);
InstanceReferenceKind.PatternInput, _semanticModel, nameSyntax, matchedType, constantValue, isImplicit: true);
return new FieldReferenceOperation(
field, isDeclaration: false, receiver, _semanticModel, nameSyntax, field.Type.TypeSymbol, constantValue, isImplicit: isImplicit);
}
case PropertySymbol property:
{
var receiver = new InstanceReferenceOperation(
InstanceReferenceKind.PatternInput, _semanticModel, nameSyntax, property.ContainingType, constantValue: default, isImplicit: true);
InstanceReferenceKind.PatternInput, _semanticModel, nameSyntax, matchedType, constantValue: default, isImplicit: true);
return new PropertyReferenceOperation(
property, receiver, ImmutableArray<IArgumentOperation>.Empty, _semanticModel, nameSyntax, property.Type.TypeSymbol,
constantValue: default, isImplicit: isImplicit);
}
case null:
return null;
default:
// We should expose the symbol in this case somehow:
// https://github.com/dotnet/roslyn/issues/33175
......
......@@ -1516,7 +1516,7 @@ public override ImmutableArray<IPatternOperation> CreateDeconstructionSubpattern
public override ImmutableArray<IPropertySubpatternOperation> CreatePropertySubpatterns()
{
return _boundRecursivePattern.Properties.IsDefault ? ImmutableArray<IPropertySubpatternOperation>.Empty :
_boundRecursivePattern.Properties.SelectAsArray((p, fac) => fac.CreatePropertySubpattern(p), _operationFactory);
_boundRecursivePattern.Properties.SelectAsArray((p, fac) => fac.CreatePropertySubpattern(p, MatchedType), _operationFactory);
}
}
......@@ -1524,20 +1524,23 @@ internal sealed partial class CSharpLazyPropertySubpatternOperation : LazyProper
{
private readonly BoundSubpattern _subpattern;
private readonly CSharpOperationFactory _operationFactory;
private readonly ITypeSymbol _matchedType;
public CSharpLazyPropertySubpatternOperation(
CSharpOperationFactory operationFactory,
BoundSubpattern subpattern,
ITypeSymbol matchedType,
SyntaxNode syntax,
SemanticModel semanticModel)
: base(semanticModel, syntax, false)
: base(semanticModel, syntax, isImplicit: false)
{
_subpattern = subpattern;
_operationFactory = operationFactory;
_matchedType = matchedType;
}
public override IOperation CreateMember()
{
return _operationFactory.CreatePropertySubpatternMember(_subpattern.Symbol, Syntax);
return _operationFactory.CreatePropertySubpatternMember(_subpattern.Symbol, _matchedType, Syntax);
}
public override IPatternOperation CreatePattern()
......
......@@ -650,69 +650,45 @@ void M(int? x, bool b, int x2, bool b2)
Block[B0] - Entry
Statements (0)
Next (Regular) Block[B1]
Entering: {R1} {R2}
Entering: {R1}
.locals {R1}
{
Locals: [System.Int32? y]
.locals {R2}
{
CaptureIds: [0] [1]
Block[B1] - Block
Predecessors: [B0]
Statements (3)
IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
Block[B1] - Block
Predecessors: [B0]
Statements (2)
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'b = x is var y;')
Expression:
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Boolean) (Syntax: 'b = x is var y')
Left:
IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: System.Boolean) (Syntax: 'b')
IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'x')
Value:
IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32?) (Syntax: 'x')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'b = x is var y;')
Expression:
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Boolean) (Syntax: 'b = x is var y')
Left:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Boolean, IsImplicit) (Syntax: 'b')
Right:
IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean) (Syntax: 'x is var y')
Value:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Int32?, IsImplicit) (Syntax: 'x')
Pattern:
IDeclarationPatternOperation (OperationKind.DeclarationPattern, Type: null) (Syntax: 'var y') (InputType: System.Int32?, DeclaredSymbol: System.Int32? y, MatchesNull: True)
Next (Regular) Block[B2]
Leaving: {R2}
Entering: {R3}
}
.locals {R3}
{
CaptureIds: [2] [3]
Block[B2] - Block
Predecessors: [B1]
Statements (3)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b2')
Value:
Right:
IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean) (Syntax: 'x is var y')
Value:
IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32?) (Syntax: 'x')
Pattern:
IDeclarationPatternOperation (OperationKind.DeclarationPattern, Type: null) (Syntax: 'var y') (InputType: System.Int32?, DeclaredSymbol: System.Int32? y, MatchesNull: True)
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'b2 = x2 is 1;')
Expression:
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Boolean) (Syntax: 'b2 = x2 is 1')
Left:
IParameterReferenceOperation: b2 (OperationKind.ParameterReference, Type: System.Boolean) (Syntax: 'b2')
IFlowCaptureOperation: 3 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'x2')
Value:
IParameterReferenceOperation: x2 (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'x2')
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'b2 = x2 is 1;')
Expression:
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Boolean) (Syntax: 'b2 = x2 is 1')
Left:
IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Boolean, IsImplicit) (Syntax: 'b2')
Right:
IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean) (Syntax: 'x2 is 1')
Right:
IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean) (Syntax: 'x2 is 1')
Value:
IParameterReferenceOperation: x2 (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'x2')
Pattern:
IConstantPatternOperation (OperationKind.ConstantPattern, Type: null) (Syntax: '1') (InputType: System.Int32)
Value:
IFlowCaptureReferenceOperation: 3 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'x2')
Pattern:
IConstantPatternOperation (OperationKind.ConstantPattern, Type: null) (Syntax: '1') (InputType: System.Int32)
Value:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
Next (Regular) Block[B3]
Leaving: {R3} {R1}
}
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
Next (Regular) Block[B2]
Leaving: {R1}
}
Block[B3] - Exit
Predecessors: [B2]
Statements (0)";
Block[B2] - Exit
Predecessors: [B1]
Statements (0)
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyFlowGraphAndDiagnosticsForTest<BlockSyntax>(source, expectedFlowGraph, expectedDiagnostics);
......@@ -731,6 +707,42 @@ void M((int X, int Y)? x, bool b)
}/*</bind>*/
}
";
var compilation = CreateCompilation(source);
compilation.VerifyDiagnostics();
string expectedOperationTree = @"
IBlockOperation (1 statements, 2 locals) (OperationKind.Block, Type: null) (Syntax: '{ ... }')
Locals: Local_1: (System.Int32 X, System.Int32 Y) p
Local_2: System.Int32 z
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'b = x is (1 ... var z } p;')
Expression:
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Boolean) (Syntax: 'b = x is (1 ... : var z } p')
Left:
IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: System.Boolean) (Syntax: 'b')
Right:
IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean) (Syntax: 'x is (1, _) ... : var z } p')
Value:
IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: (System.Int32 X, System.Int32 Y)?) (Syntax: 'x')
Pattern:
IRecursivePatternOperation (OperationKind.RecursivePattern, Type: null) (Syntax: '(1, _) { It ... : var z } p') (InputType: (System.Int32 X, System.Int32 Y)?, DeclaredSymbol: (System.Int32 X, System.Int32 Y) p, MatchedType: (System.Int32 X, System.Int32 Y), DeconstructSymbol: null)
DeconstructionSubpatterns (2):
IConstantPatternOperation (OperationKind.ConstantPattern, Type: null) (Syntax: '1') (InputType: System.Int32)
Value:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null) (Syntax: '_') (InputType: System.Int32)
PropertySubpatterns (1):
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) (Syntax: 'Item1')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: PatternInput) (OperationKind.InstanceReference, Type: (System.Int32 X, System.Int32 Y), IsImplicit) (Syntax: 'Item1')
Pattern:
IDeclarationPatternOperation (OperationKind.DeclarationPattern, Type: null) (Syntax: 'var z') (InputType: System.Int32, DeclaredSymbol: System.Int32 z, MatchesNull: True)
";
VerifyOperationTreeForTest<BlockSyntax>(compilation, expectedOperationTree);
string expectedFlowGraph = @"
Block[B0] - Entry
Statements (0)
......@@ -739,25 +751,18 @@ void M((int X, int Y)? x, bool b)
.locals {R1}
{
Locals: [(System.Int32 X, System.Int32 Y) p] [System.Int32 z]
CaptureIds: [0] [1]
Block[B1] - Block
Predecessors: [B0]
Statements (3)
IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
Value:
IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: System.Boolean) (Syntax: 'b')
IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'x')
Value:
IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: (System.Int32 X, System.Int32 Y)?) (Syntax: 'x')
Statements (1)
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'b = x is (1 ... var z } p;')
Expression:
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Boolean) (Syntax: 'b = x is (1 ... : var z } p')
Left:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Boolean, IsImplicit) (Syntax: 'b')
IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: System.Boolean) (Syntax: 'b')
Right:
IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean) (Syntax: 'x is (1, _) ... : var z } p')
Value:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: (System.Int32 X, System.Int32 Y)?, IsImplicit) (Syntax: 'x')
IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: (System.Int32 X, System.Int32 Y)?) (Syntax: 'x')
Pattern:
IRecursivePatternOperation (OperationKind.RecursivePattern, Type: null) (Syntax: '(1, _) { It ... : var z } p') (InputType: (System.Int32 X, System.Int32 Y)?, DeclaredSymbol: (System.Int32 X, System.Int32 Y) p, MatchedType: (System.Int32 X, System.Int32 Y), DeconstructSymbol: null)
DeconstructionSubpatterns (2):
......@@ -768,9 +773,9 @@ void M((int X, int Y)? x, bool b)
PropertySubpatterns (1):
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')
IFieldReferenceOperation: System.Int32 (System.Int32 X, System.Int32 Y).Item1 (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'Item1')
Instance Receiver:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: (System.Int32 X, System.Int32 Y)?, IsImplicit) (Syntax: 'x')
IInstanceReferenceOperation (ReferenceKind: PatternInput) (OperationKind.InstanceReference, Type: (System.Int32 X, System.Int32 Y), IsImplicit) (Syntax: 'Item1')
Pattern:
IDeclarationPatternOperation (OperationKind.DeclarationPattern, Type: null) (Syntax: 'var z') (InputType: System.Int32, DeclaredSymbol: System.Int32 z, MatchesNull: True)
Next (Regular) Block[B2]
......@@ -779,6 +784,92 @@ void M((int X, int Y)? x, bool b)
Block[B2] - Exit
Predecessors: [B1]
Statements (0)";
VerifyFlowGraphForTest<BlockSyntax>(compilation, expectedFlowGraph);
}
[CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow, CompilerFeature.Patterns)]
[Fact]
public void IsPattern_NoControlFlow_03()
{
string source = @"
class C
{
void M((int X, (int Y, int Z))? tuple, bool b)
/*<bind>*/{
b = tuple is (1, _) { Item1: var x, Item2: { Y: 1, Z: var z } } p;
}/*</bind>*/
}
";
string expectedFlowGraph = @"
Block[B0] - Entry
Statements (0)
Next (Regular) Block[B1]
Entering: {R1}
.locals {R1}
{
Locals: [(System.Int32 X, (System.Int32 Y, System.Int32 Z)) p] [System.Int32 x] [System.Int32 z]
Block[B1] - Block
Predecessors: [B0]
Statements (1)
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'b = tuple i ... ar z } } p;')
Expression:
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Boolean) (Syntax: 'b = tuple i ... var z } } p')
Left:
IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: System.Boolean) (Syntax: 'b')
Right:
IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean) (Syntax: 'tuple is (1 ... var z } } p')
Value:
IParameterReferenceOperation: tuple (OperationKind.ParameterReference, Type: (System.Int32 X, (System.Int32 Y, System.Int32 Z))?) (Syntax: 'tuple')
Pattern:
IRecursivePatternOperation (OperationKind.RecursivePattern, Type: null) (Syntax: '(1, _) { It ... var z } } p') (InputType: (System.Int32 X, (System.Int32 Y, System.Int32 Z))?, DeclaredSymbol: (System.Int32 X, (System.Int32 Y, System.Int32 Z)) p, MatchedType: (System.Int32 X, (System.Int32 Y, System.Int32 Z)), DeconstructSymbol: null)
DeconstructionSubpatterns (2):
IConstantPatternOperation (OperationKind.ConstantPattern, Type: null) (Syntax: '1') (InputType: System.Int32)
Value:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null) (Syntax: '_') (InputType: (System.Int32 Y, System.Int32 Z))
PropertySubpatterns (2):
IPropertySubpatternOperation (OperationKind.None, Type: null) (Syntax: 'Item1: var x')
Member:
IFieldReferenceOperation: System.Int32 (System.Int32 X, (System.Int32 Y, System.Int32 Z)).Item1 (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'Item1')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: PatternInput) (OperationKind.InstanceReference, Type: (System.Int32 X, (System.Int32 Y, System.Int32 Z)), IsImplicit) (Syntax: 'Item1')
Pattern:
IDeclarationPatternOperation (OperationKind.DeclarationPattern, Type: null) (Syntax: 'var x') (InputType: System.Int32, DeclaredSymbol: System.Int32 x, MatchesNull: True)
IPropertySubpatternOperation (OperationKind.None, Type: null) (Syntax: 'Item2: { Y: ... Z: var z }')
Member:
IFieldReferenceOperation: (System.Int32 Y, System.Int32 Z) (System.Int32 X, (System.Int32 Y, System.Int32 Z)).Item2 (OperationKind.FieldReference, Type: (System.Int32 Y, System.Int32 Z)) (Syntax: 'Item2')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: PatternInput) (OperationKind.InstanceReference, Type: (System.Int32 X, (System.Int32 Y, System.Int32 Z)), IsImplicit) (Syntax: 'Item2')
Pattern:
IRecursivePatternOperation (OperationKind.RecursivePattern, Type: null) (Syntax: '{ Y: 1, Z: var z }') (InputType: (System.Int32 Y, System.Int32 Z), DeclaredSymbol: null, MatchedType: (System.Int32 Y, System.Int32 Z), DeconstructSymbol: null)
DeconstructionSubpatterns (0)
PropertySubpatterns (2):
IPropertySubpatternOperation (OperationKind.None, Type: null) (Syntax: 'Y: 1')
Member:
IFieldReferenceOperation: System.Int32 (System.Int32 Y, System.Int32 Z).Y (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'Y')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: PatternInput) (OperationKind.InstanceReference, Type: (System.Int32 Y, System.Int32 Z), IsImplicit) (Syntax: 'Y')
Pattern:
IConstantPatternOperation (OperationKind.ConstantPattern, Type: null) (Syntax: '1') (InputType: System.Int32)
Value:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
IPropertySubpatternOperation (OperationKind.None, Type: null) (Syntax: 'Z: var z')
Member:
IFieldReferenceOperation: System.Int32 (System.Int32 Y, System.Int32 Z).Z (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'Z')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: PatternInput) (OperationKind.InstanceReference, Type: (System.Int32 Y, System.Int32 Z), IsImplicit) (Syntax: 'Z')
Pattern:
IDeclarationPatternOperation (OperationKind.DeclarationPattern, Type: null) (Syntax: 'var z') (InputType: System.Int32, DeclaredSymbol: System.Int32 z, MatchesNull: True)
Next (Regular) Block[B2]
Leaving: {R1}
}
Block[B2] - Exit
Predecessors: [B1]
Statements (0)
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyFlowGraphAndDiagnosticsForTest<BlockSyntax>(source, expectedFlowGraph, expectedDiagnostics);
......@@ -913,7 +1004,7 @@ void M((int X, int Y) tuple, bool b)
PropertySubpatterns (1):
IPropertySubpatternOperation (OperationKind.None, Type: null) (Syntax: 'Item1: int x')
Member:
IFieldReferenceOperation: System.Int32 (System.Int32 X, System.Int32 Y).Item1 (OperationKind.FieldReference, Type: System.Int32, IsImplicit) (Syntax: 'Item1')
IFieldReferenceOperation: System.Int32 (System.Int32 X, System.Int32 Y).Item1 (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'Item1')
Instance Receiver:
IInstanceReferenceOperation (ReferenceKind: PatternInput) (OperationKind.InstanceReference, Type: (System.Int32 X, System.Int32 Y), IsImplicit) (Syntax: 'Item1')
Pattern:
......@@ -924,7 +1015,7 @@ void M((int X, int Y) tuple, bool b)
VerifyOperationTreeAndDiagnosticsForTest<IsPatternExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow, CompilerFeature.Patterns)]
[CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Patterns)]
[Fact]
public void IsPattern_BadRecursivePattern_01()
{
......@@ -953,7 +1044,8 @@ void M((int X, int Y) tuple, bool b)
PropertySubpatterns (1):
IPropertySubpatternOperation (OperationKind.None, Type: null, IsInvalid) (Syntax: 'NotFound: int x')
Member:
null
IInvalidOperation (OperationKind.Invalid, Type: null, IsInvalid, IsImplicit) (Syntax: 'NotFound')
Children(0)
Pattern:
IDeclarationPatternOperation (OperationKind.DeclarationPattern, Type: null) (Syntax: 'int x') (InputType: ?, DeclaredSymbol: System.Int32 x, MatchesNull: False)
";
......@@ -966,6 +1058,79 @@ void M((int X, int Y) tuple, bool b)
VerifyOperationTreeAndDiagnosticsForTest<IsPatternExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Patterns)]
[Fact]
public void IsPattern_BadRecursivePattern_02()
{
var vbSource = @"
Public Class C1
Public Property Prop(index As Integer) As Integer
Get
Return 1
End Get
Set
End Set
End Property
End Class
";
var vbCompilation = CreateVisualBasicCompilation(vbSource);
var source = @"
class C
{
void M1(object o, bool b)
{
b = /*<bind>*/o is C1 { Prop[1]: var x }/*</bind>*/;
}
}";
var compilation = CreateCompilation(source, new[] { vbCompilation.EmitToImageReference() });
compilation.VerifyDiagnostics(
// (6,33): error CS8503: A property subpattern requires a reference to the property or field to be matched, e.g. '{ Name: Prop[1] }'
// b = /*<bind>*/o is C1 { Prop[1]: var x }/*</bind>*/;
Diagnostic(ErrorCode.ERR_PropertyPatternNameMissing, "Prop[1]").WithArguments("Prop[1]").WithLocation(6, 33),
// (6,33): error CS0103: The name 'Prop' does not exist in the current context
// b = /*<bind>*/o is C1 { Prop[1]: var x }/*</bind>*/;
Diagnostic(ErrorCode.ERR_NameNotInContext, "Prop").WithArguments("Prop").WithLocation(6, 33),
// (6,40): error CS1003: Syntax error, ',' expected
// b = /*<bind>*/o is C1 { Prop[1]: var x }/*</bind>*/;
Diagnostic(ErrorCode.ERR_SyntaxError, ":").WithArguments(",", ":").WithLocation(6, 40),
// (6,42): error CS1003: Syntax error, ',' expected
// b = /*<bind>*/o is C1 { Prop[1]: var x }/*</bind>*/;
Diagnostic(ErrorCode.ERR_SyntaxError, "var").WithArguments(",", "").WithLocation(6, 42));
var expectedOperationTree = @"
IIsPatternOperation (OperationKind.IsPattern, Type: System.Boolean, IsInvalid) (Syntax: 'o is C1 { P ... 1]: var x }')
Value:
IParameterReferenceOperation: o (OperationKind.ParameterReference, Type: System.Object) (Syntax: 'o')
Pattern:
IRecursivePatternOperation (OperationKind.RecursivePattern, Type: null, IsInvalid) (Syntax: 'C1 { Prop[1]: var x }') (InputType: System.Object, DeclaredSymbol: null, MatchedType: C1, DeconstructSymbol: null)
DeconstructionSubpatterns (0)
PropertySubpatterns (2):
IPropertySubpatternOperation (OperationKind.None, Type: null, IsInvalid) (Syntax: 'Prop[1]')
Member:
IInvalidOperation (OperationKind.Invalid, Type: null, IsInvalid, IsImplicit) (Syntax: 'Prop[1]')
Children(0)
Pattern:
IConstantPatternOperation (OperationKind.ConstantPattern, Type: null, IsInvalid) (Syntax: 'Prop[1]') (InputType: ?)
Value:
IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'Prop[1]')
Children(2):
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'Prop')
Children(0)
IPropertySubpatternOperation (OperationKind.None, Type: null, IsInvalid) (Syntax: 'var x')
Member:
IInvalidOperation (OperationKind.Invalid, Type: null, IsInvalid, IsImplicit) (Syntax: 'var x')
Children(0)
Pattern:
IDeclarationPatternOperation (OperationKind.DeclarationPattern, Type: null, IsInvalid) (Syntax: 'var x') (InputType: ?, DeclaredSymbol: ? x, MatchesNull: True)
";
VerifyOperationTreeForTest<IsPatternExpressionSyntax>(compilation, expectedOperationTree);
}
[CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow, CompilerFeature.Patterns)]
[Fact]
public void IsPattern_ControlFlowInPattern()
......
......@@ -5818,7 +5818,7 @@ IArrayInitializerOperation popAndAssembleArrayInitializerValues(IArrayInitialize
public override IOperation VisitInstanceReference(IInstanceReferenceOperation operation, int? captureIdForResult)
{
if (operation.ReferenceKind == InstanceReferenceKind.ImplicitReceiver || operation.ReferenceKind == InstanceReferenceKind.PatternInput)
if (operation.ReferenceKind == InstanceReferenceKind.ImplicitReceiver)
{
// When we're in an object or collection initializer, we need to replace the instance reference with a reference to the object being initialized
Debug.Assert(operation.IsImplicit);
......@@ -6419,14 +6419,12 @@ public override IOperation VisitDefaultValue(IDefaultValueOperation operation, i
public override IOperation VisitIsPattern(IIsPatternOperation operation, int? captureIdForResult)
{
EvalStackFrame frame = PushStackFrame();
var capturedValue = VisitAndCapture(operation.Value);
var previousImplicitInstance = _currentImplicitInstance;
_currentImplicitInstance = new ImplicitInstanceInfo(capturedValue);
PushOperand(Visit(operation.Value));
var visitedPattern = (IPatternOperation)Visit(operation.Pattern);
_currentImplicitInstance = previousImplicitInstance;
IOperation visitedValue = PopOperand();
PopStackFrame(frame);
return new IsPatternOperation(capturedValue, visitedPattern, semanticModel: null,
operation.Syntax, operation.Type, operation.ConstantValue, IsImplicit(operation));
return new IsPatternOperation(visitedValue, visitedPattern, semanticModel: null,
operation.Syntax, operation.Type, operation.ConstantValue, IsImplicit(operation));
}
public override IOperation VisitInvalid(IInvalidOperation operation, int? captureIdForResult)
......@@ -6630,14 +6628,11 @@ public override IOperation VisitSwitchExpression(ISwitchExpressionOperation oper
RegionBuilder resultCaptureRegion = _currentRegion;
int captureOutput = captureIdForResult ?? GetNextCaptureId(resultCaptureRegion);
var capturedInput = VisitAndCapture(operation.Value);
var previousImplicitInstance = _currentImplicitInstance;
var switchImplicitInstance = new ImplicitInstanceInfo(capturedInput);
var afterSwitch = new BasicBlockBuilder(BasicBlockKind.Block);
foreach (var arm in operation.Arms)
{
// START scope (arm locals)
_currentImplicitInstance = switchImplicitInstance;
var armScopeRegion = new RegionBuilder(ControlFlowRegionKind.LocalLifetime, locals: arm.Locals);
EnterRegion(armScopeRegion);
var afterArm = new BasicBlockBuilder(BasicBlockKind.Block);
......@@ -6663,8 +6658,6 @@ public override IOperation VisitSwitchExpression(ISwitchExpressionOperation oper
PopStackFrameAndLeaveRegion(frame);
}
_currentImplicitInstance = previousImplicitInstance;
// captureOutput = e
VisitAndCapture(arm.Value, captureOutput);
......
......@@ -552,7 +552,7 @@ internal override IOperation VisitRecursivePattern(IRecursivePatternOperation op
internal override IOperation VisitPropertySubpattern(IPropertySubpatternOperation operation, object argument)
{
return new PropertySubpatternOperation(
semanticModel: null,
semanticModel: ((Operation)operation).OwningSemanticModel,
operation.Syntax,
operation.IsImplicit,
Visit(operation.Member),
......
......@@ -1728,14 +1728,16 @@ private static bool CanBeInControlFlowGraph(IOperation n)
case OperationKind.InstanceReference:
// Implicit instance receivers, except for anonymous type creations, are expected to have been removed when dealing with creations.
return ((IInstanceReferenceOperation)n).ReferenceKind == InstanceReferenceKind.ContainingTypeInstance ||
((IInstanceReferenceOperation)n).ReferenceKind == InstanceReferenceKind.ImplicitReceiver &&
n.Type.IsAnonymousType &&
n.Parent is IPropertyReferenceOperation propertyReference &&
propertyReference.Instance == n &&
propertyReference.Parent is ISimpleAssignmentOperation simpleAssignment &&
simpleAssignment.Target == propertyReference &&
simpleAssignment.Parent.Kind == OperationKind.AnonymousObjectCreation;
var instanceReference = (IInstanceReferenceOperation)n;
return instanceReference.ReferenceKind == InstanceReferenceKind.ContainingTypeInstance ||
instanceReference.ReferenceKind == InstanceReferenceKind.PatternInput ||
(instanceReference.ReferenceKind == InstanceReferenceKind.ImplicitReceiver &&
n.Type.IsAnonymousType &&
n.Parent is IPropertyReferenceOperation propertyReference &&
propertyReference.Instance == n &&
propertyReference.Parent is ISimpleAssignmentOperation simpleAssignment &&
simpleAssignment.Target == propertyReference &&
simpleAssignment.Parent.Kind == OperationKind.AnonymousObjectCreation);
case OperationKind.None:
return !(n is IPlaceholderOperation);
......
......@@ -1197,12 +1197,10 @@ internal override void VisitRecursivePattern(IRecursivePatternOperation operatio
internal override void VisitPropertySubpattern(IPropertySubpatternOperation operation)
{
Assert.True(operation.Member is IMemberReferenceOperation);
Assert.True(operation.Member is IMemberReferenceOperation || operation.Member is IInvalidOperation);
var member = (IMemberReferenceOperation)operation.Member;
switch (member.Member)
{
case null: // error case
break;
case IFieldSymbol field:
case IPropertySymbol prop:
case IErrorTypeSymbol error:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册