未验证 提交 4565d828 编写于 作者: C Chris Sienkiewicz 提交者: GitHub

Implement ValEscape rules for ?? operator (#29985)

* Implement ValEscape rules for ?? operator:
- Implement GetValEscape/CheckValEscape for the null coalescing operator
- Fixes using a coalescing operator in a return statment causeing an emit failure
- Fixes a valid no escaping coalesce assignment being marked as exposing
- Add tests for cases that were failing before
- Add test for case that should still be invalid
上级 2f98b36c
......@@ -2200,6 +2200,12 @@ internal static uint GetValEscape(BoundExpression expr, uint scopeOfTheContainin
return Math.Max(consEscape,
GetValEscape(conditional.Alternative, scopeOfTheContainingExpression));
case BoundKind.NullCoalescingOperator:
var coalescingOp = (BoundNullCoalescingOperator)expr;
return Math.Max(GetValEscape(coalescingOp.LeftOperand, scopeOfTheContainingExpression),
GetValEscape(coalescingOp.RightOperand, scopeOfTheContainingExpression));
case BoundKind.FieldAccess:
var fieldAccess = (BoundFieldAccess)expr;
var fieldSymbol = fieldAccess.FieldSymbol;
......@@ -2346,7 +2352,6 @@ internal static uint GetValEscape(BoundExpression expr, uint scopeOfTheContainin
case BoundKind.AsOperator:
case BoundKind.AwaitExpression:
case BoundKind.ConditionalAccess:
case BoundKind.NullCoalescingOperator:
case BoundKind.ArrayAccess:
// only possible in error cases (if possible at all)
return scopeOfTheContainingExpression;
......@@ -2503,6 +2508,11 @@ internal static bool CheckValEscape(SyntaxNode node, BoundExpression expr, uint
return CheckValEscape(conditional.Alternative.Syntax, conditional.Alternative, escapeFrom, escapeTo, checkingReceiver: false, diagnostics: diagnostics);
case BoundKind.NullCoalescingOperator:
var coalescingOp = (BoundNullCoalescingOperator)expr;
return CheckValEscape(coalescingOp.LeftOperand.Syntax, coalescingOp.LeftOperand, escapeFrom, escapeTo, checkingReceiver, diagnostics) &&
CheckValEscape(coalescingOp.RightOperand.Syntax, coalescingOp.RightOperand, escapeFrom, escapeTo, checkingReceiver, diagnostics);
case BoundKind.FieldAccess:
var fieldAccess = (BoundFieldAccess)expr;
var fieldSymbol = fieldAccess.FieldSymbol;
......@@ -2673,7 +2683,6 @@ internal static bool CheckValEscape(SyntaxNode node, BoundExpression expr, uint
case BoundKind.AsOperator:
case BoundKind.AwaitExpression:
case BoundKind.ConditionalAccess:
case BoundKind.NullCoalescingOperator:
case BoundKind.ArrayAccess:
// only possible in error cases (if possible at all)
return false;
......
......@@ -3514,5 +3514,56 @@ public void M(ref Test obj)
// this = ref obj;
Diagnostic(ErrorCode.ERR_RefLocalOrParamExpected, "this").WithLocation(8, 9));
}
[Fact]
[WorkItem(29927, "https://github.com/dotnet/roslyn/issues/29927")]
public void CoalesceSpanReturn()
{
CreateCompilationWithMscorlibAndSpan(@"
using System;
class C
{
Span<byte> M()
{
return null ?? new Span<byte>();
}
}", options: TestOptions.ReleaseDll).VerifyDiagnostics();
}
[Fact]
[WorkItem(29927, "https://github.com/dotnet/roslyn/issues/29927")]
public void CoalesceAssignSpanReturn()
{
CreateCompilationWithMscorlibAndSpan(@"
using System;
class C
{
Span<byte> M()
{
var x = null ?? new Span<byte>();
return x;
}
}", options: TestOptions.ReleaseDll).VerifyDiagnostics();
}
[Fact]
[WorkItem(29927, "https://github.com/dotnet/roslyn/issues/29927")]
public void CoalesceRefSpanReturn()
{
CreateCompilationWithMscorlibAndSpan(@"
using System;
class C
{
Span<byte> M()
{
Span<byte> x = stackalloc byte[10];
return null ?? x;
}
}", options: TestOptions.ReleaseDll).VerifyDiagnostics(
// (8,24): error CS8352: Cannot use local 'x' in this context because it may expose referenced variables outside of their declaration scope
// return null ?? x;
Diagnostic(ErrorCode.ERR_EscapeLocal, "x").WithArguments("x").WithLocation(8, 24)
);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册