Skip to content

Enable building with strict concurrency checking enabled #8084

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 5 commits into from
Jan 13, 2023
Merged

Conversation

tgoyne
Copy link
Member

@tgoyne tgoyne commented Dec 28, 2022

This drops Xcode 13.1 and 13.2 support because @preconcurrency was added in Swift 5.6 and guarding it with #if swift would have required a large amount of duplication. 13.2 is over a year old, so it's about time to drop it anyway.

Everything except for the Realm Swift tests are now built with complete strict concurrency checks. The RS tests are built with targeted due to them otherwise hitting a very large number of warnings related to various Apple frameworks not yet being updated for Sendable checking yet. Hopefully Xcode 15 will finish annotating the SDKs.

XCTestCase.wait(for:) is @MainActor, so all the tests which wait for expectations need to be as well. I ended up just marking SwiftSyncTestCase as @MainActor as a result. Xcode 13 has a bug where overridden setUp and tearDown methods don't inherit this, so they need to be explicitly marked as @MainActor as well.

I introduced a @Locked property wrapper for the tests which guards access to a value with a lock. This is required for all the tests where we declare a variable, set it in a Sendable closure, and then check it afterwards. Unfortunately, sendability checking for property wrappers is currently buggy (swiftlang/swift#61358), so silly things are required to avoid warnings from this.

A pile of test things have been hoisted out of their containing scope to avoid having to pointlessly capture self when self isn't actually used in the function and isn't Sendable.

I rewrote the watch tests to use expectations rather than semaphores. This both fixed a pile of warnings and made them work a bit better.

There turned out to be a whole bunch more obj-c things which needed to be marked as Sendable. I also marked the sendable types which already couldn't be reasonably subclassed as final as subclassing is complicated for sendability.

Migration is now a typealias for RLMMigration rather than a wrapper. This has no effect on the user-visible API but it eliminates some complications around translating the migration blocks between the obj-c and swift versions (and it really didn't work correctly before).

RLMMigrationRealm was just long-obsolete; object store has taken care of what it was doing for years.

RLMSyncManager wasn't actually particularly thread-safe. It has some properties which had to be set before the first synchronized Realm is opened so in practice it'd work out as ensuring you set the properties in time would sort of inherently involve doing something single-threaded, but it wasn't properly Sendable. All of the properties are now atomic instead. In the process I noticed that the appID property is long obsolete and doesn't make sense any more.

Future's callback currently isn't Sendable. I am fairly confident that's a bug as that's the entire point of a Future, so I'm unsafeBitCasting it to Sendable. Similarly, DynamicProperty.update() currently isn't marked as @MainActor but I don't see how it could possibly work otherwise, so that uses an unsafe cast as well.

BoundCollection.remove() turned out to have a bug: it looked up an index, started a write transaction, then deleted the object at the index. This could possibly delete the wrong object if a write modifying the collection happened on a background thread.

MongoClient had some pointless overloads which could simply be default function arguments instead.

@cla-bot cla-bot bot added the cla: yes label Dec 28, 2022
@tgoyne tgoyne force-pushed the tg/sendable branch 3 times, most recently from aa89752 to 84fd2d8 Compare December 29, 2022 20:44
@tgoyne tgoyne marked this pull request as ready for review December 29, 2022 21:45
@@ -30,7 +30,7 @@ RLM_HEADER_AUDIT_BEGIN(nullability, sendability)

Schemas map to collections of tables in the core database.
*/
RLM_SWIFT_SENDABLE
RLM_SWIFT_SENDABLE // not actually immutable, but the public API kinda is
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it dangerous in any way having the schema classes partially mutable given the above comment?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, but it's not a new problem. This is a place where Sendable annotations are pointing out that we're doing something which requires care. All of the mutation needs to happen before we expose the objects as part of the shared schema, and there's nothing which will warn us if we get that wrong.

// (and is in practice) but isn't marked @MainActor.
func unsafeInvokeAsMainActor(_ fn: @MainActor () -> Void) {
assert(Thread.isMainThread)
withoutActuallyEscaping(fn) { fn in
Copy link
Contributor

Choose a reason for hiding this comment

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

pretty neat

Copy link
Contributor

@leemaguire leemaguire left a comment

Choose a reason for hiding this comment

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

LGTM overall, few minor comments

@tgoyne tgoyne merged commit d63923f into master Jan 13, 2023
@tgoyne tgoyne deleted the tg/sendable branch January 13, 2023 23:21
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 14, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants