未验证 提交 14ec71b1 编写于 作者: J Julien Couvreur 提交者: GitHub

Create missing binder for local function with both block and expression bodies (#24651)

上级 76853730
......@@ -52,9 +52,9 @@ private void Visit(CSharpSyntaxNode syntax, Binder enclosing)
// This may change if the language is extended to allow iterator lambdas, in which case the lambda would also be returned.
// (lambdas currently throw a diagnostic in WithLambdaParametersBinder.GetIteratorElementType when a yield is used within them)
public static SmallDictionary<SyntaxNode, Binder> BuildMap(
Symbol containingMemberOrLambda,
SyntaxNode syntax,
Binder enclosing,
Symbol containingMemberOrLambda,
SyntaxNode syntax,
Binder enclosing,
ArrayBuilder<SyntaxNode> methodsWithYields,
Action<Binder, SyntaxNode> binderUpdatedHandler = null)
{
......@@ -195,12 +195,54 @@ public override void VisitParenthesizedLambdaExpression(ParenthesizedLambdaExpre
public override void VisitLocalFunctionStatement(LocalFunctionStatementSyntax node)
{
var body = (CSharpSyntaxNode)node.Body ?? node.ExpressionBody;
bool oldSawYield = _sawYield;
Symbol oldMethod = _containingMemberOrLambda;
Binder binder = _enclosing;
LocalFunctionSymbol match = FindLocalFunction(node, _enclosing);
if ((object)match != null)
{
_containingMemberOrLambda = match;
binder = match.IsGenericMethod
? new WithMethodTypeParametersBinder(match, _enclosing)
: _enclosing;
binder = binder.WithUnsafeRegionIfNecessary(node.Modifiers);
binder = new InMethodBinder(match, binder);
}
BlockSyntax blockBody = node.Body;
if (blockBody != null)
{
_sawYield = false;
Visit(blockBody, binder);
if (_sawYield)
{
_methodsWithYields.Add(blockBody);
}
}
ArrowExpressionClauseSyntax arrowBody = node.ExpressionBody;
if (arrowBody != null)
{
_sawYield = false;
Visit(arrowBody, binder);
Debug.Assert(!_sawYield);
}
_containingMemberOrLambda = oldMethod;
_sawYield = oldSawYield;
}
private static LocalFunctionSymbol FindLocalFunction(LocalFunctionStatementSyntax node, Binder enclosing)
{
LocalFunctionSymbol match = null;
// Don't use LookupLocalFunction because it recurses up the tree, as it
// should be defined in the directly enclosing block (see note below)
Binder possibleScopeBinder = _enclosing;
Binder possibleScopeBinder = enclosing;
while (possibleScopeBinder != null && !possibleScopeBinder.IsLocalFunctionsScopeBinder)
{
possibleScopeBinder = possibleScopeBinder.Next;
......@@ -217,44 +259,7 @@ public override void VisitLocalFunctionStatement(LocalFunctionStatementSyntax no
}
}
bool oldSawYield = _sawYield;
_sawYield = false;
if (match != null)
{
var oldMethod = _containingMemberOrLambda;
_containingMemberOrLambda = match;
if (body != null)
{
Binder binder = match.IsGenericMethod
? new WithMethodTypeParametersBinder(match, _enclosing)
: _enclosing;
binder = binder.WithUnsafeRegionIfNecessary(node.Modifiers);
Visit(body, new InMethodBinder(match, binder));
}
_containingMemberOrLambda = oldMethod;
}
else
{
// The enclosing block should have found this node and created a LocalFunctionMethodSymbol
// The code that does so is in LocalScopeBinder.BuildLocalFunctions
if (body != null)
{
// do our best to attempt to bind
Visit(body);
}
}
if (_sawYield)
{
_methodsWithYields.Add(body);
}
_sawYield = oldSawYield;
return match;
}
public override void VisitArrowExpressionClause(ArrowExpressionClauseSyntax node)
......@@ -402,7 +407,7 @@ public override void VisitForStatement(ForStatementSyntax node)
foreach (var initializer in node.Initializers)
{
Visit(initializer, binder);
}
}
}
ExpressionSyntax condition = node.Condition;
......@@ -717,7 +722,7 @@ private void AddToMap(SyntaxNode node, Binder binder)
{
// If this ever breaks, make sure that all callers of
// CanHaveAssociatedLocalBinder are in sync.
Debug.Assert(node.CanHaveAssociatedLocalBinder() ||
Debug.Assert(node.CanHaveAssociatedLocalBinder() ||
(node == _root && node is ExpressionSyntax));
// Cleverness: for some nodes (e.g. lock), we want to specify a binder flag that
......
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using System;
using System.Linq;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
......@@ -73,6 +75,30 @@ public class E
0");
}
[Fact]
[WorkItem(24647, "https://github.com/dotnet/roslyn/issues/24647")]
public void Repro24647()
{
var comp = CreateStandardCompilation(@"
class Program
{
static void Main(string[] args)
{
void local() { } => new object();
}
}");
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree, ignoreAccessibility: false);
var creation = tree.GetRoot().DescendantNodes().OfType<ObjectCreationExpressionSyntax>().Single();
var operation = model.GetOperation(creation);
Assert.Null(operation); // we didn't bind the expression body, but should. See issue https://github.com/dotnet/roslyn/issues/24650
var info = model.GetTypeInfo(creation);
Assert.Equal("System.Object", info.Type.ToTestDisplayString());
Assert.Equal("System.Object", info.ConvertedType.ToTestDisplayString());
}
[Fact]
[WorkItem(22027, "https://github.com/dotnet/roslyn/issues/22027")]
public void Repro22027()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册