-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Relaxed escape rules for spans #22203
Conversation
@dotnet/roslyn-compiler - please review. |
37f38a6
to
65c4648
Compare
var consValid = CheckValEscape(conditional.Consequence.Syntax, conditional.Consequence, escapeFrom, escapeTo, checkingReceiver: false, diagnostics: diagnostics); | ||
|
||
if (consValid || conditional.IsByRef) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I get that. Why don't we check the alternative if the consequence is valid? #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -662,10 +662,7 @@ static void Main() | |||
comp.VerifyEmitDiagnostics( | |||
// (15,27): error CS8168: Cannot return local 'local1' by reference because it is not a ref local |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because it is not a ref local [](start = 84, length = 29)
because it is? #WontFix
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
local1 is not a ref local so we cannot return it by reference. When we need to ref return a ternary, we recursively check operands and produce at least one error.
The quality of cascaded error may be improved, but this is how it work right now.
In reply to: 139840517 [](ancestors = 139840517)
@@ -45,23 +47,25 @@ static S1 MayWrap(ref int arg) | |||
} | |||
} | |||
"; | |||
CreateStandardCompilation(text).VerifyDiagnostics( | |||
// (21,42): error CS8168: Cannot return local 'local' by reference because it is not a ref local | |||
CreateCompilationWithMscorlibAndSpan(text).VerifyDiagnostics( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CreateCompilationWithMscorlibAndSpan [](start = 12, length = 36)
That reminds me, how are we tracking the addition of Span to the libraries we reference in testing? so that we can remove this helper function #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not even sure we have to change this. Span implementations are platform-specific and we only care about the APIs that exposed. As long as we call right methods, we are producing right code.
I will enter a bug to add some tests with actual span (I think we can use slow-span, since that should be able to run on any platform), but that is not a priority.
In reply to: 139844972 [](ancestors = 139844972)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4c73d49
to
7b33a48
Compare
@dotnet/roslyn-compiler - any more comments on this? |
uint scopeOfTheContainingExpression) | ||
uint scopeOfTheContainingExpression, | ||
bool isRefEscape | ||
) | ||
{ | ||
// SPEC: (also applies to the CheckInvocationEscape counterpart) | ||
// | ||
// An lvalue resulting from a ref-returning method invocation e1.M(e2, ...) is ref-safe - to - escape the smallest of the following scopes: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
smallest [](start = 129, length = 8)
Nit: "smallest" is ambiguous. Consider using "narrowest" here and a couple of lines below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is the terminology from the spec proposal. I think we should fix it there.
Here it is less important, since it is just a comment. Will fix when the spec is updated. (hopefully there will be no changes to rules too :-)
if (conditional.IsByRef) | ||
{ | ||
return GetRefEscape(conditional.Consequence, scopeOfTheContainingExpression); | ||
// ref conditional defers to its operands | ||
return Math.Max(GetRefEscape(conditional.Consequence, scopeOfTheContainingExpression), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we sure we want to relax the ref-safe-to-escape for ternary? Might that cause problems once we allow ref re-assignment (ie. the ternary could be used on the left)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It cannot be on the left of ref assignment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would ned to be a ref to a ref.
@@ -2105,7 +2123,8 @@ internal static bool CheckValEscape(SyntaxNode node, BoundExpression expr, uint | |||
checkingReceiver, | |||
escapeFrom, | |||
escapeTo, | |||
diagnostics); | |||
diagnostics, | |||
isRefEscape: false); | |||
|
|||
case BoundKind.ObjectCreationExpression: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It just occurred to me, are we covering tuples?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tuples cannot contain ref-structs since they are themselves not ref structs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Also fixes #22197 (mixing rules for ternary ref)
NOTE: many tests that were tracking scope-escapes would be meaningless now since. We cannot observe the difference since spans cannot become attached to a particular scope by capturing a local ref.
I tried to salvage tests by using global/stackalloc scopes instead - to make sure we are not losing coverage by accident.
However, since that has only 2 levels of escape (not N) as before, there can be some overlap in tests now. I do not think extra testing that might result from this is a concern though.