提交 97c66864 编写于 作者: A AlekseyTs

Merge pull request #9442 from AlekseyTs/ctor_initializer

Test/fix scoping rules for pattern locals
......@@ -760,5 +760,24 @@ internal Binder WithPatternVariablesIfAny(ExpressionSyntax scopeOpt)
Debug.Assert(Locals.Length == 0);
return new PatternVariableBinder(scopeOpt, scopeOpt, this);
}
internal Binder WithPatternVariablesIfAny(ArgumentListSyntax initializerArgumentListOpt)
{
Debug.Assert(Locals.Length == 0);
if (initializerArgumentListOpt == null || initializerArgumentListOpt.Arguments.Count == 0)
{
return this;
}
return new PatternVariableBinder(initializerArgumentListOpt, initializerArgumentListOpt.Arguments, this);
}
internal BoundExpression WrapWithVariablesIfAny(BoundExpression expression)
{
return (Locals.Length == 0)
? expression
: new BoundSequence(expression.Syntax, Locals, ImmutableArray<BoundExpression>.Empty, expression, expression.Type) { WasCompilerGenerated = true };
}
}
}
......@@ -94,7 +94,7 @@ internal static void BindAttributeTypes(ImmutableArray<Binder> binders, Immutabl
internal CSharpAttributeData GetAttribute(AttributeSyntax node, NamedTypeSymbol boundAttributeType, DiagnosticBag diagnostics)
{
var boundAttribute = BindAttribute(node, boundAttributeType, diagnostics);
var boundAttribute = new PatternVariableBinder(node, this).BindAttribute(node, boundAttributeType, diagnostics);
return GetAttribute(boundAttribute, diagnostics);
}
......
......@@ -339,7 +339,8 @@ internal BoundExpression BindValueAllowArgList(ExpressionSyntax node, Diagnostic
ParameterSymbol parameter,
EqualsValueClauseSyntax defaultValueSyntax)
{
return new LocalScopeBinder(this.WithContainingMemberOrLambda(parameter.ContainingSymbol).WithAdditionalFlags(BinderFlags.ParameterDefaultValue));
return new LocalScopeBinder(this.WithContainingMemberOrLambda(parameter.ContainingSymbol).WithAdditionalFlags(BinderFlags.ParameterDefaultValue)).
WithPatternVariablesIfAny(defaultValueSyntax.Value);
}
internal BoundExpression BindParameterDefaultValue(
......@@ -357,7 +358,7 @@ internal BoundExpression BindValueAllowArgList(ExpressionSyntax node, Diagnostic
// Always generate the conversion, even if the expression is not convertible to the given type.
// We want the erroneous conversion in the tree.
return GenerateConversionForAssignment(parameterType, valueBeforeConversion, diagnostics, isDefaultParameter: true);
return WrapWithVariablesIfAny(GenerateConversionForAssignment(parameterType, valueBeforeConversion, diagnostics, isDefaultParameter: true));
}
internal BoundExpression BindEnumConstantInitializer(
......@@ -2644,12 +2645,8 @@ private static bool IsNegativeConstantForArraySize(BoundExpression expression)
MethodSymbol constructor,
DiagnosticBag diagnostics)
{
// Handle scoping for possible pattern variables declared in the initializer
PatternVariableBinder patBinder = (initializerArgumentListOpt != null)
? new PatternVariableBinder(initializerArgumentListOpt, initializerArgumentListOpt.Arguments, this)
: null;
var result = (patBinder ?? this).BindConstructorInitializerCore(initializerArgumentListOpt, constructor, diagnostics);
return patBinder?.WrapWithPatternVariables(result) ?? result;
var result = BindConstructorInitializerCore(initializerArgumentListOpt, constructor, diagnostics);
return WrapWithVariablesIfAny(result);
}
private BoundExpression BindConstructorInitializerCore(
......
......@@ -270,7 +270,7 @@ internal struct ProcessedFieldInitializers
var collisionDetector = new LocalScopeBinder(binder);
var patternBinder = new PatternVariableBinder(equalsValueClauseNode, equalsValueClauseNode.Value, collisionDetector);
var boundInitValue = patternBinder.BindVariableOrAutoPropInitializer(equalsValueClauseNode, RefKind.None, fieldSymbol.GetFieldType(fieldsBeingBound), initializerDiagnostics);
boundInitValue = patternBinder.WrapWithPatternVariables(boundInitValue);
boundInitValue = patternBinder.WrapWithVariablesIfAny(boundInitValue);
if (isImplicitlyTypedField)
{
......
......@@ -3450,7 +3450,7 @@ private BoundExpression BindCatchFilter(CatchFilterClauseSyntax filter, Diagnost
Error(diagnostics, ErrorCode.WRN_FilterIsConstant, filter.FilterExpression);
}
boundFilter = patternBinder.WrapWithPatternVariables(boundFilter);
boundFilter = patternBinder.WrapWithVariablesIfAny(boundFilter);
boundFilter = new BoundSequencePointExpression(filter, boundFilter, boundFilter.Type);
return boundFilter;
}
......
......@@ -100,6 +100,23 @@ internal PatternVariableBinder(SyntaxNode syntax, ExpressionSyntax expression, B
this.Syntax = syntax;
}
internal PatternVariableBinder(AttributeSyntax syntax, Binder next) : base(next)
{
this.Syntax = syntax;
if (syntax.ArgumentList?.Arguments.Count > 0)
{
var expressions = ArrayBuilder<ExpressionSyntax>.GetInstance(syntax.ArgumentList.Arguments.Count);
foreach (var argument in syntax.ArgumentList.Arguments)
{
expressions.Add(argument.Expression);
}
this.Expressions = expressions.ToImmutableAndFree();
}
}
protected override ImmutableArray<LocalSymbol> BuildLocals()
{
var patterns = PatternVariableFinder.FindPatternVariables(Expression, Expressions, this.Patterns);
......@@ -111,12 +128,5 @@ protected override ImmutableArray<LocalSymbol> BuildLocals()
patterns.Free();
return builder.ToImmutableAndFree();
}
internal BoundExpression WrapWithPatternVariables(BoundExpression expression)
{
return (Locals.Length == 0)
? expression
: new BoundSequence(expression.Syntax, Locals, ImmutableArray<BoundExpression>.Empty, expression, expression.Type);
}
}
}
......@@ -32,6 +32,9 @@ class PatternVariableFinder : CSharpSyntaxWalker
if (subExpression != null) expressionsToVisit.Add(subExpression);
}
}
expressionsToVisit.ReverseContents();
finder.VisitExpressions();
if (!patterns.IsDefaultOrEmpty)
......
......@@ -28,7 +28,7 @@ private AttributeSemanticModel(CSharpCompilation compilation, AttributeSyntax sy
public static AttributeSemanticModel Create(CSharpCompilation compilation, AttributeSyntax syntax, NamedTypeSymbol attributeType, AliasSymbol aliasOpt, Binder rootBinder)
{
var executableBinder = new ExecutableCodeBinder(syntax, attributeType, rootBinder);
return new AttributeSemanticModel(compilation, syntax, attributeType, aliasOpt, new LocalScopeBinder(executableBinder));
return new AttributeSemanticModel(compilation, syntax, attributeType, aliasOpt, new PatternVariableBinder(syntax, executableBinder));
}
/// <summary>
......
......@@ -194,6 +194,7 @@ private BoundEqualsValue BindEqualsValue(Binder binder, EqualsValueClauseSyntax
}
if (result != null)
{
result = binder.WrapWithVariablesIfAny(result);
return new BoundFieldEqualsValue(equalsValue, field, result);
}
break;
......@@ -205,6 +206,7 @@ private BoundEqualsValue BindEqualsValue(Binder binder, EqualsValueClauseSyntax
BoundExpression result = binder.BindVariableOrAutoPropInitializer(equalsValue, RefKind.None, property.Type, diagnostics);
if (result != null)
{
result = binder.WrapWithVariablesIfAny(result);
return new BoundPropertyEqualsValue(equalsValue, property, result);
}
break;
......
......@@ -926,7 +926,7 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node)
variableDecl, //pass in the entire field initializer to permit region analysis.
fieldSymbol,
//if we're in regular C#, then insert an extra binder to perform field initialization checks
GetFieldOrPropertyInitializerBinder(fieldSymbol, outer));
GetFieldOrPropertyInitializerBinder(fieldSymbol, outer, variableDecl.Initializer?.Value));
}
case SyntaxKind.PropertyDeclaration:
......@@ -937,7 +937,7 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node)
this.Compilation,
propertyDecl,
propertySymbol,
GetFieldOrPropertyInitializerBinder(propertySymbol.BackingField, outer));
GetFieldOrPropertyInitializerBinder(propertySymbol.BackingField, outer, propertyDecl.Initializer?.Value));
}
case SyntaxKind.Parameter:
......@@ -968,7 +968,7 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node)
this.Compilation,
enumDecl,
enumSymbol,
GetFieldOrPropertyInitializerBinder(enumSymbol, outer));
GetFieldOrPropertyInitializerBinder(enumSymbol, outer, enumDecl.EqualsValue?.Value));
}
default:
throw ExceptionUtilities.UnexpectedValue(node.Parent.Kind());
......@@ -1042,7 +1042,9 @@ private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node)
(ConstructorInitializerSyntax)node,
constructorSymbol,
//insert an extra binder to perform constructor initialization checks
outer.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.ConstructorInitializer, constructorSymbol));
// Handle scoping for possible pattern variables declared in the initializer
outer.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.ConstructorInitializer, constructorSymbol).
WithPatternVariablesIfAny(((ConstructorInitializerSyntax)node).ArgumentList));
}
case SyntaxKind.Attribute:
......@@ -1084,7 +1086,7 @@ private SourceMemberFieldSymbol GetDeclaredFieldSymbol(VariableDeclaratorSyntax
return null;
}
private Binder GetFieldOrPropertyInitializerBinder(FieldSymbol symbol, Binder outer)
private Binder GetFieldOrPropertyInitializerBinder(FieldSymbol symbol, Binder outer, ExpressionSyntax valueSyntaxOpt)
{
BinderFlags flags = BinderFlags.None;
......@@ -1094,7 +1096,13 @@ private Binder GetFieldOrPropertyInitializerBinder(FieldSymbol symbol, Binder ou
flags |= BinderFlags.FieldInitializer;
}
return new LocalScopeBinder(outer).WithAdditionalFlagsAndContainingMemberOrLambda(flags, symbol);
Binder result = new LocalScopeBinder(outer).WithAdditionalFlagsAndContainingMemberOrLambda(flags, symbol);
if (valueSyntaxOpt != null)
{
result = result.WithPatternVariablesIfAny(valueSyntaxOpt);
}
return result;
}
private static bool IsMemberDeclaration(CSharpSyntaxNode node)
......
......@@ -1726,7 +1726,9 @@ internal static BoundExpression BindConstructorInitializer(MethodSymbol construc
}
// wrap in ConstructorInitializerBinder for appropriate errors
Binder initializerBinder = outerBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.ConstructorInitializer, constructor);
// Handle scoping for possible pattern variables declared in the initializer
Binder initializerBinder = outerBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.ConstructorInitializer, constructor).
WithPatternVariablesIfAny(initializerArgumentListOpt);
return initializerBinder.BindConstructorInitializer(initializerArgumentListOpt, constructor, diagnostics);
}
......
......@@ -52,15 +52,21 @@ internal static class ConstantValueUtils
DiagnosticBag diagnostics)
{
var enumConstant = fieldSymbol as SourceEnumConstantSymbol;
var collisionDetector = new LocalScopeBinder(binder);
Binder collisionDetector = new LocalScopeBinder(binder);
collisionDetector = collisionDetector.WithPatternVariablesIfAny(initializer.Value);
BoundExpression result;
if ((object)enumConstant != null)
{
return collisionDetector.BindEnumConstantInitializer(enumConstant, initializer.Value, diagnostics);
result = collisionDetector.BindEnumConstantInitializer(enumConstant, initializer.Value, diagnostics);
}
else
{
return collisionDetector.BindVariableOrAutoPropInitializer(initializer, RefKind.None, fieldSymbol.Type, diagnostics);
result = collisionDetector.BindVariableOrAutoPropInitializer(initializer, RefKind.None, fieldSymbol.Type, diagnostics);
}
result = collisionDetector.WrapWithVariablesIfAny(result);
return result;
}
internal static ConstantValue GetAndValidateConstantValue(
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册