Skip to content

Commit

Permalink
Merge pull request #9265 from AlekseyTs/Issue8810
Browse files Browse the repository at this point in the history
Test/fix scoping of pattern variables in expression-bodied functions and properties.
  • Loading branch information
AlekseyTs committed Feb 28, 2016
2 parents 61c4a5b + 31172ce commit 5794403
Show file tree
Hide file tree
Showing 6 changed files with 450 additions and 12 deletions.
6 changes: 2 additions & 4 deletions src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ private BoundStatement BindLocalFunctionStatement(LocalFunctionStatementSyntax n
}
else if (node.ExpressionBody != null)
{
block = binder.BindExpressionBodyAsBlock(node.ExpressionBody, diagnostics);
block = binder.GetBinder(node.ExpressionBody).BindExpressionBodyAsBlock(node.ExpressionBody, diagnostics);
}
else
{
Expand Down Expand Up @@ -3575,9 +3575,7 @@ internal BoundBlock BindExpressionBodyAsBlock(ArrowExpressionClauseSyntax expres
DiagnosticBag diagnostics)
{
RefKind refKind = expressionBody.RefKeyword.Kind().GetRefKind();
PatternVariableBinder patternBinder = new PatternVariableBinder(expressionBody, expressionBody.Expression, this);
BoundExpression expression = patternBinder.BindValue(expressionBody.Expression, diagnostics, refKind != RefKind.None ? BindValueKind.RefReturn : BindValueKind.RValue);
expression = patternBinder.WrapWithPatternVariables(expression);
BoundExpression expression = BindValue(expressionBody.Expression, diagnostics, refKind != RefKind.None ? BindValueKind.RefReturn : BindValueKind.RValue);
return CreateBlockFromExpression(expressionBody, this.Locals, refKind, expression, expressionBody.Expression, diagnostics);
}

Expand Down
5 changes: 2 additions & 3 deletions src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,8 @@ public override void VisitLocalFunctionStatement(LocalFunctionStatementSyntax no

public override void VisitArrowExpressionClause(ArrowExpressionClauseSyntax node)
{
// TODO: Pattern variables in the => expression are local
//var arrowBinder = new PatternVariableBinder(node, node.Expression, _enclosing);
//AddToMap(node, arrowBinder);
var arrowBinder = new PatternVariableBinder(node, node.Expression, _enclosing);
AddToMap(node, arrowBinder);
}

public override void VisitAnonymousMethodExpression(AnonymousMethodExpressionSyntax node)
Expand Down
13 changes: 12 additions & 1 deletion src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ protected MemberSemanticModel(CSharpCompilation compilation, CSharpSyntaxNode ro
_compilation = compilation;
_root = root;
_memberSymbol = memberSymbol;

if (root.Kind() == SyntaxKind.ArrowExpressionClause)
{
rootBinder = rootBinder.WithPatternVariablesIfAny(((ArrowExpressionClauseSyntax)root).Expression);
}

this.RootBinder = rootBinder.WithAdditionalFlags(GetSemanticModelBinderFlags());
_parentSemanticModelOpt = parentSemanticModelOpt;
_speculatedPosition = speculatedPosition;
Expand Down Expand Up @@ -215,11 +221,16 @@ private Binder GetEnclosingBinder(CSharpSyntaxNode node, int position)
binder = RootBinder.GetBinder(current);
}
}
else if (current.Kind() == SyntaxKind.ArrowExpressionClause && current.Parent?.Kind() == SyntaxKind.LocalFunctionStatement)
{
binder = RootBinder.GetBinder(current);
}
else
{
// If this ever breaks, make sure that all callers of
// CanHaveAssociatedLocalBinder are in sync.
Debug.Assert(!current.CanHaveAssociatedLocalBinder());
Debug.Assert(!current.CanHaveAssociatedLocalBinder() ||
(current == _root && current.Kind() == SyntaxKind.ArrowExpressionClause));
}

if (current == _root)
Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1549,7 +1549,7 @@ private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSta
binder = new ExecutableCodeBinder(arrowExpression, sourceMethod, binder);
importChain = binder.ImportChain;
// Add locals
return binder.BindExpressionBodyAsBlock(arrowExpression, diagnostics);
return binder.WithPatternVariablesIfAny(arrowExpression.Expression).BindExpressionBodyAsBlock(arrowExpression, diagnostics);
}
else
{
Expand Down
8 changes: 5 additions & 3 deletions src/Compilers/CSharp/Portable/Syntax/SyntaxNodeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,13 @@ public static bool IsQuery(this CSharpSyntaxNode syntax)
/// </summary>
internal static bool CanHaveAssociatedLocalBinder(this CSharpSyntaxNode syntax)
{
SyntaxKind kind;
return syntax.IsAnonymousFunction() ||
syntax is StatementSyntax ||
syntax.Kind() == SyntaxKind.CatchClause ||
syntax.Kind() == SyntaxKind.CatchFilterClause ||
syntax.Kind() == SyntaxKind.SwitchSection;
(kind = syntax.Kind()) == SyntaxKind.CatchClause ||
kind == SyntaxKind.CatchFilterClause ||
kind == SyntaxKind.SwitchSection ||
kind == SyntaxKind.ArrowExpressionClause;
}

/// <summary>
Expand Down
Loading

0 comments on commit 5794403

Please sign in to comment.