提交 7f46797f 编写于 作者: J Julien 提交者: GitHub

Deconstruction-declaration in script (#13957)

上级 4c390351
......@@ -174,7 +174,7 @@ private BoundExpression FixTupleLiteral(ArrayBuilder<DeconstructionVariable> che
/// <summary>
/// The produces a deconstruction step with no Deconstruct method since the tuple already has distinct elements.
/// </summary>
private static BoundDeconstructionDeconstructStep MakeTupleDeconstructStep(
private BoundDeconstructionDeconstructStep MakeTupleDeconstructStep(
BoundDeconstructValuePlaceholder targetPlaceholder,
CSharpSyntaxNode syntax,
DiagnosticBag diagnostics,
......@@ -183,7 +183,7 @@ private BoundExpression FixTupleLiteral(ArrayBuilder<DeconstructionVariable> che
Debug.Assert(targetPlaceholder.Type.IsTupleType);
var tupleTypes = targetPlaceholder.Type.TupleElementTypes;
SetInferredTypes(variables, tupleTypes);
SetInferredTypes(variables, tupleTypes, diagnostics);
if (variables.Count != tupleTypes.Length)
{
......@@ -212,7 +212,7 @@ private BoundExpression FixTupleLiteral(ArrayBuilder<DeconstructionVariable> che
return null;
}
SetInferredTypes(variables, outPlaceholders.SelectAsArray(p => p.Type));
SetInferredTypes(variables, outPlaceholders.SelectAsArray(p => p.Type), diagnostics);
return new BoundDeconstructionDeconstructStep(syntax, deconstructInvocation, targetPlaceholder, outPlaceholders);
}
......@@ -220,15 +220,15 @@ private BoundExpression FixTupleLiteral(ArrayBuilder<DeconstructionVariable> che
/// <summary>
/// Inform the variables about found types.
/// </summary>
private static void SetInferredTypes(ArrayBuilder<DeconstructionVariable> variables, ImmutableArray<TypeSymbol> foundTypes)
private void SetInferredTypes(ArrayBuilder<DeconstructionVariable> variables, ImmutableArray<TypeSymbol> foundTypes, DiagnosticBag diagnostics)
{
var matchCount = Math.Min(variables.Count, foundTypes.Length);
for (int i = 0; i < matchCount; i++)
{
var variable = variables[i];
if (!variable.HasNestedVariables && variable.Single.Kind == BoundKind.DeconstructionLocalPendingInference)
if (!variable.HasNestedVariables && variable.Single.Kind == BoundKind.DeconstructionVariablePendingInference)
{
BoundLocal local = ((DeconstructionLocalPendingInference)variable.Single).SetInferredType(foundTypes[i], success: true);
BoundExpression local = ((DeconstructionVariablePendingInference)variable.Single).SetInferredType(foundTypes[i], this, diagnostics);
variables[i] = new DeconstructionVariable(local, local.Syntax);
}
}
......@@ -239,7 +239,7 @@ private static void SetInferredTypes(ArrayBuilder<DeconstructionVariable> variab
/// </summary>
private void FailRemainingInferences(ArrayBuilder<DeconstructionVariable> variables, DiagnosticBag diagnostics)
{
var count = variables.Count;
int count = variables.Count;
for (int i = 0; i < count; i++)
{
var variable = variables[i];
......@@ -249,9 +249,9 @@ private void FailRemainingInferences(ArrayBuilder<DeconstructionVariable> variab
}
else
{
if (variable.Single.Kind == BoundKind.DeconstructionLocalPendingInference)
if (variable.Single.Kind == BoundKind.DeconstructionVariablePendingInference)
{
var local = ((DeconstructionLocalPendingInference)variable.Single).FailInference(this);
BoundExpression local = ((DeconstructionVariablePendingInference)variable.Single).FailInference(this, diagnostics);
variables[i] = new DeconstructionVariable(local, local.Syntax);
}
}
......@@ -409,11 +409,6 @@ private static TypeSymbol MakeMergedTupleType(ArrayBuilder<DeconstructionVariabl
// typed-variable on the left
mergedType = variable.Single.Type;
}
else if ((object)mergedType == null)
{
// typeless-variable on the left and typeless-element on the right
Error(diagnostics, ErrorCode.ERR_DeconstructCouldNotInferMergedType, syntax, variable.Syntax, element.Syntax);
}
}
}
else
......@@ -619,21 +614,29 @@ internal BoundLocalDeconstructionDeclaration BindDeconstructionDeclarationStatem
internal BoundDeconstructionAssignmentOperator BindDeconstructionDeclaration(CSharpSyntaxNode node, VariableComponentSyntax declaration, ExpressionSyntax right,
DiagnosticBag diagnostics, BoundDeconstructValuePlaceholder rightPlaceholder = null)
{
DeconstructionVariable locals = BindDeconstructionDeclarationLocals(declaration, diagnostics);
DeconstructionVariable locals = BindDeconstructionDeclarationVariables(declaration, diagnostics);
Debug.Assert(locals.HasNestedVariables);
var result = BindDeconstructionAssignment(node, right, locals.NestedVariables, diagnostics, isDeclaration: true, rhsPlaceholder: rightPlaceholder);
FreeDeconstructionVariables(locals.NestedVariables);
return result;
}
private DeconstructionVariable BindDeconstructionDeclarationLocals(VariableComponentSyntax node, DiagnosticBag diagnostics)
/// <summary>
/// Prepares locals (or fields in global statement) corresponding to the variables of the declaration.
/// The locals/fields are kept in a tree which captures the nesting of variables.
/// Each local or field is either a simple local or field access (when its type is known) or a deconstruction variable pending inference.
/// The caller is responsible for releasing the nested ArrayBuilders.
/// </summary>
private DeconstructionVariable BindDeconstructionDeclarationVariables(
VariableComponentSyntax node,
DiagnosticBag diagnostics)
{
switch (node.Kind())
{
case SyntaxKind.TypedVariableComponent:
{
var component = (TypedVariableComponentSyntax)node;
return BindDeconstructionDeclarationLocals(component.Type, component.Designation, diagnostics);
return BindDeconstructionDeclarationVariables(component.Type, component.Designation, diagnostics);
}
case SyntaxKind.ParenthesizedVariableComponent:
{
......@@ -641,7 +644,7 @@ private DeconstructionVariable BindDeconstructionDeclarationLocals(VariableCompo
var builder = ArrayBuilder<DeconstructionVariable>.GetInstance(component.Variables.Count);
foreach (var n in component.Variables)
{
builder.Add(BindDeconstructionDeclarationLocals(n, diagnostics));
builder.Add(BindDeconstructionDeclarationVariables(n, diagnostics));
}
return new DeconstructionVariable(builder, node);
}
......@@ -650,14 +653,17 @@ private DeconstructionVariable BindDeconstructionDeclarationLocals(VariableCompo
}
}
private DeconstructionVariable BindDeconstructionDeclarationLocals(TypeSyntax type, VariableDesignationSyntax node, DiagnosticBag diagnostics)
private DeconstructionVariable BindDeconstructionDeclarationVariables(
TypeSyntax type,
VariableDesignationSyntax node,
DiagnosticBag diagnostics)
{
switch (node.Kind())
{
case SyntaxKind.SingleVariableDesignation:
{
var single = (SingleVariableDesignationSyntax)node;
return new DeconstructionVariable(BindDeconstructionDeclarationLocal(type, single, diagnostics), node);
return new DeconstructionVariable(BindDeconstructionDeclarationVariable(type, single, diagnostics), node);
}
case SyntaxKind.ParenthesizedVariableDesignation:
{
......@@ -665,7 +671,7 @@ private DeconstructionVariable BindDeconstructionDeclarationLocals(TypeSyntax ty
var builder = ArrayBuilder<DeconstructionVariable>.GetInstance();
foreach (var n in tuple.Variables)
{
builder.Add(BindDeconstructionDeclarationLocals(type, n, diagnostics));
builder.Add(BindDeconstructionDeclarationVariables(type, n, diagnostics));
}
return new DeconstructionVariable(builder, node);
}
......@@ -675,30 +681,18 @@ private DeconstructionVariable BindDeconstructionDeclarationLocals(TypeSyntax ty
}
/// <summary>
/// Prepares locals corresponding to the variables of the declaration.
/// The locals are kept in a tree which captures the nesting of variables.
/// Each local is either a simple local (when its type is known) or a deconstruction local pending inference.
/// The caller is responsible for releasing the nested ArrayBuilders.
/// In embedded statements, returns a BoundLocal when the type was explicit.
/// In global statements, returns a BoundFieldAccess when the type was explicit.
/// Otherwise returns a DeconstructionVariablePendingInference when the type is implicit.
/// </summary>
private ArrayBuilder<DeconstructionVariable> BindDeconstructionDeclarationLocals(VariableComponentAssignmentSyntax node, TypeSyntax closestTypeSyntax, DiagnosticBag diagnostics)
private BoundExpression BindDeconstructionDeclarationVariable(
TypeSyntax typeSyntax,
SingleVariableDesignationSyntax designation,
DiagnosticBag diagnostics)
{
var deconstructionVariable = BindDeconstructionDeclarationLocals(node.VariableComponent, diagnostics);
Debug.Assert(deconstructionVariable.HasNestedVariables);
return deconstructionVariable.NestedVariables;
}
/// <summary>
/// Returns a BoundLocal when the type was explicit, otherwise returns a DeconstructionLocalPendingInference.
/// </summary>
private BoundExpression BindDeconstructionDeclarationLocal(TypeSyntax typeSyntax, SingleVariableDesignationSyntax designation, DiagnosticBag diagnostics)
{
var localSymbol = LocateDeclaredVariableSymbol(designation, typeSyntax);
// Check for variable declaration errors.
// Use the binder that owns the scope for the local because this (the current) binder
// might own nested scope.
bool hasErrors = localSymbol.ScopeBinder.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics);
SourceLocalSymbol localSymbol = LookupLocal(designation.Identifier);
bool hasErrors = false;
bool isVar;
bool isConst = false;
AliasSymbol alias;
......@@ -712,11 +706,49 @@ private BoundExpression BindDeconstructionDeclarationLocal(TypeSyntax typeSyntax
Error(diagnostics, ErrorCode.ERR_DeconstructionVarFormDisallowsSpecificType, designation);
hasErrors = true;
}
}
// is this a local?
if (localSymbol != null)
{
// Check for variable declaration errors.
// Use the binder that owns the scope for the local because this (the current) binder
// might own nested scope.
hasErrors |= localSymbol.ScopeBinder.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics);
if (!isVar)
{
return new BoundLocal(designation, localSymbol, constantValueOpt: null, type: declType, hasErrors: hasErrors);
}
return new DeconstructionVariablePendingInference(designation, localSymbol, receiverOpt: null);
}
return new BoundLocal(designation, localSymbol, constantValueOpt: null, type: declType, hasErrors: hasErrors);
// Is this a field?
SourceMemberFieldSymbolFromDesignation field = LookupDeclaredField(designation);
if ((object)field == null)
{
// We should have the right binder in the chain, cannot continue otherwise.
throw ExceptionUtilities.Unreachable;
}
BoundThisReference receiver = ThisReference(designation, this.ContainingType, hasErrors: false,
wasCompilerGenerated: true);
if (!isVar)
{
TypeSymbol fieldType = field.GetFieldType(this.FieldsBeingBound);
return new BoundFieldAccess(designation,
receiver,
field,
constantValueOpt: null,
resultKind: LookupResultKind.Viable,
type: fieldType,
hasErrors: hasErrors);
}
return new DeconstructionLocalPendingInference(designation, localSymbol);
return new DeconstructionVariablePendingInference(designation, field, receiver);
}
}
}
......@@ -384,9 +384,11 @@ protected override Symbol MakePatternVariable(DeclarationPatternSyntax node, Syn
{
throw ExceptionUtilities.Unreachable;
}
protected override Symbol MakeOutVariable(DeclarationExpressionSyntax node, BaseArgumentListSyntax argumentListSyntax, SyntaxNode nodeToBind)
{
return SourceMemberFieldSymbolFromDesignation.Create(_containingType, node.VariableDesignation(), _modifiers, _containingFieldOpt, nodeToBind);
return SourceMemberFieldSymbolFromDesignation.Create(_containingType, node.VariableDesignation(), node.Type(),
_modifiers, _containingFieldOpt, nodeToBind);
}
#region pool
......
......@@ -1601,10 +1601,13 @@
<Field Name="Type" Type="TypeSymbol" Override="true" Null="always"/>
</Node>
<!-- The node is transformed into BoundLocal after inference -->
<Node Name="DeconstructionLocalPendingInference" Base="BoundExpression">
<!-- The node is transformed into BoundLocal or BoundFieldAccess after inference -->
<Node Name="DeconstructionVariablePendingInference" Base="BoundExpression">
<!-- Type is not significant for this node type; always null -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="always"/>
<Field Name="LocalSymbol" Type="SourceLocalSymbol"/>
<!-- A local symbol or a field symbol representing the variable -->
<Field Name="VariableSymbol" Type="Symbol"/>
<!-- A field receiver when VariableSymbol is a field -->
<Field Name="ReceiverOpt" Type="BoundExpression" Null="allow"/>
</Node>
</Tree>
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Diagnostics;
namespace Microsoft.CodeAnalysis.CSharp
{
internal partial class DeconstructionLocalPendingInference
{
public BoundLocal SetInferredType(TypeSymbol type, bool success)
{
Debug.Assert((object)type != null);
Debug.Assert(this.Syntax.Kind() == SyntaxKind.SingleVariableDesignation);
this.LocalSymbol.SetType(type);
return new BoundLocal(this.Syntax, this.LocalSymbol, constantValueOpt: null, type: type, hasErrors: this.HasErrors || !success);
}
public BoundLocal FailInference(Binder binder)
{
return this.SetInferredType(binder.CreateErrorType("var"), success: false);
}
}
}
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Diagnostics;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp
{
internal partial class DeconstructionVariablePendingInference
{
public BoundExpression SetInferredType(TypeSymbol type, Binder binderOpt, DiagnosticBag diagnostics)
{
Debug.Assert(binderOpt != null || (object)type != null);
Debug.Assert(this.Syntax.Kind() == SyntaxKind.SingleVariableDesignation);
bool inferenceFailed = ((object)type == null);
if (inferenceFailed)
{
type = binderOpt.CreateErrorType("var");
}
switch (this.VariableSymbol.Kind)
{
case SymbolKind.Local:
var local = (SourceLocalSymbol)this.VariableSymbol;
if (inferenceFailed)
{
ReportInferenceFailure(diagnostics);
}
local.SetType(type);
return new BoundLocal(this.Syntax, local, constantValueOpt: null, type: type, hasErrors: this.HasErrors || inferenceFailed);
case SymbolKind.Field:
var field = (SourceMemberFieldSymbolFromDesignation)this.VariableSymbol;
var inferenceDiagnostics = DiagnosticBag.GetInstance();
if (inferenceFailed)
{
ReportInferenceFailure(inferenceDiagnostics);
}
field.SetType(type, inferenceDiagnostics);
inferenceDiagnostics.Free();
return new BoundFieldAccess(this.Syntax, this.ReceiverOpt, field, constantValueOpt: null, hasErrors: this.HasErrors || inferenceFailed);
default:
throw ExceptionUtilities.Unreachable;
}
}
private void ReportInferenceFailure(DiagnosticBag diagnostics)
{
var designation = (SingleVariableDesignationSyntax)this.Syntax;
Binder.Error(
diagnostics, ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, designation.Identifier,
designation.Identifier.ValueText);
}
public BoundExpression FailInference(Binder binder, DiagnosticBag diagnosticsOpt)
{
return this.SetInferredType(null, binder, diagnosticsOpt);
}
}
}
\ No newline at end of file
......@@ -3000,7 +3000,7 @@ protected override OperationKind ExpressionKind
/// This node represents a deconstruction local.
/// It is only used temporarily during initial binding.
/// </summary>
internal partial class DeconstructionLocalPendingInference
internal partial class DeconstructionVariablePendingInference
{
public override void Accept(OperationVisitor visitor)
{
......
......@@ -120,7 +120,7 @@ public override object Display
}
}
internal partial class DeconstructionLocalPendingInference
internal partial class DeconstructionVariablePendingInference
{
public override object Display
{
......
......@@ -199,7 +199,7 @@
<Compile Include="BoundTree\Constructors.cs" />
<Compile Include="BoundTree\DecisionTree.cs" />
<Compile Include="BoundTree\Expression.cs" />
<Compile Include="BoundTree\DeconstructionLocalPendingInference.cs" />
<Compile Include="BoundTree\DeconstructionVariablePendingInference.cs" />
<Compile Include="BoundTree\OutVariablePendingInference.cs" />
<Compile Include="BoundTree\OutDeconstructVarPendingInference.cs" />
<Compile Include="BoundTree\PseudoVariableExpressions.cs" />
......
......@@ -3103,15 +3103,6 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to The type information on the left-hand-side &apos;{0}&apos; and right-hand-side &apos;{1}&apos; of the deconstruction was insufficient to infer a merged type..
/// </summary>
internal static string ERR_DeconstructCouldNotInferMergedType {
get {
return ResourceManager.GetString("ERR_DeconstructCouldNotInferMergedType", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Deconstruction &apos;var (...)&apos; form disallows a specific type for &apos;var&apos;..
/// </summary>
......@@ -8881,6 +8872,15 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to Cannot infer the type of implicitly-typed deconstruction variable &apos;{0}&apos;..
/// </summary>
internal static string ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable {
get {
return ResourceManager.GetString("ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cannot infer the type of implicitly-typed out variable &apos;{0}&apos;..
/// </summary>
......
......@@ -4908,6 +4908,9 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_TypeInferenceFailedForImplicitlyTypedOutVariable" xml:space="preserve">
<value>Cannot infer the type of implicitly-typed out variable '{0}'.</value>
</data>
<data name="ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable" xml:space="preserve">
<value>Cannot infer the type of implicitly-typed deconstruction variable '{0}'.</value>
</data>
<data name="ERR_DeconstructWrongCardinality" xml:space="preserve">
<value>Cannot deconstruct a tuple of '{0}' elements into '{1}' variables.</value>
</data>
......@@ -4935,9 +4938,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_ExplicitTupleElementNames" xml:space="preserve">
<value>Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names.</value>
</data>
<data name="ERR_DeconstructCouldNotInferMergedType" xml:space="preserve">
<value>The type information on the left-hand-side '{0}' and right-hand-side '{1}' of the deconstruction was insufficient to infer a merged type.</value>
</data>
<data name="ERR_ExpressionTreeContainsOutVariable" xml:space="preserve">
<value>An expression tree may not contain an out argument variable declaration.</value>
</data>
......
......@@ -1371,7 +1371,7 @@ internal enum ErrorCode
ERR_TupleDuplicateMemberName = 8127,
ERR_PredefinedTypeMemberNotFoundInAssembly = 8128,
ERR_MissingDeconstruct = 8129,
ERR_DeconstructCouldNotInferMergedType = 8130,
ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable = 8130,
ERR_DeconstructRequiresExpression = 8131,
ERR_DeconstructWrongCardinality = 8132,
ERR_CannotDeconstructDynamic = 8133,
......
......@@ -2654,7 +2654,7 @@ public override sealed BoundNode VisitOutVariablePendingInference(OutVariablePen
throw ExceptionUtilities.Unreachable;
}
public sealed override BoundNode VisitDeconstructionLocalPendingInference(DeconstructionLocalPendingInference node)
public sealed override BoundNode VisitDeconstructionVariablePendingInference(DeconstructionVariablePendingInference node)
{
throw ExceptionUtilities.Unreachable;
}
......
......@@ -285,9 +285,9 @@ public override sealed BoundNode VisitOutDeconstructVarPendingInference(OutDecon
throw ExceptionUtilities.Unreachable;
}
public override BoundNode VisitDeconstructionLocalPendingInference(DeconstructionLocalPendingInference node)
public override BoundNode VisitDeconstructionVariablePendingInference(DeconstructionVariablePendingInference node)
{
// DeconstructionLocalPendingInference nodes are only used within initial binding, but don't survive past that stage
// DeconstructionVariablePendingInference nodes are only used within initial binding, but don't survive past that stage
throw ExceptionUtilities.Unreachable;
}
......
......@@ -2406,6 +2406,17 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatement(SyntaxKind par
}
}
if (acceptStatement)
{
var deconstruction = ParseDeconstructionDeclarationAssignment();
if (deconstruction != null)
{
var semicolon = this.EatToken(SyntaxKind.SemicolonToken);
return _syntaxFactory.GlobalStatement(_syntaxFactory.DeconstructionDeclarationStatement(
new SyntaxList<SyntaxToken>(), deconstruction, semicolon));
}
}
// Everything that's left -- methods, fields, properties,
// indexers, and non-conversion operators -- starts with a type
// (possibly void). Parse that.
......
......@@ -2892,7 +2892,7 @@ private static bool HasNonConstantInitializer(ArrayBuilder<ImmutableArray<FieldO
if (IsScriptClass)
{
// also gather expression-declared variables from the bracketed argument lists and the initializers
ExpressionFieldFinder.FindExpressionVariables(builder.NonTypeNonIndexerMembers, variable, this,
ExpressionFieldFinder.FindExpressionVariables(builder.NonTypeNonIndexerMembers, variable, this,
DeclarationModifiers.Private | (modifiers & DeclarationModifiers.Static),
fieldSymbol);
}
......@@ -3149,12 +3149,18 @@ private static bool HasNonConstantInitializer(ArrayBuilder<ImmutableArray<FieldO
switch (innerStatement.Kind())
{
case SyntaxKind.DeconstructionDeclarationStatement:
var assignment = ((DeconstructionDeclarationStatementSyntax)innerStatement).Assignment;
CollectFieldsFromGlobalDeconstruction(builder.NonTypeNonIndexerMembers,
assignment.VariableComponent,
assignment);
ExpressionFieldFinder.FindExpressionVariables(builder.NonTypeNonIndexerMembers,
((DeconstructionDeclarationStatementSyntax)innerStatement).Assignment.Value,
this,
DeclarationModifiers.Private,
containingFieldOpt: null);
break;
assignment.Value,
this,
DeclarationModifiers.Private,
containingFieldOpt: null);
break;
case SyntaxKind.LocalDeclarationStatement:
// We shouldn't reach this place, but field declarations preceded with a label end up here.
......@@ -3207,6 +3213,57 @@ private static bool HasNonConstantInitializer(ArrayBuilder<ImmutableArray<FieldO
AddInitializers(builder.StaticInitializers, staticInitializers);
}
private void CollectFieldsFromGlobalDeconstruction(ArrayBuilder<Symbol> builder, VariableComponentSyntax variableComponent,
VariableComponentAssignmentSyntax assignment)
{
switch (variableComponent.Kind())
{
case SyntaxKind.TypedVariableComponent:
var typed = (TypedVariableComponentSyntax)variableComponent;
CollectFieldsFromGlobalDeconstruction(
builder,
typed.Designation,
typed.Type,
assignment);
break;
case SyntaxKind.ParenthesizedVariableComponent:
foreach (VariableComponentSyntax variable in ((ParenthesizedVariableComponentSyntax)variableComponent).Variables)
{
CollectFieldsFromGlobalDeconstruction(builder, variable, assignment);
}
break;
default:
throw ExceptionUtilities.UnexpectedValue(variableComponent.Kind());
}
}
private void CollectFieldsFromGlobalDeconstruction(ArrayBuilder<Symbol> builder, VariableDesignationSyntax designation,
TypeSyntax type, VariableComponentAssignmentSyntax assignment)
{
switch (designation.Kind())
{
case SyntaxKind.SingleVariableDesignation:
var field = SourceMemberFieldSymbolFromDesignation.Create(this, (SingleVariableDesignationSyntax)designation,
type, DeclarationModifiers.Private, null, assignment);
builder.Add(field);
break;
case SyntaxKind.ParenthesizedVariableDesignation:
foreach (VariableDesignationSyntax variable in ((ParenthesizedVariableDesignationSyntax)designation).Variables)
{
CollectFieldsFromGlobalDeconstruction(builder, variable, type, assignment);
}
break;
default:
throw ExceptionUtilities.UnexpectedValue(designation.Kind());
}
}
private static bool IsGlobalCodeAllowed(CSharpSyntaxNode parent)
{
var parentKind = parent.Kind();
......
......@@ -15,28 +15,34 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols
internal class SourceMemberFieldSymbolFromDesignation : SourceMemberFieldSymbol
{
private TypeSymbol _lazyType;
private SyntaxReference _typeSyntax;
internal SourceMemberFieldSymbolFromDesignation(
SourceMemberContainerTypeSymbol containingType,
SingleVariableDesignationSyntax designation,
TypeSyntax typeSyntax,
DeclarationModifiers modifiers)
: base(containingType, modifiers, designation.Identifier.ValueText, designation.GetReference(), designation.Identifier.GetLocation())
{
Debug.Assert(DeclaredAccessibility == Accessibility.Private);
_typeSyntax = typeSyntax.GetReference();
}
internal static SourceMemberFieldSymbolFromDesignation Create(
SourceMemberContainerTypeSymbol containingType,
SingleVariableDesignationSyntax designation,
TypeSyntax typeSyntax,
DeclarationModifiers modifiers,
FieldSymbol containingFieldOpt,
SyntaxNode nodeToBind)
{
Debug.Assert(nodeToBind.Kind() == SyntaxKind.VariableDeclarator || nodeToBind is ExpressionSyntax);
var typeSyntax = ((TypedVariableComponentSyntax)designation.Parent).Type;
Debug.Assert(nodeToBind.Kind() == SyntaxKind.VariableDeclarator
|| nodeToBind is ExpressionSyntax
|| nodeToBind.Kind() == SyntaxKind.VariableComponentAssignment);
return typeSyntax.IsVar
? new SourceMemberFieldSymbolFromDesignationWithEnclosingContext(containingType, designation, modifiers, containingFieldOpt, nodeToBind)
: new SourceMemberFieldSymbolFromDesignation(containingType, designation, modifiers);
? new SourceMemberFieldSymbolFromDesignationWithEnclosingContext(containingType, designation, typeSyntax, modifiers, containingFieldOpt, nodeToBind)
: new SourceMemberFieldSymbolFromDesignation(containingType, designation, typeSyntax, modifiers);
}
protected override SyntaxList<AttributeListSyntax> AttributeDeclarationSyntaxList
......@@ -54,14 +60,8 @@ public SingleVariableDesignationSyntax VariableDesignation
return (SingleVariableDesignationSyntax)this.SyntaxNode;
}
}
protected override TypeSyntax TypeSyntax
{
get
{
return ((TypedVariableComponentSyntax)VariableDesignation.Parent).Type;
}
}
protected override TypeSyntax TypeSyntax => (TypeSyntax)_typeSyntax.GetSyntax();
protected override SyntaxTokenList ModifiersTokenList
{
......@@ -170,16 +170,19 @@ private class SourceMemberFieldSymbolFromDesignationWithEnclosingContext : Sourc
private readonly FieldSymbol _containingFieldOpt;
private readonly SyntaxReference _nodeToBind;
internal SourceMemberFieldSymbolFromDesignationWithEnclosingContext(
SourceMemberContainerTypeSymbol containingType,
SingleVariableDesignationSyntax designation,
TypeSyntax typeSyntax,
DeclarationModifiers modifiers,
FieldSymbol containingFieldOpt,
SyntaxNode nodeToBind)
: base(containingType, designation, modifiers)
: base(containingType, designation, typeSyntax, modifiers)
{
Debug.Assert(nodeToBind.Kind() == SyntaxKind.VariableDeclarator || nodeToBind is ExpressionSyntax);
Debug.Assert(nodeToBind.Kind() == SyntaxKind.VariableDeclarator
|| nodeToBind is ExpressionSyntax
|| nodeToBind.Kind() == SyntaxKind.VariableComponentAssignment);
_containingFieldOpt = containingFieldOpt;
_nodeToBind = nodeToBind.GetReference();
}
......@@ -207,6 +210,14 @@ protected override void InferFieldType(ConsList<FieldSymbol> fieldsBeingBound, B
binder.BindDeclaratorArguments((VariableDeclaratorSyntax)nodeToBind, diagnostics);
break;
case SyntaxKind.VariableComponentAssignment:
var deconstruction = (VariableComponentAssignmentSyntax)nodeToBind;
binder.BindDeconstructionDeclaration(deconstruction, deconstruction.VariableComponent,
deconstruction.Value, diagnostics);
break;
default:
binder.BindExpression((ExpressionSyntax)nodeToBind, diagnostics);
break;
......
......@@ -1325,6 +1325,7 @@ static void Main()
var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular6);
comp.VerifyDiagnostics(
// (6,9): error CS8059: Feature 'tuples' is not available in C# 6. Please use language version 7 or greater.
// var (x1, x2) = Pair.Create(1, 2);
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "var (x1, x2)").WithArguments("tuples", "7").WithLocation(6, 9),
// (7,9): error CS8059: Feature 'tuples' is not available in C# 6. Please use language version 7 or greater.
......@@ -1335,7 +1336,19 @@ static void Main()
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "(int x5, var (x6, x7))").WithArguments("tuples", "7").WithLocation(8, 18),
// (9,14): error CS8059: Feature 'tuples' is not available in C# 6. Please use language version 7 or greater.
// for ((int x8, var (x9, x10)) = Pair.Create(1, Pair.Create(2, 3)); ; ) { }
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "(int x8, var (x9, x10))").WithArguments("tuples", "7").WithLocation(9, 14)
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "(int x8, var (x9, x10))").WithArguments("tuples", "7").WithLocation(9, 14),
// (8,32): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x6'.
// foreach ((int x5, var (x6, x7)) in new[] { Pair.Create(1, Pair.Create(2, 3)) }) { }
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x6").WithArguments("x6").WithLocation(8, 32),
// (8,36): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x7'.
// foreach ((int x5, var (x6, x7)) in new[] { Pair.Create(1, Pair.Create(2, 3)) }) { }
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x7").WithArguments("x7").WithLocation(8, 36),
// (9,28): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x9'.
// for ((int x8, var (x9, x10)) = Pair.Create(1, Pair.Create(2, 3)); ; ) { }
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x9").WithArguments("x9").WithLocation(9, 28),
// (9,32): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x10'.
// for ((int x8, var (x9, x10)) = Pair.Create(1, Pair.Create(2, 3)); ; ) { }
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x10").WithArguments("x10").WithLocation(9, 32)
);
}
......@@ -1535,7 +1548,13 @@ static void Main()
comp.VerifyDiagnostics(
// (6,24): error CS8131: Deconstruct assignment requires an expression with a type on the right-hand-side.
// var (x1, x2) = null;
Diagnostic(ErrorCode.ERR_DeconstructRequiresExpression, "null").WithLocation(6, 24)
Diagnostic(ErrorCode.ERR_DeconstructRequiresExpression, "null").WithLocation(6, 24),
// (6,14): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x1'.
// var (x1, x2) = null;
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x1").WithArguments("x1").WithLocation(6, 14),
// (6,18): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x2'.
// var (x1, x2) = null;
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x2").WithArguments("x2").WithLocation(6, 18)
);
}
......@@ -1553,9 +1572,12 @@ static void Main()
";
var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (6,9): error CS8130: The type information on the left-hand-side 'x2' and right-hand-side 'null' of the deconstruction was insufficient to infer a merged type.
// (6,14): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x1'.
// var (x1, x2) = (1, null);
Diagnostic(ErrorCode.ERR_DeconstructCouldNotInferMergedType, "var (x1, x2) = (1, null);").WithArguments("x2", "null").WithLocation(6, 9)
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x1").WithArguments("x1").WithLocation(6, 14),
// (6,18): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x2'.
// var (x1, x2) = (1, null);
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x2").WithArguments("x2").WithLocation(6, 18)
);
}
......@@ -1573,12 +1595,12 @@ static void Main()
";
var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (6,9): error CS8130: The type information on the left-hand-side 'x3' and right-hand-side 'null' of the deconstruction was insufficient to infer a merged type.
// (6,35): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x3'.
// (string x1, (byte x2, var x3), var x4) = (null, (2, null), null);
Diagnostic(ErrorCode.ERR_DeconstructCouldNotInferMergedType, "(string x1, (byte x2, var x3), var x4) = (null, (2, null), null);").WithArguments("x3", "null").WithLocation(6, 9),
// (6,9): error CS8130: The type information on the left-hand-side 'x4' and right-hand-side 'null' of the deconstruction was insufficient to infer a merged type.
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x3").WithArguments("x3").WithLocation(6, 35),
// (6,44): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x4'.
// (string x1, (byte x2, var x3), var x4) = (null, (2, null), null);
Diagnostic(ErrorCode.ERR_DeconstructCouldNotInferMergedType, "(string x1, (byte x2, var x3), var x4) = (null, (2, null), null);").WithArguments("x4", "null").WithLocation(6, 9)
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x4").WithArguments("x4").WithLocation(6, 44)
);
}
......@@ -1598,7 +1620,10 @@ static void Main()
comp.VerifyDiagnostics(
// (6,51): error CS8131: Deconstruct assignment requires an expression with a type on the right-hand-side.
// ((string x1, byte x2, var x3), int x4) = (null, 4);
Diagnostic(ErrorCode.ERR_DeconstructRequiresExpression, "null").WithLocation(6, 51)
Diagnostic(ErrorCode.ERR_DeconstructRequiresExpression, "null").WithLocation(6, 51),
// (6,35): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x3'.
// ((string x1, byte x2, var x3), int x4) = (null, 4);
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x3").WithArguments("x3").WithLocation(6, 35)
);
}
......@@ -1616,9 +1641,9 @@ static void Main()
";
var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (6,9): error CS8130: The type information on the left-hand-side 'x2' and right-hand-side '(null, 2)' of the deconstruction was insufficient to infer a merged type.
// (6,25): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x2'.
// (string x1, var x2) = (null, (null, 2));
Diagnostic(ErrorCode.ERR_DeconstructCouldNotInferMergedType, "(string x1, var x2) = (null, (null, 2));").WithArguments("x2", "(null, 2)").WithLocation(6, 9)
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x2").WithArguments("x2").WithLocation(6, 25)
);
}
......@@ -1662,7 +1687,10 @@ static void Main()
Diagnostic(ErrorCode.ERR_DeconstructWrongCardinality, @"(string x1, var y1) = (null, ""hello"", 3);").WithArguments("3", "2").WithLocation(6, 9),
// (7,47): error CS8131: Deconstruct assignment requires an expression with a type on the right-hand-side.
// (string x2, var y2) = (null, "hello", null);
Diagnostic(ErrorCode.ERR_DeconstructRequiresExpression, "null").WithLocation(7, 47)
Diagnostic(ErrorCode.ERR_DeconstructRequiresExpression, "null").WithLocation(7, 47),
// (7,25): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'y2'.
// (string x2, var y2) = (null, "hello", null);
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "y2").WithArguments("y2").WithLocation(7, 25)
);
}
......@@ -1749,7 +1777,13 @@ static void Main()
comp.VerifyDiagnostics(
// (6,9): error CS8132: Cannot deconstruct a tuple of '3' elements into '2' variables.
// (var (x1, x2), var x3) = (1, 2, 3);
Diagnostic(ErrorCode.ERR_DeconstructWrongCardinality, "(var (x1, x2), var x3) = (1, 2, 3);").WithArguments("3", "2").WithLocation(6, 9)
Diagnostic(ErrorCode.ERR_DeconstructWrongCardinality, "(var (x1, x2), var x3) = (1, 2, 3);").WithArguments("3", "2").WithLocation(6, 9),
// (6,15): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x1'.
// (var (x1, x2), var x3) = (1, 2, 3);
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x1").WithArguments("x1").WithLocation(6, 15),
// (6,19): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x2'.
// (var (x1, x2), var x3) = (1, 2, 3);
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x2").WithArguments("x2").WithLocation(6, 19)
);
}
......@@ -1821,17 +1855,23 @@ static void Main()
var comp = CreateCompilationWithMscorlib(source);
comp.VerifyDiagnostics(
// (9,13): error CS0128: A local variable named 'x' is already defined in this scope
// var(x, y) = 42;
// var(x, y) = 42; // parsed as deconstruction
Diagnostic(ErrorCode.ERR_LocalDuplicate, "x").WithArguments("x").WithLocation(9, 13),
// (9,16): error CS0128: A local variable named 'y' is already defined in this scope
// var(x, y) = 42;
// var(x, y) = 42; // parsed as deconstruction
Diagnostic(ErrorCode.ERR_LocalDuplicate, "y").WithArguments("y").WithLocation(9, 16),
// (9,21): error CS1061: 'int' does not contain a definition for 'Deconstruct' and no extension method 'Deconstruct' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?)
// var(x, y) = 42;
// var(x, y) = 42; // parsed as deconstruction
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "42").WithArguments("int", "Deconstruct").WithLocation(9, 21),
// (9,21): error CS8129: No Deconstruct instance or extension method was found for type 'int', with 2 out parameters.
// var(x, y) = 42;
// var(x, y) = 42; // parsed as deconstruction
Diagnostic(ErrorCode.ERR_MissingDeconstruct, "42").WithArguments("int", "2").WithLocation(9, 21),
// (9,13): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x'.
// var(x, y) = 42; // parsed as deconstruction
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x").WithArguments("x").WithLocation(9, 13),
// (9,16): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'y'.
// var(x, y) = 42; // parsed as deconstruction
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "y").WithArguments("y").WithLocation(9, 16),
// (8,13): warning CS0219: The variable 'x' is assigned but its value is never used
// int x = 0, y = 0;
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x").WithArguments("x").WithLocation(8, 13),
......@@ -2223,7 +2263,13 @@ static void Main()
comp.VerifyDiagnostics(
// (6,34): error CS1579: foreach statement cannot operate on variables of type 'int' because 'int' does not contain a public definition for 'GetEnumerator'
// foreach (var (x1, x2) in 1)
Diagnostic(ErrorCode.ERR_ForEachMissingMember, "1").WithArguments("int", "GetEnumerator").WithLocation(6, 34)
Diagnostic(ErrorCode.ERR_ForEachMissingMember, "1").WithArguments("int", "GetEnumerator").WithLocation(6, 34),
// (6,23): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x1'.
// foreach (var (x1, x2) in 1)
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x1").WithArguments("x1").WithLocation(6, 23),
// (6,27): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x2'.
// foreach (var (x1, x2) in 1)
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x2").WithArguments("x2").WithLocation(6, 27)
);
}
......@@ -2277,7 +2323,13 @@ static void Main()
comp.VerifyDiagnostics(
// (6,36): error CS0103: The name 'x1' does not exist in the current context
// foreach (var (x1, x2) in M(x1)) { }
Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(6, 36)
Diagnostic(ErrorCode.ERR_NameNotInContext, "x1").WithArguments("x1").WithLocation(6, 36),
// (6,23): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x1'.
// foreach (var (x1, x2) in M(x1)) { }
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x1").WithArguments("x1").WithLocation(6, 23),
// (6,27): error CS8130: Cannot infer the type of implicitly-typed deconstruction variable 'x2'.
// foreach (var (x1, x2) in M(x1)) { }
Diagnostic(ErrorCode.ERR_TypeInferenceFailedForImplicitlyTypedDeconstructionVariable, "x2").WithArguments("x2").WithLocation(6, 27)
);
}
......
......@@ -23103,36 +23103,6 @@ public static bool TakeOutParam<T>(T y, out T x)
options: TestOptions.ReleaseExe.WithScriptClassName("Script"), parseOptions: TestOptions.Script);
compilation.VerifyDiagnostics(
// (2,17): error CS1519: Invalid token '=' in class, struct, or interface member declaration
// (bool a, int b) = (H.TakeOutParam(1, out int x1), 1);
Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(2, 17),
// (2,17): error CS1525: Invalid expression term '='
// (bool a, int b) = (H.TakeOutParam(1, out int x1), 1);
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "=").WithArguments("=").WithLocation(2, 17),
// (6,17): error CS1519: Invalid token '=' in class, struct, or interface member declaration
// (bool c, int d) = (H.TakeOutParam(2, out int x2), 2);
Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(6, 17),
// (6,17): error CS1525: Invalid expression term '='
// (bool c, int d) = (H.TakeOutParam(2, out int x2), 2);
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "=").WithArguments("=").WithLocation(6, 17),
// (8,17): error CS1519: Invalid token '=' in class, struct, or interface member declaration
// (bool e, int f) = (H.TakeOutParam(3, out int x3), 3);
Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(8, 17),
// (8,17): error CS1525: Invalid expression term '='
// (bool e, int f) = (H.TakeOutParam(3, out int x3), 3);
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "=").WithArguments("=").WithLocation(8, 17),
// (11,18): error CS1519: Invalid token '=' in class, struct, or interface member declaration
// (bool g, bool h) = (H.TakeOutParam(41, out int x4),
Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(11, 18),
// (11,18): error CS1525: Invalid expression term '='
// (bool g, bool h) = (H.TakeOutParam(41, out int x4),
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "=").WithArguments("=").WithLocation(11, 18),
// (14,20): error CS1519: Invalid token '=' in class, struct, or interface member declaration
// (bool x5, bool x6) = (H.TakeOutParam(5, out int x5),
Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(14, 20),
// (14,20): error CS1525: Invalid expression term '='
// (bool x5, bool x6) = (H.TakeOutParam(5, out int x5),
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "=").WithArguments("=").WithLocation(14, 20),
// (6,46): error CS0102: The type 'Script' already contains a definition for 'x2'
// (bool c, int d) = (H.TakeOutParam(2, out int x2), 2);
Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x2").WithArguments("Script", "x2").WithLocation(6, 46),
......@@ -23142,6 +23112,12 @@ public static bool TakeOutParam<T>(T y, out T x)
// (12,48): error CS0102: The type 'Script' already contains a definition for 'x4'
// H.TakeOutParam(42, out int x4));
Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("Script", "x4").WithLocation(12, 48),
// (14,49): error CS0102: The type 'Script' already contains a definition for 'x5'
// (bool x5, bool x6) = (H.TakeOutParam(5, out int x5),
Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("Script", "x5").WithLocation(14, 49),
// (15,49): error CS0102: The type 'Script' already contains a definition for 'x6'
// H.TakeOutParam(6, out int x6));
Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x6").WithArguments("Script", "x6").WithLocation(15, 49),
// (19,17): error CS0229: Ambiguity between 'x2' and 'x2'
// H.Dummy(x1, x2, x3, x4, x5, x6);
Diagnostic(ErrorCode.ERR_AmbigMember, "x2").WithArguments("x2", "x2").WithLocation(19, 17),
......@@ -23150,7 +23126,13 @@ public static bool TakeOutParam<T>(T y, out T x)
Diagnostic(ErrorCode.ERR_AmbigMember, "x3").WithArguments("x3", "x3").WithLocation(19, 21),
// (19,25): error CS0229: Ambiguity between 'x4' and 'x4'
// H.Dummy(x1, x2, x3, x4, x5, x6);
Diagnostic(ErrorCode.ERR_AmbigMember, "x4").WithArguments("x4", "x4").WithLocation(19, 25)
Diagnostic(ErrorCode.ERR_AmbigMember, "x4").WithArguments("x4", "x4").WithLocation(19, 25),
// (19,29): error CS0229: Ambiguity between 'x5' and 'x5'
// H.Dummy(x1, x2, x3, x4, x5, x6);
Diagnostic(ErrorCode.ERR_AmbigMember, "x5").WithArguments("x5", "x5").WithLocation(19, 29),
// (19,33): error CS0229: Ambiguity between 'x6' and 'x6'
// H.Dummy(x1, x2, x3, x4, x5, x6);
Diagnostic(ErrorCode.ERR_AmbigMember, "x6").WithArguments("x6", "x6").WithLocation(19, 33)
);
var tree = compilation.SyntaxTrees.Single();
......@@ -23177,13 +23159,13 @@ public static bool TakeOutParam<T>(T y, out T x)
var x5Decl = GetOutVarDeclarations(tree, "x5").Single();
var x5Ref = GetReferences(tree, "x5").ToArray();
Assert.Equal(2, x5Ref.Length);
VerifyModelForOutField(model, x5Decl, x5Ref[1]);
Assert.Equal(1, x5Ref.Length);
VerifyModelForOutFieldDuplicate(model, x5Decl, x5Ref[0]);
var x6Decl = GetOutVarDeclarations(tree, "x6").Single();
var x6Ref = GetReferences(tree, "x6").ToArray();
Assert.Equal(2, x6Ref.Length);
VerifyModelForOutField(model, x6Decl, x6Ref[1]);
Assert.Equal(1, x6Ref.Length);
VerifyModelForOutFieldDuplicate(model, x6Decl, x6Ref[0]);
}
{
......@@ -24016,6 +23998,12 @@ public static bool TakeOutParam<T>(T y, out T x)
// (12,48): error CS0102: The type 'Script' already contains a definition for 'x4'
// H.TakeOutParam(42, out int x4));
Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("Script", "x4").WithLocation(12, 48),
// (14,49): error CS0102: The type 'Script' already contains a definition for 'x5'
// (bool x5, bool x6) = (H.TakeOutParam(5, out int x5),
Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("Script", "x5").WithLocation(14, 49),
// (15,49): error CS0102: The type 'Script' already contains a definition for 'x6'
// H.TakeOutParam(6, out int x6));
Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x6").WithArguments("Script", "x6").WithLocation(15, 49),
// (1,1): warning CS0164: This label has not been referenced
// l1:
Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l1").WithLocation(1, 1),
......@@ -24039,7 +24027,13 @@ public static bool TakeOutParam<T>(T y, out T x)
Diagnostic(ErrorCode.ERR_AmbigMember, "x3").WithArguments("x3", "x3").WithLocation(19, 21),
// (19,25): error CS0229: Ambiguity between 'x4' and 'x4'
// H.Dummy(x1, x2, x3, x4, x5, x6);
Diagnostic(ErrorCode.ERR_AmbigMember, "x4").WithArguments("x4", "x4").WithLocation(19, 25)
Diagnostic(ErrorCode.ERR_AmbigMember, "x4").WithArguments("x4", "x4").WithLocation(19, 25),
// (19,29): error CS0229: Ambiguity between 'x5' and 'x5'
// H.Dummy(x1, x2, x3, x4, x5, x6);
Diagnostic(ErrorCode.ERR_AmbigMember, "x5").WithArguments("x5", "x5").WithLocation(19, 29),
// (19,33): error CS0229: Ambiguity between 'x6' and 'x6'
// H.Dummy(x1, x2, x3, x4, x5, x6);
Diagnostic(ErrorCode.ERR_AmbigMember, "x6").WithArguments("x6", "x6").WithLocation(19, 33)
);
var tree = compilation.SyntaxTrees.Single();
......@@ -24067,12 +24061,12 @@ public static bool TakeOutParam<T>(T y, out T x)
var x5Decl = GetOutVarDeclarations(tree, "x5").Single();
var x5Ref = GetReferences(tree, "x5").ToArray();
Assert.Equal(1, x5Ref.Length);
VerifyModelForOutField(model, x5Decl, x5Ref);
VerifyModelForOutFieldDuplicate(model, x5Decl, x5Ref);
var x6Decl = GetOutVarDeclarations(tree, "x6").Single();
var x6Ref = GetReferences(tree, "x6").ToArray();
Assert.Equal(1, x6Ref.Length);
VerifyModelForOutField(model, x6Decl, x6Ref);
VerifyModelForOutFieldDuplicate(model, x6Decl, x6Ref);
}
{
......@@ -24171,6 +24165,12 @@ public static bool TakeOutParam<T>(T y, out T x)
// (12,48): error CS0102: The type 'Script' already contains a definition for 'x4'
// H.TakeOutParam(42, out var x4));
Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x4").WithArguments("Script", "x4").WithLocation(12, 48),
// (14,49): error CS0102: The type 'Script' already contains a definition for 'x5'
// (bool x5, bool x6) = (H.TakeOutParam(5, out var x5),
Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x5").WithArguments("Script", "x5").WithLocation(14, 49),
// (15,49): error CS0102: The type 'Script' already contains a definition for 'x6'
// H.TakeOutParam(6, out var x6));
Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "x6").WithArguments("Script", "x6").WithLocation(15, 49),
// (1,1): warning CS0164: This label has not been referenced
// l1:
Diagnostic(ErrorCode.WRN_UnreferencedLabel, "l1").WithLocation(1, 1),
......@@ -24194,7 +24194,13 @@ public static bool TakeOutParam<T>(T y, out T x)
Diagnostic(ErrorCode.ERR_AmbigMember, "x3").WithArguments("x3", "x3").WithLocation(19, 21),
// (19,25): error CS0229: Ambiguity between 'x4' and 'x4'
// H.Dummy(x1, x2, x3, x4, x5, x6);
Diagnostic(ErrorCode.ERR_AmbigMember, "x4").WithArguments("x4", "x4").WithLocation(19, 25)
Diagnostic(ErrorCode.ERR_AmbigMember, "x4").WithArguments("x4", "x4").WithLocation(19, 25),
// (19,29): error CS0229: Ambiguity between 'x5' and 'x5'
// H.Dummy(x1, x2, x3, x4, x5, x6);
Diagnostic(ErrorCode.ERR_AmbigMember, "x5").WithArguments("x5", "x5").WithLocation(19, 29),
// (19,33): error CS0229: Ambiguity between 'x6' and 'x6'
// H.Dummy(x1, x2, x3, x4, x5, x6);
Diagnostic(ErrorCode.ERR_AmbigMember, "x6").WithArguments("x6", "x6").WithLocation(19, 33)
);
var tree = compilation.SyntaxTrees.Single();
......@@ -24222,12 +24228,12 @@ public static bool TakeOutParam<T>(T y, out T x)
var x5Decl = GetOutVarDeclarations(tree, "x5").Single();
var x5Ref = GetReferences(tree, "x5").ToArray();
Assert.Equal(1, x5Ref.Length);
VerifyModelForOutField(model, x5Decl, x5Ref);
VerifyModelForOutFieldDuplicate(model, x5Decl, x5Ref);
var x6Decl = GetOutVarDeclarations(tree, "x6").Single();
var x6Ref = GetReferences(tree, "x6").ToArray();
Assert.Equal(1, x6Ref.Length);
VerifyModelForOutField(model, x6Decl, x6Ref);
VerifyModelForOutFieldDuplicate(model, x6Decl, x6Ref);
}
{
......@@ -1538,6 +1538,169 @@ void Foo()
EOF();
}
[Fact]
public void DeconstructionInScript()
{
var tree = UsingTree(@" (int x, int y) = (1, 2); ", options: TestOptions.Script);
N(SyntaxKind.CompilationUnit);
{
N(SyntaxKind.GlobalStatement);
{
N(SyntaxKind.DeconstructionDeclarationStatement);
{
N(SyntaxKind.VariableComponentAssignment);
{
N(SyntaxKind.ParenthesizedVariableComponent);
{
N(SyntaxKind.OpenParenToken);
N(SyntaxKind.TypedVariableComponent);
{
N(SyntaxKind.PredefinedType);
{
N(SyntaxKind.IntKeyword);
}
N(SyntaxKind.SingleVariableDesignation);
{
N(SyntaxKind.IdentifierToken, "x");
}
}
N(SyntaxKind.CommaToken);
N(SyntaxKind.TypedVariableComponent);
{
N(SyntaxKind.PredefinedType);
{
N(SyntaxKind.IntKeyword);
}
N(SyntaxKind.SingleVariableDesignation);
{
N(SyntaxKind.IdentifierToken, "y");
}
}
N(SyntaxKind.CloseParenToken);
}
N(SyntaxKind.EqualsToken);
N(SyntaxKind.TupleExpression);
{
N(SyntaxKind.OpenParenToken);
N(SyntaxKind.Argument);
{
N(SyntaxKind.NumericLiteralExpression);
{
N(SyntaxKind.NumericLiteralToken);
}
}
N(SyntaxKind.CommaToken);
N(SyntaxKind.Argument);
{
N(SyntaxKind.NumericLiteralExpression);
{
N(SyntaxKind.NumericLiteralToken);
}
}
N(SyntaxKind.CloseParenToken);
}
}
N(SyntaxKind.SemicolonToken);
}
}
N(SyntaxKind.EndOfFileToken);
}
EOF();
}
[Fact]
public void DeconstructionForEachInScript()
{
var tree = UsingTree(@" foreach ((int x, int y) in new[] { (1, 2) }) { }; ", options: TestOptions.Script);
N(SyntaxKind.CompilationUnit);
{
N(SyntaxKind.GlobalStatement);
{
N(SyntaxKind.ForEachComponentStatement);
{
N(SyntaxKind.ForEachKeyword);
N(SyntaxKind.OpenParenToken);
N(SyntaxKind.ParenthesizedVariableComponent);
{
N(SyntaxKind.OpenParenToken);
N(SyntaxKind.TypedVariableComponent);
{
N(SyntaxKind.PredefinedType);
{
N(SyntaxKind.IntKeyword);
}
N(SyntaxKind.SingleVariableDesignation);
{
N(SyntaxKind.IdentifierToken, "x");
}
}
N(SyntaxKind.CommaToken);
N(SyntaxKind.TypedVariableComponent);
{
N(SyntaxKind.PredefinedType);
{
N(SyntaxKind.IntKeyword);
}
N(SyntaxKind.SingleVariableDesignation);
{
N(SyntaxKind.IdentifierToken, "y");
}
}
N(SyntaxKind.CloseParenToken);
}
N(SyntaxKind.InKeyword);
N(SyntaxKind.ImplicitArrayCreationExpression);
{
N(SyntaxKind.NewKeyword);
N(SyntaxKind.OpenBracketToken);
N(SyntaxKind.CloseBracketToken);
N(SyntaxKind.ArrayInitializerExpression);
{
N(SyntaxKind.OpenBraceToken);
N(SyntaxKind.TupleExpression);
{
N(SyntaxKind.OpenParenToken);
N(SyntaxKind.Argument);
{
N(SyntaxKind.NumericLiteralExpression);
{
N(SyntaxKind.NumericLiteralToken);
}
}
N(SyntaxKind.CommaToken);
N(SyntaxKind.Argument);
{
N(SyntaxKind.NumericLiteralExpression);
{
N(SyntaxKind.NumericLiteralToken);
}
}
N(SyntaxKind.CloseParenToken);
}
N(SyntaxKind.CloseBraceToken);
}
}
N(SyntaxKind.CloseParenToken);
N(SyntaxKind.Block);
{
N(SyntaxKind.OpenBraceToken);
N(SyntaxKind.CloseBraceToken);
}
}
}
N(SyntaxKind.GlobalStatement);
{
N(SyntaxKind.EmptyStatement);
{
N(SyntaxKind.SemicolonToken);
}
}
N(SyntaxKind.EndOfFileToken);
}
EOF();
}
[Fact]
public void TupleArray()
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册