提交 880516ba 编写于 作者: A AlekseyTs

Adjust scope of locals declared within Lock Statements according to the latest design.

Related to #12597.
上级 f221ecc9
......@@ -250,7 +250,7 @@ private BoundStatement BindLockStatement(LockStatementSyntax node, DiagnosticBag
{
var lockBinder = this.GetBinder(node);
Debug.Assert(lockBinder != null);
return lockBinder.WrapWithVariablesIfAny(node, lockBinder.BindLockStatementParts(diagnostics, lockBinder));
return lockBinder.BindLockStatementParts(diagnostics, lockBinder);
}
internal virtual BoundStatement BindLockStatementParts(DiagnosticBag diagnostics, Binder originalBinder)
......@@ -278,6 +278,7 @@ internal BoundStatement BindPossibleEmbeddedStatement(StatementSyntax node, Diag
case SyntaxKind.ExpressionStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.LockStatement:
Binder binder = this.GetBinder(node);
Debug.Assert(binder != null);
return binder.WrapWithVariablesIfAny(node, binder.BindStatement(node, diagnostics));
......
......@@ -454,8 +454,7 @@ public override void VisitFixedStatement(FixedStatementSyntax node)
public override void VisitLockStatement(LockStatementSyntax node)
{
var patternBinder = new ExpressionVariableBinder(node, _enclosing);
var lockBinder = new LockBinder(patternBinder, node);
var lockBinder = new LockBinder(_enclosing, node);
AddToMap(node, lockBinder);
Visit(node.Expression, lockBinder);
......@@ -717,8 +716,6 @@ private void VisitPossibleEmbeddedStatement(StatementSyntax statement, Binder en
{
if (statement != null)
{
BlockBinder blockBinder;
switch (statement.Kind())
{
case SyntaxKind.LocalDeclarationStatement:
......@@ -729,18 +726,13 @@ private void VisitPossibleEmbeddedStatement(StatementSyntax statement, Binder en
// inside a block.
case SyntaxKind.ExpressionStatement:
Debug.Assert((object)_containingMemberOrLambda == enclosing.ContainingMemberOrLambda);
blockBinder = new BlockBinder(enclosing, new SyntaxList<StatementSyntax>(statement));
AddToMap(statement, blockBinder);
Visit(statement, blockBinder);
return;
case SyntaxKind.WhileStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.LockStatement:
Debug.Assert((object)_containingMemberOrLambda == enclosing.ContainingMemberOrLambda);
blockBinder = new BlockBinder(enclosing, new SyntaxList<StatementSyntax>(statement));
var blockBinder = new BlockBinder(enclosing, new SyntaxList<StatementSyntax>(statement));
AddToMap(statement, blockBinder);
Visit(statement, blockBinder);
Debug.Assert(_map.ContainsKey(statement));
return;
default:
......
......@@ -197,6 +197,7 @@ protected ImmutableArray<LocalSymbol> BuildLocals(SyntaxList<StatementSyntax> st
case SyntaxKind.WhileStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.LockStatement:
ExpressionVariableFinder.FindExpressionVariables(this, locals, innerStatement, enclosingBinder.GetBinder(innerStatement));
break;
......
......@@ -2794,6 +2794,15 @@ static bool TakeOutParam(int y, out int x)
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular);
CompileAndVerify(compilation, expectedOutput: @"2
2");
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var x1Decl = GetOutVarDeclarations(tree, "x1").ToArray();
var x1Ref = GetReferences(tree, "x1").ToArray();
Assert.Equal(1, x1Decl.Length);
Assert.Equal(2, x1Ref.Length);
VerifyModelForOutVar(model, x1Decl[0], x1Ref);
}
[Fact]
......@@ -7231,7 +7240,7 @@ void Test4()
var x4 = 11;
Dummy(x4);
lock (Dummy(TakeOutParam(true, out var x4) && x4))
lock (Dummy(TakeOutParam(true, out var x4) && x4 > 0))
Dummy(x4);
}
......@@ -7326,18 +7335,18 @@ static bool TakeOutParam(int y, out int x)
// (87,13): error CS1023: Embedded statement cannot be a declaration or labeled statement
// var y12 = 12;
Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "var y12 = 12;").WithLocation(87, 13),
// (29,48): error CS0136: A local or parameter named 'x4' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
// lock (Dummy(TakeOutParam(true, out var x4) && x4))
Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x4").WithArguments("x4").WithLocation(29, 48),
// (29,48): error CS0128: A local variable named 'x4' is already defined in this scope
// lock (Dummy(TakeOutParam(true, out var x4) && x4 > 0))
Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(29, 48),
// (35,21): error CS0841: Cannot use local variable 'x6' before it is declared
// lock (Dummy(x6 && TakeOutParam(true, out var x6)))
Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x6").WithArguments("x6").WithLocation(35, 21),
// (43,17): error CS0136: A local or parameter named 'x7' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
// var x7 = 12;
Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x7").WithArguments("x7").WithLocation(43, 17),
// (53,34): error CS0103: The name 'x8' does not exist in the current context
// System.Console.WriteLine(x8);
Diagnostic(ErrorCode.ERR_NameNotInContext, "x8").WithArguments("x8").WithLocation(53, 34),
// (60,19): error CS0841: Cannot use local variable 'x9' before it is declared
// Dummy(x9);
Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x9").WithArguments("x9").WithLocation(60, 19),
// (61,52): error CS0136: A local or parameter named 'x9' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
// lock (Dummy(TakeOutParam(true, out var x9) && x9)) // 2
Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x9").WithArguments("x9").WithLocation(61, 52),
......@@ -7369,7 +7378,9 @@ static bool TakeOutParam(int y, out int x)
var x4Ref = GetReferences(tree, "x4").ToArray();
Assert.Equal(3, x4Ref.Length);
VerifyNotAnOutLocal(model, x4Ref[0]);
VerifyModelForOutVar(model, x4Decl, x4Ref[1], x4Ref[2]);
VerifyNotAnOutLocal(model, x4Ref[1]);
VerifyNotAnOutLocal(model, x4Ref[2]);
VerifyModelForOutVarDuplicateInSameScope(model, x4Decl);
var x6Decl = GetOutVarDeclarations(tree, "x6").Single();
var x6Ref = GetReferences(tree, "x6").ToArray();
......@@ -7385,15 +7396,14 @@ static bool TakeOutParam(int y, out int x)
var x8Decl = GetOutVarDeclarations(tree, "x8").Single();
var x8Ref = GetReferences(tree, "x8").ToArray();
Assert.Equal(3, x8Ref.Length);
VerifyModelForOutVar(model, x8Decl, x8Ref[0], x8Ref[1]);
VerifyNotInScope(model, x8Ref[2]);
VerifyModelForOutVar(model, x8Decl, x8Ref);
var x9Decl = GetOutVarDeclarations(tree, "x9").ToArray();
var x9Ref = GetReferences(tree, "x9").ToArray();
Assert.Equal(2, x9Decl.Length);
Assert.Equal(4, x9Ref.Length);
VerifyModelForOutVar(model, x9Decl[0], x9Ref[0], x9Ref[1]);
VerifyModelForOutVar(model, x9Decl[1], x9Ref[2], x9Ref[3]);
VerifyModelForOutVar(model, x9Decl[0], x9Ref[0]);
VerifyModelForOutVar(model, x9Decl[1], x9Ref[1], x9Ref[2], x9Ref[3]);
var y10Ref = GetReferences(tree, "y10").ToArray();
Assert.Equal(2, y10Ref.Length);
......@@ -7411,6 +7421,52 @@ static bool TakeOutParam(int y, out int x)
VerifyModelForOutVarDuplicateInSameScope(model, x14Decl[1]);
}
[Fact]
public void Scope_Lock_02()
{
var source =
@"
public class X
{
public static void Main()
{
}
object Dummy(params object[] x) {return null;}
void Test1()
{
if (true)
lock (Dummy(TakeOutParam(true, out var x1)))
{
}
x1++;
}
static object TakeOutParam(bool y, out bool x)
{
x = y;
return true;
}
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular);
compilation.VerifyDiagnostics(
// (17,9): error CS0103: The name 'x1' does not exist in the current context
// x1++;
Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(17, 9)
);
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var x1Decl = GetOutVarDeclarations(tree, "x1").Single();
var x1Ref = GetReferences(tree, "x1").Single();
VerifyModelForOutVar(model, x1Decl);
VerifyNotInScope(model, x1Ref);
}
[Fact]
public void Lock_01()
{
......@@ -7424,6 +7480,8 @@ public static void Main()
{
System.Console.WriteLine(x1);
}
System.Console.WriteLine(x1);
}
static object Dummy(object y, object z)
......@@ -7442,7 +7500,68 @@ static bool TakeOutParam<T>(T y, out T x)
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular);
CompileAndVerify(compilation, expectedOutput:
@"lock
lock
lock");
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var x1Decl = GetOutVarDeclarations(tree, "x1").ToArray();
var x1Ref = GetReferences(tree, "x1").ToArray();
Assert.Equal(1, x1Decl.Length);
Assert.Equal(3, x1Ref.Length);
VerifyModelForOutVar(model, x1Decl[0], x1Ref);
}
[Fact]
public void Lock_02()
{
var source =
@"
public class X
{
public static void Main()
{
bool f = true;
if (f)
lock (Dummy(f, TakeOutParam((f ? 1 : 2), out var x1), x1))
{}
if (f)
{
lock (Dummy(f, TakeOutParam((f ? 3 : 4), out var x1), x1))
{}
}
}
static object Dummy(bool x, object y, object z)
{
System.Console.WriteLine(z);
return x;
}
static bool TakeOutParam<T>(T y, out T x)
{
x = y;
return true;
}
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular);
CompileAndVerify(compilation, expectedOutput:
@"1
3");
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var x1Decl = GetOutVarDeclarations(tree, "x1").ToArray();
var x1Ref = GetReferences(tree, "x1").ToArray();
Assert.Equal(2, x1Decl.Length);
Assert.Equal(2, x1Ref.Length);
VerifyModelForOutVar(model, x1Decl[0], x1Ref[0]);
VerifyModelForOutVar(model, x1Decl[1], x1Ref[1]);
}
[Fact]
......@@ -9926,6 +10045,48 @@ static bool TakeOutParam<T>(T y, out T x)
Assert.Equal("System.Int32", model.GetTypeInfo(yRef).Type.ToTestDisplayString());
}
[Fact]
public void Scope_SwitchLabelGuard_05()
{
var source =
@"
public class X
{
public static void Main()
{
Test(1);
}
static void Test(int val)
{
switch (val)
{
case 1 when TakeOutParam(123, out var x1):
lock ((object)TakeOutParam(x1, out var y1)) {}
System.Console.WriteLine(y1);
break;
}
}
static bool TakeOutParam<T>(T y, out T x)
{
x = y;
return true;
}
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular);
CompileAndVerify(compilation, expectedOutput: @"123").VerifyDiagnostics();
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var yRef = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "y1").Single();
Assert.Equal("System.Int32", model.GetTypeInfo(yRef).Type.ToTestDisplayString());
}
[Fact]
public void Scope_SwitchLabelPattern_01()
{
......
......@@ -7511,6 +7511,15 @@ static bool Dummy(bool x, object y, object z)
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe);
CompileAndVerify(compilation, expectedOutput:@"2
2");
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var x1Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x1").ToArray();
var x1Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x1").ToArray();
Assert.Equal(1, x1Decl.Length);
Assert.Equal(2, x1Ref.Length);
VerifyModelForDeclarationPattern(model, x1Decl[0], x1Ref);
}
[Fact]
......@@ -9476,18 +9485,18 @@ void Test14()
// (87,13): error CS1023: Embedded statement cannot be a declaration or labeled statement
// var y12 = 12;
Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "var y12 = 12;").WithLocation(87, 13),
// (29,33): error CS0136: A local or parameter named 'x4' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
// (29,33): error CS0128: A local variable named 'x4' is already defined in this scope
// lock (Dummy(true is var x4 && x4))
Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x4").WithArguments("x4").WithLocation(29, 33),
Diagnostic(ErrorCode.ERR_LocalDuplicate, "x4").WithArguments("x4").WithLocation(29, 33),
// (35,21): error CS0841: Cannot use local variable 'x6' before it is declared
// lock (Dummy(x6 && true is var x6))
Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x6").WithArguments("x6").WithLocation(35, 21),
// (43,17): error CS0136: A local or parameter named 'x7' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
// var x7 = 12;
Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x7").WithArguments("x7").WithLocation(43, 17),
// (53,34): error CS0103: The name 'x8' does not exist in the current context
// System.Console.WriteLine(x8);
Diagnostic(ErrorCode.ERR_NameNotInContext, "x8").WithArguments("x8").WithLocation(53, 34),
// (60,19): error CS0841: Cannot use local variable 'x9' before it is declared
// Dummy(x9);
Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "x9").WithArguments("x9").WithLocation(60, 19),
// (61,37): error CS0136: A local or parameter named 'x9' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
// lock (Dummy(true is var x9 && x9)) // 2
Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x9").WithArguments("x9").WithLocation(61, 37),
......@@ -9519,7 +9528,9 @@ void Test14()
var x4Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x4").ToArray();
Assert.Equal(3, x4Ref.Length);
VerifyNotAPatternLocal(model, x4Ref[0]);
VerifyModelForDeclarationPattern(model, x4Decl, x4Ref[1], x4Ref[2]);
VerifyNotAPatternLocal(model, x4Ref[1]);
VerifyNotAPatternLocal(model, x4Ref[2]);
VerifyModelForDeclarationPatternDuplicateInSameScope(model, x4Decl);
var x6Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x6").Single();
var x6Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x6").ToArray();
......@@ -9535,15 +9546,14 @@ void Test14()
var x8Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x8").Single();
var x8Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x8").ToArray();
Assert.Equal(3, x8Ref.Length);
VerifyModelForDeclarationPattern(model, x8Decl, x8Ref[0], x8Ref[1]);
VerifyNotInScope(model, x8Ref[2]);
VerifyModelForDeclarationPattern(model, x8Decl, x8Ref);
var x9Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x9").ToArray();
var x9Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x9").ToArray();
Assert.Equal(2, x9Decl.Length);
Assert.Equal(4, x9Ref.Length);
VerifyModelForDeclarationPattern(model, x9Decl[0], x9Ref[0], x9Ref[1]);
VerifyModelForDeclarationPattern(model, x9Decl[1], x9Ref[2], x9Ref[3]);
VerifyModelForDeclarationPattern(model, x9Decl[0], x9Ref[0]);
VerifyModelForDeclarationPattern(model, x9Decl[1], x9Ref[1], x9Ref[2], x9Ref[3]);
var y10Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "y10").ToArray();
Assert.Equal(2, y10Ref.Length);
......@@ -9561,6 +9571,46 @@ void Test14()
VerifyModelForDeclarationPatternDuplicateInSameScope(model, x14Decl[1]);
}
[Fact]
public void ScopeOfPatternVariables_Lock_02()
{
var source =
@"
public class X
{
public static void Main()
{
}
object Dummy(params object[] x) {return null;}
void Test1()
{
if (true)
lock (Dummy(true is var x1))
{
}
x1++;
}
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe);
compilation.VerifyDiagnostics(
// (17,9): error CS0103: The name 'x1' does not exist in the current context
// x1++;
Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(17, 9)
);
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var x1Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x1").Single();
var x1Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x1").Single();
VerifyModelForDeclarationPattern(model, x1Decl);
VerifyNotInScope(model, x1Ref);
}
[Fact]
public void Lock_01()
{
......@@ -9574,6 +9624,8 @@ public static void Main()
{
System.Console.WriteLine(x1);
}
System.Console.WriteLine(x1);
}
static object Dummy(object y, object z)
......@@ -9586,7 +9638,62 @@ static object Dummy(object y, object z)
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe);
CompileAndVerify(compilation, expectedOutput:
@"lock
lock
lock");
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var x1Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x1").ToArray();
var x1Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x1").ToArray();
Assert.Equal(1, x1Decl.Length);
Assert.Equal(3, x1Ref.Length);
VerifyModelForDeclarationPattern(model, x1Decl[0], x1Ref);
}
[Fact]
public void Lock_02()
{
var source =
@"
public class X
{
public static void Main()
{
bool f = true;
if (f)
lock (Dummy(f, (f ? 1 : 2) is var x1, x1))
{}
if (f)
{
lock (Dummy(f, (f ? 3 : 4) is var x1, x1))
{}
}
}
static object Dummy(bool x, object y, object z)
{
System.Console.WriteLine(z);
return x;
}
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe);
CompileAndVerify(compilation, expectedOutput:
@"1
3");
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var x1Decl = tree.GetRoot().DescendantNodes().OfType<DeclarationPatternSyntax>().Where(p => p.Identifier.ValueText == "x1").ToArray();
var x1Ref = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "x1").ToArray();
Assert.Equal(2, x1Decl.Length);
Assert.Equal(2, x1Ref.Length);
VerifyModelForDeclarationPattern(model, x1Decl[0], x1Ref[0]);
VerifyModelForDeclarationPattern(model, x1Decl[1], x1Ref[1]);
}
[Fact]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册