Skip to content
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

Merged
merged 4 commits into from
Sep 20, 2017

Conversation

VSadov
Copy link
Member

@VSadov VSadov commented Sep 19, 2017

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.

@VSadov
Copy link
Member Author

VSadov commented Sep 19, 2017

@dotnet/roslyn-compiler - please review.

var consValid = CheckValEscape(conditional.Consequence.Syntax, conditional.Consequence, escapeFrom, escapeTo, checkingReceiver: false, diagnostics: diagnostics);

if (consValid || conditional.IsByRef)
{
Copy link
Contributor

@OmarTawfik OmarTawfik Sep 19, 2017

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

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be !consValid. And I need test, I guess.


In reply to: 139840188 [](ancestors = 139840188)

@@ -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
Copy link
Contributor

@OmarTawfik OmarTawfik Sep 19, 2017

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

Copy link
Member Author

@VSadov VSadov Sep 19, 2017

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(
Copy link
Contributor

@OmarTawfik OmarTawfik Sep 19, 2017

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

Copy link
Member Author

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)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#22213


In reply to: 139847810 [](ancestors = 139847810,139844972)

@VSadov
Copy link
Member Author

VSadov commented Sep 20, 2017

@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:
Copy link
Member

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.

Copy link
Member Author

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),
Copy link
Member

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)?

Copy link
Member Author

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.

Copy link
Member Author

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:
Copy link
Member

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?

Copy link
Member Author

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

Copy link
Member

@jcouv jcouv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@VSadov VSadov merged commit 698b9e0 into dotnet:features/readonly-ref Sep 20, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants