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

Make top-level code variables @MainActor @preconcurrency #40998

Merged
merged 6 commits into from
Jan 28, 2022

Conversation

etcwilde
Copy link
Contributor

@etcwilde etcwilde commented Jan 25, 2022

This patch gets the semantics roughly where we want them. The top-level code context is set to run on the main actor and the top-level variables are @MainActor @preconcurrency. This pairing reduces the number of hops between actors for top-level code, provides some level of safety, and keeps the code breakage fairly minimal.

The next PR contains await detection to turn the top-level code into an async context once the first use of await is used in the top-level. If no awaits are used, the top-level should behave exactly the same as it does today to keep current scripts working.

@etcwilde etcwilde added the concurrency Feature: umbrella label for concurrency language features label Jan 25, 2022
@etcwilde etcwilde changed the title Waiting on https://github.com/apple/swift/pull/40963/: Make top-level code variables @MainActor @_predatesConcurrency Waiting on PR#40963: Make top-level code variables @MainActor @_predatesConcurrency Jan 25, 2022
lib/AST/Decl.cpp Outdated
// Variables declared in top-level code are @_predatesConcurrency
if (const VarDecl *var = dyn_cast<VarDecl>(this)) {
return getASTContext().LangOpts.EnableExperimentalAsyncTopLevel &&
var->isTopLevelGlobal();
Copy link
Member

Choose a reason for hiding this comment

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

Should we also check for Swift version < 6 here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that should get picked up by contextRequiresStrictConcurrencyChecking, which is used by adjustVarTypeForConcurrecy to strip off the actor from the type.
I'll throw it in just to ensure that nothing leaks past though.

@etcwilde etcwilde changed the title Waiting on PR#40963: Make top-level code variables @MainActor @_predatesConcurrency Make top-level code variables @MainActor @_predatesConcurrency Jan 25, 2022
@etcwilde etcwilde force-pushed the ewilde/mainactor-top-level-vars branch from 06eac77 to e6c437f Compare January 26, 2022 18:53
@etcwilde
Copy link
Contributor Author

@swift-ci please test

@etcwilde etcwilde marked this pull request as ready for review January 26, 2022 18:59
@etcwilde
Copy link
Contributor Author

@swift-ci please test

@etcwilde
Copy link
Contributor Author

@swift-ci please test

@@ -4741,7 +4741,9 @@ ERROR(global_actor_non_unsafe_init,none,
"global actor attribute %0 argument can only be '(unsafe)'", (Type))
ERROR(global_actor_non_final_class,none,
"non-final class %0 cannot be a global actor", (DeclName))

ERROR(global_actor_top_level_var,none,
"top-level code variables cannot have a global actor", ())
Copy link
Contributor

Choose a reason for hiding this comment

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

add a test to cover this? there doesn't seem to be one

Copy link
Contributor Author

Choose a reason for hiding this comment

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

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.

Looks good to me, perhaps add one test to cover the error this also added

@etcwilde
Copy link
Contributor Author

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 8a8bd57316958bffd3f6894e312d4b8caf9574fd

@etcwilde
Copy link
Contributor Author

It looks like all of the API's have changed... D:
Missing predatesConcurrency and swift::ActorIsolation::forGlobalActor!? Interesting.

@stevapple
Copy link
Contributor

predatesConcurrency has been changed into preconcurrency in #40680

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 8a8bd57316958bffd3f6894e312d4b8caf9574fd

@etcwilde etcwilde force-pushed the ewilde/mainactor-top-level-vars branch from 8a8bd57 to 294b0d0 Compare January 28, 2022 06:06
This patch sets the actor isolation of the top-level code contexts to be
on the main actor. This holds since the implicit `async_Main` function
generated is executed on the main actor executor.
This is an interesting patch that may raise some eyebrows. The machinery
we have now can completely handle arbitrary global-actor isolation on
the global variables. I'm forcing the variables to be on the main actor
because in an ideal future, the variables won't be global and will
actually be local to the implicit `async_Main` function, where they will
be isolated to the main actor by virtue of the `async_Main` function
being run by the main actor executor. For that to work, we can't really
allow top-level variables to have global actor isolation since local
variables can't have global actor isolation. So while there is no
technical reason we can't handle it now, to avoid source-breaking
changes in the future, I'm removing the ability to explicitly declare a
global actor on top-level global variables and forcing them all to be on
the MainActor implicitly.
Top-level global variables should have the `@predatesConcurrency
@MainActor` behaviour. This allows them to be somewhat concurrency safe
while still working with old code.
Since we're forcing all of the variables at the top-level to be main
actor isolated, there were some changes to where actor-hops were are to
happen. Additionally, I had to pull of the actor isolation on `a` since
we don't allow explicit global actor isolation. Given this, it doesn't
really make sense to keep `b` around. As a nice change though, we can
call synchronous functions directly in top level code, passing variables
directly.
Ensure that the predates concurrency behavior is only applied for Swift
5 and not for Swift 6.
Adding a test to ensure that we emit an error message if there are
global actors on top-level variables.
@etcwilde etcwilde force-pushed the ewilde/mainactor-top-level-vars branch from 294b0d0 to 8d509ad Compare January 28, 2022 07:08
@etcwilde
Copy link
Contributor Author

@swift-ci please test

@etcwilde etcwilde changed the title Make top-level code variables @MainActor @_predatesConcurrency Make top-level code variables @MainActor @preconcurrency Jan 28, 2022
@etcwilde etcwilde merged commit d265ec9 into swiftlang:main Jan 28, 2022
@etcwilde etcwilde deleted the ewilde/mainactor-top-level-vars branch January 28, 2022 15:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
concurrency Feature: umbrella label for concurrency language features
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants