提交 e9723de3 编写于 作者: A AlekseyTs 提交者: GitHub

Merge pull request #12274 from AlekseyTs/OutVar_16

Ensure the right binder is used to bind initializer of implicitly typed variable.
......@@ -2200,18 +2200,10 @@ private BoundExpression BindArgumentValue(DiagnosticBag diagnostics, ArgumentSyn
SourceLocalSymbol localSymbol = this.LookupLocal(argumentSyntax.Identifier);
// In error scenarios with misplaced code, it is possible we can't bind the local declaration.
// This occurs through the semantic model. In that case concoct a plausible result.
if ((object)localSymbol == null)
{
localSymbol = SourceLocalSymbol.MakeLocal(
ContainingMemberOrLambda,
this,
RefKind.None,
typeSyntax,
argumentSyntax.Identifier,
LocalDeclarationKind.RegularVariable,
initializer: null);
// We should have the right binder in the chain, cannot continue otherwise.
throw ExceptionUtilities.Unreachable;
}
else
{
......
......@@ -425,7 +425,42 @@ private sealed class LocalWithInitializer : SourceLocalSymbol
protected override TypeSymbol InferTypeOfVarVariable(DiagnosticBag diagnostics)
{
var newBinder = new ImplicitlyTypedLocalBinder(this.binder, this);
// Since initializer might use Out Variable Declarations and Pattern Variable Declarations, we need to find
// the right binder to use for the initializer.
// Climb up the syntax tree looking for a first binder that we can find, but stop at the first statement syntax.
CSharpSyntaxNode currentNode = _initializer;
Binder initializerBinder;
do
{
initializerBinder = this.binder.GetBinder(currentNode);
if (initializerBinder != null || currentNode is StatementSyntax)
{
break;
}
currentNode = currentNode.Parent;
}
while (currentNode != null);
#if DEBUG
Binder parentBinder = initializerBinder;
while (parentBinder != null)
{
if (parentBinder == this.binder)
{
break;
}
parentBinder = parentBinder.Next;
}
Debug.Assert(parentBinder != null);
#endif
var newBinder = new ImplicitlyTypedLocalBinder(initializerBinder ?? this.binder, this);
var initializerOpt = newBinder.BindInferredVariableInitializer(diagnostics, RefKind, _initializer, _initializer);
if (initializerOpt != null)
{
......
......@@ -13120,7 +13120,7 @@ public static bool M(int i, out string s)
);
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/12266")]
[Fact]
[WorkItem(12266, "https://github.com/dotnet/roslyn/issues/12266")]
public void LocalVariableTypeInferenceAndOutVar_01()
{
......@@ -13153,7 +13153,7 @@ static int Test1(out int x)
Assert.Equal("System.Int32", model.GetTypeInfo(yRef).Type.ToTestDisplayString());
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/12266")]
[Fact]
[WorkItem(12266, "https://github.com/dotnet/roslyn/issues/12266")]
public void LocalVariableTypeInferenceAndOutVar_02()
{
......@@ -13185,5 +13185,108 @@ static int Test1(out int x)
Assert.Equal("System.Int32", model.GetTypeInfo(yRef).Type.ToTestDisplayString());
}
[Fact]
[WorkItem(12266, "https://github.com/dotnet/roslyn/issues/12266")]
public void LocalVariableTypeInferenceAndOutVar_03()
{
var text = @"
public class Cls
{
public static void Main()
{
var y = Test1(out var x) + x;
System.Console.WriteLine(y);
}
static int Test1(out int x)
{
x = 123;
return 124;
}
}";
var compilation = CreateCompilationWithMscorlib(text,
options: TestOptions.ReleaseExe,
parseOptions: TestOptions.Regular);
CompileAndVerify(compilation, expectedOutput: @"247").VerifyDiagnostics();
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var yRef = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "y").Single();
Assert.Equal("System.Int32", model.GetTypeInfo(yRef).Type.ToTestDisplayString());
}
[Fact]
[WorkItem(12266, "https://github.com/dotnet/roslyn/issues/12266")]
public void LocalVariableTypeInferenceAndOutVar_04()
{
var text = @"
public class Cls
{
public static void Main()
{
for (var y = Test1(out var x) + x; y != 0 ; y = 0)
{
System.Console.WriteLine(y);
}
}
static int Test1(out int x)
{
x = 123;
return 124;
}
}";
var compilation = CreateCompilationWithMscorlib(text,
options: TestOptions.ReleaseExe,
parseOptions: TestOptions.Regular);
CompileAndVerify(compilation, expectedOutput: @"247").VerifyDiagnostics();
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var yRef = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "y").Last();
Assert.Equal("System.Int32", model.GetTypeInfo(yRef).Type.ToTestDisplayString());
}
[Fact]
[WorkItem(12266, "https://github.com/dotnet/roslyn/issues/12266")]
public void LocalVariableTypeInferenceAndOutVar_05()
{
var text = @"
public class Cls
{
public static void Main()
{
foreach (var y in new [] {Test1(out var x) + x})
{
System.Console.WriteLine(y);
}
}
static int Test1(out int x)
{
x = 123;
return 124;
}
}";
var compilation = CreateCompilationWithMscorlib(text,
options: TestOptions.ReleaseExe,
parseOptions: TestOptions.Regular);
CompileAndVerify(compilation, expectedOutput: @"247").VerifyDiagnostics();
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var yRef = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "y").Last();
Assert.Equal("System.Int32", model.GetTypeInfo(yRef).Type.ToTestDisplayString());
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册