Skip to content

🍒[5.7] Remove the need for convenience keyword for delegating actor initializers #59741

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 7 commits into from
Jul 1, 2022

Conversation

kavon
Copy link
Member

@kavon kavon commented Jun 28, 2022

Cherry-pick of #41083 and #59828

This is part of SE-327 and includes new warnings for the convenience keyword appearing and has a fix-it to delete it. Those warnings turn into an error in Swift 6.

Description: As part of SE-327, the convenience keyword is no longer required for delegating actor initializers (the presence of it becomes an error in Swift 6). This means the initializers work similarly to structs, e.g., a non-delegating init can now appear in the extension of an actor.
Risk: Medium. This PR introduces an ABI break for any libraries that had a public actor init. Specifically, if the library was compiled with Swift 5.6 or 5.5, any program compiled with optimizations enabled and linked against that library will be dependent on the initializer's delegating status remaining fixed. For example, if the library authors change the implementation to no-longer delegate, the Swift <5.7 program will need to be recompiled, or else there will be a missing symbol error. For Swift 5.7+ we now specifically guarantee that changing the implementation of the init to delegate or not won't break existing programs.
Importance: High. The longer we wait to make this ABI break, the worse it will become.
Review by: Doug Gregor
Testing: PR testing
Original PR: #41083 #59828
Radar: rdar://87567878

@kavon kavon requested a review from a team as a code owner June 28, 2022 02:36
@kavon
Copy link
Member Author

kavon commented Jun 28, 2022

@swift-ci please test

@kavon kavon force-pushed the 5.7-inconvenienced-actors branch from 6bf051a to 6b9c9ba Compare June 30, 2022 05:43
@kavon
Copy link
Member Author

kavon commented Jun 30, 2022

@swift-ci please test

@kavon kavon force-pushed the 5.7-inconvenienced-actors branch from 6b9c9ba to 2cbc0c8 Compare June 30, 2022 17:36
@kavon
Copy link
Member Author

kavon commented Jun 30, 2022

@swift-ci please test

@kavon kavon changed the title [5.7] Remove the need for convenience keyword for delegating actor initializers 🍒[5.7] Remove the need for convenience keyword for delegating actor initializers Jun 30, 2022
Copy link
Member

@DougGregor DougGregor left a comment

Choose a reason for hiding this comment

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

I want us to explore the ABI issue in more detail before we commit to this.

@kavon kavon marked this pull request as draft June 30, 2022 22:35
@kavon kavon marked this pull request as ready for review June 30, 2022 23:04
@kavon
Copy link
Member Author

kavon commented Jun 30, 2022

@swift-ci please test and merge

kavon added 7 commits June 30, 2022 18:08
This is possible because actors do not support inheritance. There
is one specific exception to that rule, which is that an actor
can inherit from `NSObject` just to support ObjC interop.

This means an actor is effectively a final class.

resolves rdar://87568153
When synthesizing the default initializer for an actor, we'd sometimes hit
a cycle when that initializer needs to chain to NSObject.init. The cycle
only happens because we ask if the initializer we're trying to synthesize
is a convenience init in a scenario which only applies to non-final classes.

Since all actors are effectively "final" classes, it's valid to workaround the
cycle by only asking that initializer question for non-final classes, thus
breaking the cycle.
it should not matter whether an initializer is delegating or not when
importing a library. this test helps make sure that stays true.
A public designated initializer of a class would have its allocating
entry-point serialized in the module, meaning with `-O` that entry-point
can get inlined into programs linking against that module. Once that
entry-point is inlined, the program will _require_ that it remain non-delegating,
because it will depend on the 2nd entry-point (for actual initializing) to be in the
library.

As a result of this change, public initializers of an actor should be resilient in a library,
whether their underlying implementation is delegating or not.
When I began removing `convenience` from actor inits, I thought it would
be ok for an actor's extensions to be non-delegating. But that's wrong,
because the actor could be in a resilient module and still have its
properties change between stored and computed, meaning that there isn't
a practical way to allow this, unless if the extension and the actor
are in the same file.

For now, just re-ban this behavior before anybody notices :)
@kavon kavon force-pushed the 5.7-inconvenienced-actors branch from 9109bdc to 4dac108 Compare July 1, 2022 01:08
@kavon
Copy link
Member Author

kavon commented Jul 1, 2022

@swift-ci please test and merge

forgot to add a REQUIRES: objc_interop

@kavon
Copy link
Member Author

kavon commented Jul 1, 2022

@swift-ci please test

@kavon kavon merged commit fc4f64c into swiftlang:release/5.7 Jul 1, 2022
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.

2 participants