提交 a8dcfc93 编写于 作者: A AlekseyTs

Prevent future backward compatibility issues around supporting deconstruction...

Prevent future backward compatibility issues around supporting deconstruction declaration as an out argument.

Fixes #13148.
上级 7fea5237
...@@ -7018,6 +7018,15 @@ internal class CSharpResources { ...@@ -7018,6 +7018,15 @@ internal class CSharpResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Deconstruction is not supported for an &apos;out&apos; argument..
/// </summary>
internal static string ERR_OutVarDeconstructionIsNotSupported {
get {
return ResourceManager.GetString("ERR_OutVarDeconstructionIsNotSupported", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to &apos;{0}&apos; cannot define overloaded methods that differ only on ref and out. /// Looks up a localized string similar to &apos;{0}&apos; cannot define overloaded methods that differ only on ref and out.
/// </summary> /// </summary>
......
...@@ -4944,4 +4944,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ ...@@ -4944,4 +4944,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_InvalidInstrumentationKind" xml:space="preserve"> <data name="ERR_InvalidInstrumentationKind" xml:space="preserve">
<value>Invalid instrumentation kind: {0}</value> <value>Invalid instrumentation kind: {0}</value>
</data> </data>
<data name="ERR_OutVarDeconstructionIsNotSupported" xml:space="preserve">
<value>Deconstruction is not supported for an 'out' argument.</value>
</data>
</root> </root>
\ No newline at end of file
...@@ -1431,6 +1431,7 @@ internal enum ErrorCode ...@@ -1431,6 +1431,7 @@ internal enum ErrorCode
ERR_ImplicitlyTypedOutVariableUsedInTheSameArgumentList = 8196, ERR_ImplicitlyTypedOutVariableUsedInTheSameArgumentList = 8196,
ERR_TypeInferenceFailedForImplicitlyTypedOutVariable = 8197, ERR_TypeInferenceFailedForImplicitlyTypedOutVariable = 8197,
ERR_ExpressionTreeContainsOutVariable = 8198, ERR_ExpressionTreeContainsOutVariable = 8198,
ERR_OutVarDeconstructionIsNotSupported = 8199,
#endregion diagnostics for out var #endregion diagnostics for out var
} }
} }
...@@ -9843,12 +9843,76 @@ private ArgumentSyntax ParseArgumentExpression(bool isIndexer) ...@@ -9843,12 +9843,76 @@ private ArgumentSyntax ParseArgumentExpression(bool isIndexer)
else else
{ {
expression = this.ParseSubExpression(Precedence.Expression); expression = this.ParseSubExpression(Precedence.Expression);
// See if the expression is an invocation that could also be successfully parsed and interpreted
// as a deconstruction target. I.e. something like "var (x, y)" or "var (x, (y, z))".
// We should report an error in this case because we plan to support deconstruction for out arguments
// in the future. We need to ensure that we do not successfully interpret this as an invocation of a
// ref-returning method named var with two, or more arguments.
if (IsDeconstructionCompatibleArgument(refOrOutKeyword, expression))
{
expression = this.AddError(expression, ErrorCode.ERR_OutVarDeconstructionIsNotSupported);
}
} }
} }
return _syntaxFactory.Argument(nameColon, refOrOutKeyword, expression); return _syntaxFactory.Argument(nameColon, refOrOutKeyword, expression);
} }
private static bool IsDeconstructionCompatibleArgument(SyntaxToken refOrOutKeyword, ExpressionSyntax expression)
{
if (refOrOutKeyword?.Kind == SyntaxKind.OutKeyword &&
expression.Kind == SyntaxKind.InvocationExpression)
{
var invocation = (InvocationExpressionSyntax)expression;
ExpressionSyntax invocationTarget = invocation.Expression;
return invocationTarget.Kind == SyntaxKind.IdentifierName &&
((IdentifierNameSyntax)invocationTarget).Identifier.IsVar() &&
invocation.ArgumentList.Arguments.Count > 1 &&
!expression.GetDiagnostics().Contains(info => info.Severity == DiagnosticSeverity.Error) &&
IsDeconstructionCompatibleArgumentList(invocation.ArgumentList.Arguments);
}
return false;
}
private static bool IsDeconstructionCompatibleArgumentList(SeparatedSyntaxList<ArgumentSyntax> arguments)
{
int count = arguments.Count;
for (int i = 0; i < count; i++)
{
ArgumentSyntax argument = arguments[i];
if (argument.NameColon != null || argument.RefOrOutKeyword != null)
{
return false;
}
switch (argument.Expression.Kind)
{
case SyntaxKind.IdentifierName:
// Identifier is compatible
break;
case SyntaxKind.TupleExpression:
// Tuple is compatible if its argument list is compatible
if (!IsDeconstructionCompatibleArgumentList(((TupleExpressionSyntax)argument.Expression).Arguments))
{
return false;
}
break;
default:
// Nothing else can be compatible.
return false;
}
}
return true;
}
private bool IsPossibleOutVarDeclaration() private bool IsPossibleOutVarDeclaration()
{ {
var tk = this.CurrentToken.Kind; var tk = this.CurrentToken.Kind;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册