Skip to content

Commit

Permalink
Disallow deconstruction declarations except at the statement level.
Browse files Browse the repository at this point in the history
This is now a semantic restriction (until we decide to remove it).
  • Loading branch information
gafter committed Nov 28, 2016
1 parent 1da1e53 commit 1003470
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 5 deletions.
36 changes: 31 additions & 5 deletions src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,38 @@ private BoundExpression BindDeconstruction(AssignmentExpressionSyntax node, Diag
CSharpSyntaxNode declaration = null;
CSharpSyntaxNode expression = null;
var result = BindDeconstruction(node, left, right, diagnostics, ref declaration, ref expression);
if (declaration != null && expression != null)
if (declaration != null)
{
// We only allow assignment-only or declaration-only deconstructions at this point.
// Issue https://github.com/dotnet/roslyn/issues/15050 tracks allowing mixed deconstructions.
// For now we give an error when you mix.
Error(diagnostics, ErrorCode.ERR_MixedDeconstructionUnsupported, left);
// only allowed at the top level, or in a for loop
switch (node.Parent?.Kind())
{
case null:
case SyntaxKind.ExpressionStatement:
if (expression != null)
{
// We only allow assignment-only or declaration-only deconstructions at this point.
// Issue https://github.com/dotnet/roslyn/issues/15050 tracks allowing mixed deconstructions.
// For now we give an error when you mix.
Error(diagnostics, ErrorCode.ERR_MixedDeconstructionUnsupported, left);
}
break;
case SyntaxKind.ForStatement:
if (((ForStatementSyntax)node.Parent).Initializers.Contains(node))
{
if (expression != null)
{
Error(diagnostics, ErrorCode.ERR_MixedDeconstructionUnsupported, left);
}
}
else
{
Error(diagnostics, ErrorCode.ERR_DeclarationExpressionNotPermitted, declaration);
}
break;
default:
Error(diagnostics, ErrorCode.ERR_DeclarationExpressionNotPermitted, declaration);
break;
}
}

return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2634,5 +2634,91 @@ static void Main()
Diagnostic(ErrorCode.ERR_TypeVarNotFound, "var").WithLocation(6, 15)
);
}

[Fact]
public void MixedDeconstruction_01()
{
string source = @"
class Program
{
static void Main(string[] args)
{
var t = (1, 2);
var x = (int y, int z) = t;
}
}";

var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (7,18): error CS8185: A declaration is not allowed in this context.
// var x = (int y, int z) = t;
Diagnostic(ErrorCode.ERR_DeclarationExpressionNotPermitted, "int y").WithLocation(7, 18)
);
}

[Fact]
public void MixedDeconstruction_02()
{
string source = @"
class Program
{
static void Main(string[] args)
{
var t = (1, 2);
int z;
(int y, z) = t;
}
}";

var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (8,9): error CS8184: A deconstruction cannot mix declarations and expressions on the left-hand-side.
// (int y, z) = t;
Diagnostic(ErrorCode.ERR_MixedDeconstructionUnsupported, "(int y, z)").WithLocation(8, 9)
);
}

[Fact]
public void MixedDeconstruction_03()
{
string source = @"
class Program
{
static void Main(string[] args)
{
var t = (1, 2);
int z;
for ((int y, z) = t; ; ) {}
}
}";

var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (8,14): error CS8184: A deconstruction cannot mix declarations and expressions on the left-hand-side.
// for ((int y, z) = t; ; ) {}
Diagnostic(ErrorCode.ERR_MixedDeconstructionUnsupported, "(int y, z)").WithLocation(8, 14)
);
}

[Fact]
public void MixedDeconstruction_04()
{
string source = @"
class Program
{
static void Main(string[] args)
{
var t = (1, 2);
for (; ; (int y, int z) = t) {}
}
}";

var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (7,19): error CS8185: A declaration is not allowed in this context.
// for (; ; (int y, int z) = t) {}
Diagnostic(ErrorCode.ERR_DeclarationExpressionNotPermitted, "int y").WithLocation(7, 19)
);
}
}
}

0 comments on commit 1003470

Please sign in to comment.