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

Don't check safe-to-escape of receiver arguments to readonly members #35597

Merged

Conversation

RikkiGibson
Copy link
Contributor

Fixes #35146 but we'll need to create a new issue to track fixing escape analysis on properties where one accessor is readonly and the other is not.

@RikkiGibson RikkiGibson requested a review from a team as a code owner May 9, 2019 00:38
@RikkiGibson RikkiGibson added this to the 16.2.P2 milestone May 9, 2019
@RikkiGibson
Copy link
Contributor Author

These tests are a bit messed up--bad names and copy/pastes. I'll fix them up.

var isReadOnlyInvocation = symbol switch
{
MethodSymbol m => m.IsEffectivelyReadOnly,
// TODO: val escape checks should be skipped for property accesses when
Copy link
Member

Choose a reason for hiding this comment

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

This is the case you were telling me about, where we can't easily determine which accessor we are using?

So an indexer that takes a Span<T> (for multi-dimensional indexing) won't work with this change and will need to be handled in the future, correct (just talking about the getter, since the setter needs to be mutable in this case)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah if it looks like this[Span<T> span] { readonly get; set; } we will be pessimistic and say the span could escape illegally even though we should be able to tell that only the getter is called.

comp.VerifyDiagnostics(
// (11,15): error CS8352: Cannot use local 'x' in this context because it may expose referenced variables outside of their declaration scope
// b.P = x;
Diagnostic(ErrorCode.ERR_EscapeLocal, "x").WithArguments("x").WithLocation(11, 15));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The purpose of this test is more to explicitly illustrate the existing behavior. Strictly speaking we might be able to exclude such properties from escape analysis but it doesn't seem to present much value.

@gafter
Copy link
Member

gafter commented May 9, 2019

Is there a proposed update to a specification? Or is this something already specified? Is there something over on csharplang that is a reference for this change?

@tannergooding
Copy link
Member

This is functionality that already works for methods of readonly struct. It does not currently work for readonly members of a mutable struct, so I logged #35146

@gafter
Copy link
Member

gafter commented May 9, 2019

Where would I find a spec for the behavior implemented here? Or the related functionality for readonly struct for that matter?

@tannergooding
Copy link
Member

I would expect it to be in either https://github.com/dotnet/csharplang/blob/master/proposals/csharp-7.2/span-safety.md or https://github.com/dotnet/csharplang/blob/master/proposals/csharp-7.2/readonly-ref.md, if anywhere.

However, I did not immediately see a section detailing a ref struct passed to an instance method of another ref struct and how the escaping rules apply if that instance method is itself considered readonly (which in 7.2 would have only applied to readonly ref struct, but in 8.0 also applies to readonly members of ref struct).

@gafter
Copy link
Member

gafter commented May 9, 2019

I would prefer a specification for the proposed language change (even if that means also writing spec language for stuff already done, such as readonly structs) to be reviewed before I would feel comfortable reviewing its implementation.

@agocke
Copy link
Member

agocke commented May 9, 2019

I agree with @gafter. This isn't bug-fix level, we need a spec proposal first.

@RikkiGibson
Copy link
Contributor Author

RikkiGibson commented May 9, 2019

It seems like the currently shipped behavior on escape analysis for arguments to readonly struct methods isn't specified in the span-safety or readonly-ref docs. It seems better to put in span-safety.

How about I propose a change to the span safety spec as the next step? Please let me know if there's anything I should look at to onboard to that or if there's some other way this should get done.

@RikkiGibson
Copy link
Contributor Author

After some closer study of the span safety spec I've identified the following relevant clauses in the Language Constraints section.

In a method invocation, the following constraints apply:

  • If there is a ref or out argument of a ref struct type (including the receiver), with safe-to-escape E1, then
  • no argument (including the receiver) may have a narrower safe-to-escape than E1.

It seems like these constraints are what's checked by CheckInvocationArgMixing. The spec language excludes ref readonly/in arguments. Since the receiver argument is passed by ref readonly to a readonly method or accessor, there's no need to check its safe-to-escape and this PR brings us closer to adherence to the spec.

I'm going to update the implementation to quote the spec and ask you to take another look.

@RikkiGibson RikkiGibson changed the title Relax escape analysis rules for readonly methods Don't check safe-to-escape of receiver arguments to readonly members May 14, 2019
@RikkiGibson RikkiGibson requested a review from a team May 14, 2019 21:24
Copy link
Member

@gafter gafter left a comment

Choose a reason for hiding this comment

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

:shipit:

@RikkiGibson RikkiGibson requested a review from a team May 17, 2019 20:08
@333fred
Copy link
Member

333fred commented May 20, 2019

Talked with @RikkiGibson offline. We think there might be a forward compat scenario where you can call one of these members from a C# 7 assembly in VS 2019, but not in 2017, so he's going to add more tests to verify behavior and adjust as necessary.

@333fred
Copy link
Member

333fred commented May 20, 2019

Done review pass (commit 5)

@RikkiGibson
Copy link
Contributor Author

We decided that this is an uncommon enough scenario that we're comfortable asking people to simply update their compiler version to make it work.

@RikkiGibson RikkiGibson merged commit 5f4c7ab into dotnet:master May 21, 2019
@RikkiGibson RikkiGibson deleted the readonly-members-span-parameters branch May 21, 2019 22:31
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.

Compiler doesn't take readonly members into account for span safety rules
6 participants