提交 e560fdce 编写于 作者: N Neal Gafter 提交者: Neal Gafter

- Fix parsing regression of expressions involving parens when used as a case...

- Fix parsing regression of expressions involving parens when used as a case expression or a constant pattern.
Fixes #33054
Fixes #33208
- Incidentally also correct and test the precedence of the switch expression
See https://github.com/dotnet/csharplang/blob/master/proposals/patterns.md#switch-expression for the spec.
- Fix terminology to match the spec - "conditional expression" rather than "ternary expression".
上级 3ec26cae
......@@ -3060,10 +3060,10 @@ internal enum AddressKind
return true;
case BoundKind.ConditionalOperator:
var ternary = (BoundConditionalOperator)expression;
var conditional = (BoundConditionalOperator)expression;
// only ref ternary may be referenced as a variable
if (!ternary.IsRef)
// only ref conditional may be referenced as a variable
if (!conditional.IsRef)
{
return false;
}
......@@ -3071,8 +3071,8 @@ internal enum AddressKind
// branch that has no home will need a temporary
// if both have no home, just say whole expression has no home
// so we could just use one temp for the whole thing
return HasHome(ternary.Consequence, addressKind, method, peVerifyCompatEnabled, stackLocalsOpt)
&& HasHome(ternary.Alternative, addressKind, method, peVerifyCompatEnabled, stackLocalsOpt);
return HasHome(conditional.Consequence, addressKind, method, peVerifyCompatEnabled, stackLocalsOpt)
&& HasHome(conditional.Alternative, addressKind, method, peVerifyCompatEnabled, stackLocalsOpt);
default:
return false;
......
......@@ -3622,7 +3622,7 @@ private BoundExpression GenerateNullCoalescingAssignmentBadBinaryOpsError(Assign
/// <remarks>
/// From ExpressionBinder::EnsureQMarkTypesCompatible:
///
/// The v2.0 specification states that the types of the second and third operands T and S of a ternary operator
/// The v2.0 specification states that the types of the second and third operands T and S of a conditional operator
/// must be TT and TS such that either (a) TT==TS, or (b), TT->TS or TS->TT but not both.
///
/// Unfortunately that is not what we implemented in v2.0. Instead, we implemented
......
......@@ -6703,7 +6703,7 @@ internal class CSharpResources {
}
/// <summary>
/// Looks up a localized string similar to Branches of a ref ternary operator cannot refer to variables with incompatible declaration scopes.
/// Looks up a localized string similar to Branches of a ref conditional operator cannot refer to variables with incompatible declaration scopes.
/// </summary>
internal static string ERR_MismatchedRefEscapeInTernary {
get {
......
......@@ -4987,7 +4987,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<value>This combination of arguments to '{0}' is disallowed because it may expose variables referenced by parameter '{1}' outside of their declaration scope</value>
</data>
<data name="ERR_MismatchedRefEscapeInTernary" xml:space="preserve">
<value>Branches of a ref ternary operator cannot refer to variables with incompatible declaration scopes</value>
<value>Branches of a ref conditional operator cannot refer to variables with incompatible declaration scopes</value>
</data>
<data name="ERR_EscapeStackAlloc" xml:space="preserve">
<value>A result of a stackalloc expression of type '{0}' cannot be used in this context because it may be exposed outside of the containing method</value>
......
......@@ -3192,7 +3192,7 @@ private void EmitConditionalOperator(BoundConditionalOperator expr, bool used)
/// </remarks>
private void EmitNullCoalescingOperator(BoundNullCoalescingOperator expr, bool used)
{
Debug.Assert(expr.LeftConversion.IsIdentity, "coalesce with nontrivial left conversions are lowered into ternary.");
Debug.Assert(expr.LeftConversion.IsIdentity, "coalesce with nontrivial left conversions are lowered into conditional.");
Debug.Assert(expr.Type.IsReferenceType);
EmitExpression(expr.LeftOperand, used: true);
......@@ -3242,7 +3242,7 @@ private void EmitNullCoalescingOperator(BoundNullCoalescingOperator expr, bool u
}
// Implicit casts are not emitted. As a result verifier may operate on a different
// types from the types of operands when performing stack merges in coalesce/ternary.
// types from the types of operands when performing stack merges in coalesce/conditional.
// Such differences are in general irrelevant since merging rules work the same way
// for base and derived types.
//
......
......@@ -1503,7 +1503,7 @@ internal enum ErrorCode
ERR_NamedArgumentSpecificationBeforeFixedArgumentInDynamicInvocation = 8324,
#endregion diagnostics introduced for C# 7.2
#region diagnostics introduced for `ref readonly`, `ref ternary` and `ref-like` features in C# 7.2
#region diagnostics introduced for `ref readonly`, `ref conditional` and `ref-like` features in C# 7.2
ERR_RefConditionalAndAwait = 8325,
ERR_RefConditionalNeedsTwoRefs = 8326,
ERR_RefConditionalDifferentTypes = 8327,
......@@ -1538,7 +1538,7 @@ internal enum ErrorCode
ERR_EscapeStackAlloc = 8353,
ERR_RefReturnThis = 8354,
ERR_OutAttrOnInParam = 8355,
#endregion diagnostics introduced for `ref readonly`, `ref ternary` and `ref-like` features in C# 7.2
#endregion diagnostics introduced for `ref readonly`, `ref conditional` and `ref-like` features in C# 7.2
ERR_PredefinedValueTupleTypeAmbiguous3 = 8356,
ERR_InvalidVersionFormatDeterministic = 8357,
......
......@@ -2723,7 +2723,7 @@ private void VisitArgumentEvaluate(ImmutableArray<BoundExpression> arguments, Im
else
{
// As far as we can tell, there is no scenario relevant to nullability analysis
// where splitting an L-value (for instance with a ref ternary) would affect the result.
// where splitting an L-value (for instance with a ref conditional) would affect the result.
VisitLvalue(argument);
}
}
......
......@@ -26,8 +26,8 @@ public override BoundNode VisitLoweredConditionalAccess(BoundLoweredConditionalA
private enum ConditionalAccessLoweringKind
{
LoweredConditionalAccess,
Ternary,
TernaryCaptureReceiverByVal
Conditional,
ConditionalCaptureReceiverByVal
}
// IL gen can generate more compact code for certain conditional accesses
......@@ -46,10 +46,10 @@ internal BoundExpression RewriteConditionalAccess(BoundConditionalAccess node, b
}
ConditionalAccessLoweringKind loweringKind;
// dynamic receivers are not directly supported in codegen and need to be lowered to a ternary
var lowerToTernary = node.AccessExpression.Type.IsDynamic();
// dynamic receivers are not directly supported in codegen and need to be lowered to a conditional
var lowerToConditional = node.AccessExpression.Type.IsDynamic();
if (!lowerToTernary)
if (!lowerToConditional)
{
// trivial cases are directly supported in IL gen
loweringKind = ConditionalAccessLoweringKind.LoweredConditionalAccess;
......@@ -61,11 +61,11 @@ internal BoundExpression RewriteConditionalAccess(BoundConditionalAccess node, b
// so we can capture receiver by value in dynamic case regardless of
// the type of receiver
// Nullable receivers are immutable so should be captured by value as well.
loweringKind = ConditionalAccessLoweringKind.TernaryCaptureReceiverByVal;
loweringKind = ConditionalAccessLoweringKind.ConditionalCaptureReceiverByVal;
}
else
{
loweringKind = ConditionalAccessLoweringKind.Ternary;
loweringKind = ConditionalAccessLoweringKind.Conditional;
}
......@@ -84,11 +84,11 @@ internal BoundExpression RewriteConditionalAccess(BoundConditionalAccess node, b
break;
case ConditionalAccessLoweringKind.Ternary:
case ConditionalAccessLoweringKind.Conditional:
_currentConditionalAccessTarget = loweredReceiver;
break;
case ConditionalAccessLoweringKind.TernaryCaptureReceiverByVal:
case ConditionalAccessLoweringKind.ConditionalCaptureReceiverByVal:
temp = _factory.SynthesizedLocal(receiverType);
_currentConditionalAccessTarget = _factory.Local(temp);
break;
......@@ -155,15 +155,15 @@ internal BoundExpression RewriteConditionalAccess(BoundConditionalAccess node, b
break;
case ConditionalAccessLoweringKind.TernaryCaptureReceiverByVal:
case ConditionalAccessLoweringKind.ConditionalCaptureReceiverByVal:
// capture the receiver into a temp
loweredReceiver = _factory.MakeSequence(
_factory.AssignmentExpression(_factory.Local(temp), loweredReceiver),
_factory.Local(temp));
goto case ConditionalAccessLoweringKind.Ternary;
goto case ConditionalAccessLoweringKind.Conditional;
case ConditionalAccessLoweringKind.Ternary:
case ConditionalAccessLoweringKind.Conditional:
{
// (object)r != null ? access : default(T)
var condition = _factory.ObjectNotEqual(
......
......@@ -6191,7 +6191,7 @@ bool canBeNullableType()
return false;
if (mode == ParseTypeMode.NewExpression && type.Kind == SyntaxKind.TupleType &&
this.PeekToken(1).Kind != SyntaxKind.OpenParenToken && this.PeekToken(1).Kind != SyntaxKind.OpenBraceToken)
return false; // Permit `new (int, int)?(t)` (creation) and `new (int, int) ? x : y` (ternary)
return false; // Permit `new (int, int)?(t)` (creation) and `new (int, int) ? x : y` (conditional)
return true;
}
case SyntaxKind.AsteriskToken when type.Kind != SyntaxKind.ArrayType:
......@@ -8078,7 +8078,7 @@ private SwitchSectionSyntax ParseSwitchSection()
}
else
{
var node = CheckRecursivePatternFeature(ParseExpressionOrPattern(whenIsKeyword: true, forSwitchCase: true, precedence: Precedence.Ternary));
var node = CheckRecursivePatternFeature(ParseExpressionOrPattern(whenIsKeyword: true, forSwitchCase: true, precedence: Precedence.Conditional));
// if there is a 'when' token, we treat a case expression as a constant pattern.
if (this.CurrentToken.ContextualKind == SyntaxKind.WhenKeyword && node is ExpressionSyntax ex)
......@@ -8862,7 +8862,7 @@ enum Precedence : uint
Expression = 0, // Loosest possible precedence, used to accept all expressions
Assignment,
Lambda = Assignment, // "The => operator has the same precedence as assignment (=) and is right-associative."
Ternary,
Conditional,
Coalescing,
ConditionalOr,
ConditionalAnd,
......@@ -8921,6 +8921,7 @@ private static Precedence GetPrecedence(SyntaxKind op)
case SyntaxKind.IsExpression:
case SyntaxKind.AsExpression:
case SyntaxKind.IsPatternExpression:
case SyntaxKind.SwitchExpression:
return Precedence.Relational;
case SyntaxKind.LeftShiftExpression:
case SyntaxKind.RightShiftExpression:
......@@ -8957,7 +8958,6 @@ private static Precedence GetPrecedence(SyntaxKind op)
case SyntaxKind.RangeExpression:
return Precedence.Range;
case SyntaxKind.ConditionalExpression:
case SyntaxKind.SwitchExpression:
return Precedence.Expression;
default:
throw ExceptionUtilities.UnexpectedValue(op);
......@@ -9044,9 +9044,8 @@ private ExpressionSyntax ParseSubExpression(Precedence precedence)
private ExpressionSyntax ParseSubExpressionCore(Precedence precedence)
{
ExpressionSyntax leftOperand = null;
ExpressionSyntax leftOperand;
Precedence newPrecedence = 0;
SyntaxKind opKind = SyntaxKind.None;
// all of these are tokens that start statements and are invalid
// to start a expression with. if we see one, then we must have
......@@ -9061,11 +9060,10 @@ private ExpressionSyntax ParseSubExpressionCore(Precedence precedence)
return this.AddError(this.CreateMissingIdentifierName(), ErrorCode.ERR_InvalidExprTerm, SyntaxFacts.GetText(tk));
}
// No left operand, so we need to parse one -- possibly preceded by a
// unary operator.
// Parse a left operand -- possibly preceded by a unary operator.
if (IsExpectedPrefixUnaryOperator(tk))
{
opKind = SyntaxFacts.GetPrefixUnaryExpression(tk);
var opKind = SyntaxFacts.GetPrefixUnaryExpression(tk);
newPrecedence = GetPrecedence(opKind);
var opToken = this.EatToken();
var operand = this.ParseSubExpression(newPrecedence);
......@@ -9075,7 +9073,7 @@ private ExpressionSyntax ParseSubExpressionCore(Precedence precedence)
{
// Operator ".." here can either be a prefix unary operator or a stand alone empty range:
var opToken = this.EatToken();
opKind = SyntaxKind.RangeExpression;
var opKind = SyntaxKind.RangeExpression;
newPrecedence = GetPrecedence(opKind);
ExpressionSyntax rightOperand;
......@@ -9092,7 +9090,7 @@ private ExpressionSyntax ParseSubExpressionCore(Precedence precedence)
}
else if (IsAwaitExpression())
{
opKind = SyntaxKind.AwaitExpression;
var opKind = SyntaxKind.AwaitExpression;
newPrecedence = GetPrecedence(opKind);
var awaitToken = this.EatContextualToken(SyntaxKind.AwaitKeyword);
awaitToken = CheckFeatureAvailability(awaitToken, MessageID.IDS_FeatureAsync);
......@@ -9129,12 +9127,18 @@ private ExpressionSyntax ParseSubExpressionCore(Precedence precedence)
leftOperand = this.ParseTerm(precedence);
}
return ParseExpressionContinued(leftOperand, precedence);
}
private ExpressionSyntax ParseExpressionContinued(ExpressionSyntax leftOperand, Precedence precedence)
{
while (true)
{
// We either have a binary or assignment operator here, or we're finished.
tk = this.CurrentToken.ContextualKind;
var tk = this.CurrentToken.ContextualKind;
bool isAssignmentOperator = false;
SyntaxKind opKind = leftOperand.Kind;
if (IsExpectedBinaryOperator(tk))
{
opKind = SyntaxFacts.GetBinaryExpression(tk);
......@@ -9148,12 +9152,16 @@ private ExpressionSyntax ParseSubExpressionCore(Precedence precedence)
{
opKind = SyntaxKind.RangeExpression;
}
else if (tk == SyntaxKind.SwitchKeyword && this.PeekToken(1).Kind == SyntaxKind.OpenBraceToken)
{
opKind = SyntaxKind.SwitchExpression;
}
else
{
break;
}
newPrecedence = GetPrecedence(opKind);
var newPrecedence = GetPrecedence(opKind);
Debug.Assert(newPrecedence > 0); // All binary operators must have precedence > 0!
......@@ -9210,46 +9218,45 @@ private ExpressionSyntax ParseSubExpressionCore(Precedence precedence)
{
leftOperand = ParseIsExpression(leftOperand, opToken);
}
else
else if (isAssignmentOperator)
{
if (isAssignmentOperator)
ExpressionSyntax rhs = opKind == SyntaxKind.SimpleAssignmentExpression && CurrentToken.Kind == SyntaxKind.RefKeyword
? rhs = CheckFeatureAvailability(ParsePossibleRefExpression(), MessageID.IDS_FeatureRefReassignment)
: rhs = this.ParseSubExpression(newPrecedence);
if (opKind == SyntaxKind.CoalesceAssignmentExpression)
{
ExpressionSyntax rhs = opKind == SyntaxKind.SimpleAssignmentExpression && CurrentToken.Kind == SyntaxKind.RefKeyword
? rhs = CheckFeatureAvailability(ParsePossibleRefExpression(), MessageID.IDS_FeatureRefReassignment)
: rhs = this.ParseSubExpression(newPrecedence);
opToken = CheckFeatureAvailability(opToken, MessageID.IDS_FeatureCoalesceAssignmentExpression);
}
if (opKind == SyntaxKind.CoalesceAssignmentExpression)
{
opToken = CheckFeatureAvailability(opToken, MessageID.IDS_FeatureCoalesceAssignmentExpression);
}
leftOperand = _syntaxFactory.AssignmentExpression(opKind, leftOperand, opToken, rhs);
}
else if (opKind == SyntaxKind.SwitchExpression)
{
leftOperand = ParseSwitchExpression(leftOperand, opToken);
}
else if (tk == SyntaxKind.DotDotToken)
{
// Operator ".." here can either be a binary or a postfix unary operator:
Debug.Assert(opKind == SyntaxKind.RangeExpression);
leftOperand = _syntaxFactory.AssignmentExpression(opKind, leftOperand, opToken, rhs);
ExpressionSyntax rightOperand;
if (CanStartExpression())
{
newPrecedence = GetPrecedence(opKind);
rightOperand = this.ParseSubExpression(newPrecedence);
}
else
{
if (tk == SyntaxKind.DotDotToken)
{
// Operator ".." here can either be a binary or a postfix unary operator:
Debug.Assert(opKind == SyntaxKind.RangeExpression);
ExpressionSyntax rightOperand;
if (CanStartExpression())
{
newPrecedence = GetPrecedence(opKind);
rightOperand = this.ParseSubExpression(newPrecedence);
}
else
{
rightOperand = null;
}
leftOperand = _syntaxFactory.RangeExpression(leftOperand, opToken, rightOperand);
}
else
{
leftOperand = _syntaxFactory.BinaryExpression(opKind, leftOperand, opToken, this.ParseSubExpression(newPrecedence));
}
rightOperand = null;
}
leftOperand = _syntaxFactory.RangeExpression(leftOperand, opToken, rightOperand);
}
else
{
Debug.Assert(IsExpectedBinaryOperator(tk));
leftOperand = _syntaxFactory.BinaryExpression(opKind, leftOperand, opToken, this.ParseSubExpression(newPrecedence));
}
}
......@@ -9259,10 +9266,8 @@ private ExpressionSyntax ParseSubExpressionCore(Precedence precedence)
// null-coalescing-expression
// null-coalescing-expression ? expression : expression
//
// Only take the ternary if we're at a precedence less than the null coalescing
// expression.
if (tk == SyntaxKind.QuestionToken && precedence < Precedence.Coalescing)
// Only take the conditional if we're at or below its precedence.
if (CurrentToken.Kind == SyntaxKind.QuestionToken && precedence <= Precedence.Conditional)
{
var questionToken = this.EatToken();
var colonLeft = this.ParsePossibleRefExpression();
......@@ -9285,23 +9290,6 @@ private ExpressionSyntax ParseSubExpressionCore(Precedence precedence)
}
}
// From the proposed language spec:
//
// switch-expression:
// null-coalescing-expression switch ( switch-expression-case-list )
// switch-expression-case-list:
// switch-expression-case
// switch-expression-case , switch-expression-case-list
// switch-expression-case:
// pattern => expression
//
// Only take the switch if we're at a precedence less than the null coalescing expression.
else if (tk == SyntaxKind.SwitchKeyword && precedence < Precedence.Coalescing && this.PeekToken(1).Kind == SyntaxKind.OpenBraceToken)
{
leftOperand = ParseSwitchExpression(leftOperand);
}
return leftOperand;
}
......
......@@ -70,7 +70,7 @@ private CSharpSyntaxNode ParseTypeOrPatternForIsOperatorCore()
if (!type.IsMissing)
{
PatternSyntax p = ParsePatternContinued(type, false);
PatternSyntax p = ParsePatternContinued(type, precedence, whenIsKeyword: false);
if (p != null)
{
return p;
......@@ -102,7 +102,7 @@ private CSharpSyntaxNode ParseTypeOrPatternForIsOperatorCore()
var resetPoint = this.GetResetPoint();
try
{
PatternSyntax p = ParsePatternContinued(null, false);
PatternSyntax p = ParsePatternContinued(type: null, precedence, whenIsKeyword: false);
if (p != null)
{
return p;
......@@ -358,7 +358,7 @@ private CSharpSyntaxNode ParseExpressionOrPattern(bool whenIsKeyword, bool forSw
}
}
PatternSyntax p = ParsePatternContinued(type, whenIsKeyword);
PatternSyntax p = ParsePatternContinued(type, precedence, whenIsKeyword);
if (p != null)
{
return (whenIsKeyword && p is ConstantPatternSyntax c) ? c.expression : (CSharpSyntaxNode)p;
......@@ -408,7 +408,7 @@ private bool CanTokenFollowTypeInPattern()
}
}
private PatternSyntax ParsePatternContinued(TypeSyntax type, bool whenIsKeyword)
private PatternSyntax ParsePatternContinued(TypeSyntax type, Precedence precedence, bool whenIsKeyword)
{
if (type?.Kind == SyntaxKind.IdentifierName)
{
......@@ -450,7 +450,9 @@ private PatternSyntax ParsePatternContinued(TypeSyntax type, bool whenIsKeyword)
// There is an ambiguity between a positional pattern `(` pattern `)`
// and a constant expression pattern that happens to be parenthesized.
// Per 2017-11-20 LDM we treat such syntax as a parenthesized expression always.
return _syntaxFactory.ConstantPattern(_syntaxFactory.ParenthesizedExpression(openParenToken, cp.Expression, closeParenToken));
ExpressionSyntax expression = _syntaxFactory.ParenthesizedExpression(openParenToken, cp.Expression, closeParenToken);
expression = ParseExpressionContinued(expression, precedence);
return _syntaxFactory.ConstantPattern(expression);
}
}
......@@ -615,7 +617,7 @@ private SubpatternSyntax ParseSubpatternElement()
nameColon = _syntaxFactory.NameColon(name, colon);
}
var pattern = ParsePattern(Precedence.Ternary);
var pattern = ParsePattern(Precedence.Conditional);
return this._syntaxFactory.Subpattern(nameColon, pattern);
}
......@@ -642,13 +644,11 @@ private bool IsPossibleSubpatternElement()
expected);
}
private ExpressionSyntax ParseSwitchExpression(ExpressionSyntax leftOperand)
private ExpressionSyntax ParseSwitchExpression(ExpressionSyntax governingExpression, SyntaxToken switchKeyword)
{
// For better error recovery when an expression is typed on a line before a switch statement,
// the caller checks if the switch keyword is followed by an open curly brace. Only if it is
// would we attempt to parse it as a switch expression here.
var governingExpression = leftOperand;
var switchKeyword = this.EatToken();
var openBrace = this.EatToken(SyntaxKind.OpenBraceToken);
var arms = this.ParseSwitchExpressionArms();
var closeBrace = this.EatToken(SyntaxKind.CloseBraceToken);
......@@ -663,9 +663,9 @@ private SeparatedSyntaxList<SwitchExpressionArmSyntax> ParseSwitchExpressionArms
while (this.CurrentToken.Kind != SyntaxKind.CloseBraceToken)
{
// We use a precedence that excludes lambdas, assignments, and a ternary which could have a
// We use a precedence that excludes lambdas, assignments, and a conditional which could have a
// lambda on the right, because we need the parser to leave the EqualsGreaterThanToken
// to be consumed by the switch arm. The strange side-effect of that is that the ternary
// to be consumed by the switch arm. The strange side-effect of that is that the conditional
// expression is not permitted as a constant expression here; it would have to be parenthesized.
var pattern = ParsePattern(Precedence.Coalescing, whenIsKeyword: true);
var whenClause = ParseWhenClause(Precedence.Coalescing);
......
......@@ -8889,8 +8889,8 @@ Pokud chcete odstranit toto varování, můžete místo toho použít /reference
<note />
</trans-unit>
<trans-unit id="ERR_MismatchedRefEscapeInTernary">
<source>Branches of a ref ternary operator cannot refer to variables with incompatible declaration scopes</source>
<target state="translated">Větve tříhodnotového operátoru REF nemůžou odkazovat na proměnné s nekompatibilními obory deklarace.</target>
<source>Branches of a ref conditional operator cannot refer to variables with incompatible declaration scopes</source>
<target state="needs-review-translation">Větve tříhodnotového operátoru REF nemůžou odkazovat na proměnné s nekompatibilními obory deklarace.</target>
<note />
</trans-unit>
<trans-unit id="ERR_EscapeStackAlloc">
......
......@@ -8889,8 +8889,8 @@ Um die Warnung zu beheben, können Sie stattdessen /reference verwenden (Einbett
<note />
</trans-unit>
<trans-unit id="ERR_MismatchedRefEscapeInTernary">
<source>Branches of a ref ternary operator cannot refer to variables with incompatible declaration scopes</source>
<target state="translated">Branches eines ternären ref-Operators können nicht auf Variablen mit inkompatiblen Deklarationsbereichen verweisen.</target>
<source>Branches of a ref conditional operator cannot refer to variables with incompatible declaration scopes</source>
<target state="needs-review-translation">Branches eines ternären ref-Operators können nicht auf Variablen mit inkompatiblen Deklarationsbereichen verweisen.</target>
<note />
</trans-unit>
<trans-unit id="ERR_EscapeStackAlloc">
......
......@@ -8889,8 +8889,8 @@ Para eliminar la advertencia puede usar /reference (establezca la propiedad Embe
<note />
</trans-unit>
<trans-unit id="ERR_MismatchedRefEscapeInTernary">
<source>Branches of a ref ternary operator cannot refer to variables with incompatible declaration scopes</source>
<target state="translated">Las ramas de un operador ternario ref no pueden hacer referencia a variables con ámbitos de declaración incompatibles.</target>
<source>Branches of a ref conditional operator cannot refer to variables with incompatible declaration scopes</source>
<target state="needs-review-translation">Las ramas de un operador ternario ref no pueden hacer referencia a variables con ámbitos de declaración incompatibles.</target>
<note />
</trans-unit>
<trans-unit id="ERR_EscapeStackAlloc">
......
......@@ -8889,8 +8889,8 @@ Pour supprimer l'avertissement, vous pouvez utiliser la commande /reference (dé
<note />
</trans-unit>
<trans-unit id="ERR_MismatchedRefEscapeInTernary">
<source>Branches of a ref ternary operator cannot refer to variables with incompatible declaration scopes</source>
<target state="translated">Les branches d'un opérateur ternaire ref ne peuvent pas faire référence à des variables ayant des portées de déclaration incompatibles</target>
<source>Branches of a ref conditional operator cannot refer to variables with incompatible declaration scopes</source>
<target state="needs-review-translation">Les branches d'un opérateur ternaire ref ne peuvent pas faire référence à des variables ayant des portées de déclaration incompatibles</target>
<note />
</trans-unit>
<trans-unit id="ERR_EscapeStackAlloc">
......
......@@ -8889,8 +8889,8 @@ Per rimuovere l'avviso, è invece possibile usare /reference (impostare la propr
<note />
</trans-unit>
<trans-unit id="ERR_MismatchedRefEscapeInTernary">
<source>Branches of a ref ternary operator cannot refer to variables with incompatible declaration scopes</source>
<target state="translated">I rami di un operatore ternario ref non possono fare riferimento a variabili con ambiti di dichiarazione incompatibili</target>
<source>Branches of a ref conditional operator cannot refer to variables with incompatible declaration scopes</source>
<target state="needs-review-translation">I rami di un operatore ternario ref non possono fare riferimento a variabili con ambiti di dichiarazione incompatibili</target>
<note />
</trans-unit>
<trans-unit id="ERR_EscapeStackAlloc">
......
......@@ -8889,8 +8889,8 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<note />
</trans-unit>
<trans-unit id="ERR_MismatchedRefEscapeInTernary">
<source>Branches of a ref ternary operator cannot refer to variables with incompatible declaration scopes</source>
<target state="translated">ref 三項演算子のブランチから、互換性のない宣言スコープを持つ変数を参照することはできません</target>
<source>Branches of a ref conditional operator cannot refer to variables with incompatible declaration scopes</source>
<target state="needs-review-translation">ref 三項演算子のブランチから、互換性のない宣言スコープを持つ変数を参照することはできません</target>
<note />
</trans-unit>
<trans-unit id="ERR_EscapeStackAlloc">
......
......@@ -8889,8 +8889,8 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<note />
</trans-unit>
<trans-unit id="ERR_MismatchedRefEscapeInTernary">
<source>Branches of a ref ternary operator cannot refer to variables with incompatible declaration scopes</source>
<target state="translated">참조 3항 연산자의 분기는 호환되지 않는 선언 범위의 변수를 참조할 수 없습니다.</target>
<source>Branches of a ref conditional operator cannot refer to variables with incompatible declaration scopes</source>
<target state="needs-review-translation">참조 3항 연산자의 분기는 호환되지 않는 선언 범위의 변수를 참조할 수 없습니다.</target>
<note />
</trans-unit>
<trans-unit id="ERR_EscapeStackAlloc">
......
......@@ -8889,8 +8889,8 @@ Aby usunąć ostrzeżenie, możesz zamiast tego użyć opcji /reference (ustaw w
<note />
</trans-unit>
<trans-unit id="ERR_MismatchedRefEscapeInTernary">
<source>Branches of a ref ternary operator cannot refer to variables with incompatible declaration scopes</source>
<target state="translated">Gałęzie trzyelementowego operatora ref nie mogą odwoływać się do zmiennych z niezgodnymi zakresami deklaracji</target>
<source>Branches of a ref conditional operator cannot refer to variables with incompatible declaration scopes</source>
<target state="needs-review-translation">Gałęzie trzyelementowego operatora ref nie mogą odwoływać się do zmiennych z niezgodnymi zakresami deklaracji</target>
<note />
</trans-unit>
<trans-unit id="ERR_EscapeStackAlloc">
......
......@@ -8889,8 +8889,8 @@ Para incorporar informações de tipo de interoperabilidade para os dois assembl
<note />
</trans-unit>
<trans-unit id="ERR_MismatchedRefEscapeInTernary">
<source>Branches of a ref ternary operator cannot refer to variables with incompatible declaration scopes</source>
<target state="translated">Branches de um operador ternário de referência não podem se referir a variáveis com escopos de declaração incompatível</target>
<source>Branches of a ref conditional operator cannot refer to variables with incompatible declaration scopes</source>
<target state="needs-review-translation">Branches de um operador ternário de referência não podem se referir a variáveis com escopos de declaração incompatível</target>
<note />
</trans-unit>
<trans-unit id="ERR_EscapeStackAlloc">
......
......@@ -8889,8 +8889,8 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<note />
</trans-unit>
<trans-unit id="ERR_MismatchedRefEscapeInTernary">
<source>Branches of a ref ternary operator cannot refer to variables with incompatible declaration scopes</source>
<target state="translated">Ветви ссылочного тернарного оператора не могут ссылаться на переменные с несовместимыми областями объявления.</target>
<source>Branches of a ref conditional operator cannot refer to variables with incompatible declaration scopes</source>
<target state="needs-review-translation">Ветви ссылочного тернарного оператора не могут ссылаться на переменные с несовместимыми областями объявления.</target>
<note />
</trans-unit>
<trans-unit id="ERR_EscapeStackAlloc">
......
......@@ -8889,8 +8889,8 @@ Uyarıyı kaldırmak için, /reference kullanabilirsiniz (Birlikte Çalışma T
<note />
</trans-unit>
<trans-unit id="ERR_MismatchedRefEscapeInTernary">
<source>Branches of a ref ternary operator cannot refer to variables with incompatible declaration scopes</source>
<target state="translated">Başvuru üçlü operatörünün dalları, bildirim kapsamı uyumsuz olan değişkenlere başvuruda bulunamaz</target>
<source>Branches of a ref conditional operator cannot refer to variables with incompatible declaration scopes</source>
<target state="needs-review-translation">Başvuru üçlü operatörünün dalları, bildirim kapsamı uyumsuz olan değişkenlere başvuruda bulunamaz</target>
<note />
</trans-unit>
<trans-unit id="ERR_EscapeStackAlloc">
......
......@@ -8889,8 +8889,8 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<note />
</trans-unit>
<trans-unit id="ERR_MismatchedRefEscapeInTernary">
<source>Branches of a ref ternary operator cannot refer to variables with incompatible declaration scopes</source>
<target state="translated">ref 三元运算符的分支不能引用具有不兼容的声明范围的变量</target>
<source>Branches of a ref conditional operator cannot refer to variables with incompatible declaration scopes</source>
<target state="needs-review-translation">ref 三元运算符的分支不能引用具有不兼容的声明范围的变量</target>
<note />
</trans-unit>
<trans-unit id="ERR_EscapeStackAlloc">
......
......@@ -8889,8 +8889,8 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<note />
</trans-unit>
<trans-unit id="ERR_MismatchedRefEscapeInTernary">
<source>Branches of a ref ternary operator cannot refer to variables with incompatible declaration scopes</source>
<target state="translated">ref 三元運算子分支無法參考具有不相容宣告範圍的變數</target>
<source>Branches of a ref conditional operator cannot refer to variables with incompatible declaration scopes</source>
<target state="needs-review-translation">ref 三元運算子分支無法參考具有不相容宣告範圍的變數</target>
<note />
</trans-unit>
<trans-unit id="ERR_EscapeStackAlloc">
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册