Skip to content

prevent nonisolated mutation of isolated properties through an existential #59655

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

Merged
merged 1 commit into from
Jun 23, 2022

Conversation

kavon
Copy link
Member

@kavon kavon commented Jun 22, 2022

The underlying problem was that the ActorIsolationChecker was not properly
recording the mutation environment in which a lookup through an existential was
happening. That's because the AST looks like this:

(inout_expr ...
  (open_existential_expr ...
    (opaque_value_expr ...
     (declref_expr ...
     (member_ref_expr ...
       (opaque_value_expr ...

and the walker creates a link from the open_existential_expr to the inout_expr,
but that kind of expression is not checked for its usage environment. Instead, we
need to look through that OpenExistentialExpr recursively so that a link from
its sub-expression, the member_ref_expr, to the inout_expr is formed instead.

The side-effect of that missing link causing the bug is that the usageEnv of
that member_ref_expr appears to be empty when we don't have the link. A missing
link is assumed to mean that it's not in a mutating environment, and thus the
usage is treated as a read.

This is why in #59573 / rdar://95509917 we are seeing the compiler report that an
await is needed around the assignment expr. The checker thinks it's a read, but
it's actually a mutation, because the member ref is happening in an inout expr.

Resolves rdar://95509917
Resolves #59573

This PR supersedes #59580

…ntial

The underlying problem was that the ActorIsolationChecker was not properly
recording the mutation environment in which a lookup through an existential was
happening. That's because the AST looks like this:

```
(inout_expr ...
  (open_existential_expr ...
    (opaque_value_expr ...
     (declref_expr ...
     (member_ref_expr ...
       (opaque_value_expr ...
```

and the walker creates a link from the `open_existential_expr` to the `inout_expr`,
but that kind of expression is not checked for its usage environment. Instead, we
need to look through that OpenExistentialExpr recursively so that a link from
its sub-expression, the `member_ref_expr`, to the `inout_expr` is formed instead.

The side-effect of that missing link causing the bug is that the `usageEnv` of
that `member_ref_expr` appears to be empty when we don't have the link. A missing
link is assumed to mean that it's not in a mutating environment, and thus the
usage is treated as a read.

This is why in swiftlang#59573 / rdar://95509917 we are seeing the compiler report that an
`await` is needed around the assignment expr. The checker thinks it's a read, but
it's actually a mutation, because the member ref is happening in an `inout` expr.

Resolves rdar://95509917
Resolves swiftlang#59573
@kavon
Copy link
Member Author

kavon commented Jun 22, 2022

@swift-ci please test

Copy link
Contributor

@ktoso ktoso left a comment

Choose a reason for hiding this comment

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

Awesome, this patch is much nicer than my attempt at it -- thank you! :-)

@kavon
Copy link
Member Author

kavon commented Jun 23, 2022

hm, seems the macOS failure is unrelated.

@swift-ci please smoke test and merge

@swift-ci swift-ci merged commit 05dcba1 into swiftlang:main Jun 23, 2022
@DougGregor
Copy link
Member

This looks great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

It's possible to set an isolated property asynchronously
4 participants