Skip to content

Commit

Permalink
Build in Swift 6 language mode when supported
Browse files Browse the repository at this point in the history
  • Loading branch information
tgoyne committed Sep 4, 2024
1 parent 7ffcc11 commit a4df969
Show file tree
Hide file tree
Showing 58 changed files with 2,538 additions and 794 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/master-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ on:
- "master"
- "release/**"
env:
XCODE_VERSION: "['15.1', '15.2', '15.3', '15.4']"
XCODE_TEST_VERSIONS: "['15.1', '15.2', '15.3', '15.4']"
XCODE_VERSION: "['15.3', '15.4']"
XCODE_TEST_VERSIONS: "['15.3', '15.4']"
PLATFORM: "['ios', 'osx', 'watchos', 'tvos', 'catalyst', 'visionos']"
BUILD_PLATFORM: "['ios', 'iossimulator', 'osx', 'watchos', 'watchossimulator', 'tvos', 'tvossimulator', 'catalyst', 'visionos', 'visionossimulator']"
DOC_VERSION: '15.4'
Expand Down
22 changes: 20 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,25 @@
x.y.z Release notes (yyyy-MM-dd)
=============================================================

The minimum supported version of Xcode is now 15.3.

### Enhancements
* None.
* Build in Swift 6 language mode when using Xcode 16. Libraries build in Swift
6 mode can be consumed by apps built in Swift 5 mode, so this should not have
any immediate effects beyond eliminating some warnings and ensuring that all
Realm APIs can be used in Swift 6 mode. Some notes about using Realm Swift in
Swift 6:
- `try await Realm(actor: actor)` has been replaced with `try await Realm.open()` to work around (swift bug link). The actor is now automatically inferred.
- `@ThreadSafe` is not usable as a property wrapper on local variables and
function arguments in Swift 6 mode. Sendability checking for property
wrappers never got implemented due to them being quietly deprecated in favor
of macros. It can still be used as a property wrapper for class properties
and as a manual wrapper locally, but note that it does not combine well with
actor-isolated Realms.
- In Swift 6 mode a few mongo client functions have changed from returning
`[AnyHashable: Any]` to `Document`. These should have been `Document` all
along, and the old return type no longer compiles due to not being Sendable.


### Fixed
* <How to hit and notice issue? what was the impact?> ([#????](https://github.com/realm/realm-swift/issues/????), since v?.?.?)
Expand All @@ -14,7 +32,7 @@ x.y.z Release notes (yyyy-MM-dd)
* APIs are backwards compatible with all previous releases in the 10.x.y series.
* Carthage release for Swift is built with Xcode 15.4.0.
* CocoaPods: 1.10 or later.
* Xcode: 15.1.0-16 beta 5.
* Xcode: 15.3.0-16 beta 5.

### Internal
* Upgraded realm-core from ? to ?
Expand Down
5 changes: 4 additions & 1 deletion Configuration/Base.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ APPLICATION_EXTENSION_API_ONLY = YES;
REALM_MACH_O_TYPE = mh_dylib;
SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator watchos watchsimulator appletvos appletvsimulator xros xrsimulator;
SUPPORTS_MACCATALYST = YES;
SWIFT_VERSION = 5.7;
TARGETED_DEVICE_FAMILY = 1,2,3,4,6,7;

SWIFT_VERSION_1500 = 5.7;
SWIFT_VERSION_1600 = 5.7;
SWIFT_VERSION = $(SWIFT_VERSION_$(XCODE_VERSION_MAJOR));

9 changes: 8 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
// swift-tools-version:5.7
// swift-tools-version:5.10

import PackageDescription
import Foundation

let coreVersion = Version("14.12.0")
let cocoaVersion = Version("10.53.0")

#if compiler(>=6)
let swiftVersion = [SwiftVersion.version("6")]
#else
let swiftVersion = [SwiftVersion.v5]
#endif

let cxxSettings: [CXXSetting] = [
.headerSearchPath("."),
.headerSearchPath("include"),
Expand Down Expand Up @@ -392,5 +398,6 @@ let package = Package(
]
)
],
swiftLanguageVersions: swiftVersion,
cxxLanguageStandard: .cxx20
)
45 changes: 31 additions & 14 deletions Realm/ObjectServerTests/AsyncSyncTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -279,9 +279,14 @@ class AsyncAwaitSyncTests: SwiftSyncTestCase {

let configuration = try configuration()
func isolatedOpen(_ actor: isolated CustomExecutorActor) async throws {
#if compiler(<6)
_ = try await Realm(configuration: configuration, actor: actor, downloadBeforeOpen: .always)
#else
_ = try await Realm.open(configuration: configuration, downloadBeforeOpen: .always)
#endif
}


// Try opening the Realm with the Task being cancelled at every possible
// point between executor invocations. This doesn't really test that
// cancellation is *correct*; just that cancellation never results in
Expand Down Expand Up @@ -350,7 +355,7 @@ class AsyncAwaitSyncTests: SwiftSyncTestCase {

func testUserCallFunctionAsyncAwait() async throws {
let user = try await self.app.login(credentials: basicCredentials())
guard case let .int32(sum) = try await user.functions.sum(.array([1, 2, 3, 4, 5])) else {
guard case let .int32(sum) = try await user.functions.sum(1, 2, 3, 4, 5) else {
return XCTFail("Should be int32")
}
XCTAssertEqual(sum, 15)
Expand Down Expand Up @@ -418,9 +423,7 @@ class AsyncAwaitSyncTests: SwiftSyncTestCase {

func testCustomUserDataAsyncAwait() async throws {
let user = try await createUser()
_ = try await user.functions.updateUserData([
["favourite_colour": "green", "apples": 10]
])
_ = try await user.functions.updateUserData(["favourite_colour": "green", "apples": 10])

try await user.refreshCustomData()
XCTAssertEqual(user.customData["favourite_colour"], .string("green"))
Expand All @@ -442,6 +445,7 @@ class AsyncAwaitSyncTests: SwiftSyncTestCase {
XCTAssertEqual(app.allUsers.count, 0)
}

@MainActor
func testSwiftAddObjectsAsync() async throws {
let realm = try await openRealm()
checkCount(expected: 0, realm, SwiftPerson.self)
Expand Down Expand Up @@ -535,10 +539,11 @@ class AsyncFlexibleSyncTests: SwiftSyncTestCase {
try await populateSwiftPerson(5)

let user = try await createUser()
let name = self.name
try await Task {
var config = user.flexibleSyncConfiguration(initialSubscriptions: { subs in
subs.append(QuerySubscription<SwiftPerson> {
$0.age > 0 && $0.firstName == self.name
$0.age > 0 && $0.firstName == name
})
})
config.objectTypes = [SwiftPerson.self]
Expand All @@ -557,7 +562,7 @@ class AsyncFlexibleSyncTests: SwiftSyncTestCase {

var config = user.flexibleSyncConfiguration(initialSubscriptions: { subs in
subs.append(QuerySubscription<SwiftPerson> {
$0.age > 5 && $0.firstName == self.name
$0.age > 5 && $0.firstName == name
})
})
config.objectTypes = [SwiftPerson.self]
Expand All @@ -567,7 +572,7 @@ class AsyncFlexibleSyncTests: SwiftSyncTestCase {

var config2 = user.flexibleSyncConfiguration(initialSubscriptions: { subs in
subs.append(QuerySubscription<SwiftPerson> {
$0.age > 0 && $0.firstName == self.name
$0.age > 0 && $0.firstName == name
})
})
config2.objectTypes = [SwiftPerson.self]
Expand Down Expand Up @@ -621,9 +626,10 @@ class AsyncFlexibleSyncTests: SwiftSyncTestCase {
}

let user = try await createUser()
let name = self.name
var config = user.flexibleSyncConfiguration(initialSubscriptions: { subscriptions in
subscriptions.append(QuerySubscription<SwiftPerson>(name: "person_age_10") {
$0.age > 10 && $0.firstName == "\(self.name)"
$0.age > 10 && $0.firstName == "\(name)"
})
})
config.objectTypes = [SwiftPerson.self]
Expand All @@ -639,10 +645,11 @@ class AsyncFlexibleSyncTests: SwiftSyncTestCase {

@MainActor
func testFlexibleSyncInitialSubscriptionsNotRerunOnOpen() async throws {
let name = self.name
let user = try await createUser()
var config = user.flexibleSyncConfiguration(initialSubscriptions: { subscriptions in
subscriptions.append(QuerySubscription<SwiftPerson>(name: "person_age_10") {
$0.age > 10 && $0.firstName == "\(self.name)"
$0.age > 10 && $0.firstName == "\(name)"
})
})
config.objectTypes = [SwiftPerson.self]
Expand All @@ -657,10 +664,11 @@ class AsyncFlexibleSyncTests: SwiftSyncTestCase {
@MainActor
func testFlexibleSyncInitialSubscriptionsRerunOnOpenNamedQuery() async throws {
let user = try await createUser()
let name = self.name
var config = user.flexibleSyncConfiguration(initialSubscriptions: { subscriptions in
if subscriptions.first(named: "person_age_10") == nil {
subscriptions.append(QuerySubscription<SwiftPerson>(name: "person_age_10") {
$0.age > 20 && $0.firstName == "\(self.name)"
$0.age > 20 && $0.firstName == "\(name)"
})
}
}, rerunOnOpen: true)
Expand Down Expand Up @@ -698,6 +706,7 @@ class AsyncFlexibleSyncTests: SwiftSyncTestCase {

let user = try await createUser()
let isFirstOpen = Locked(true)
let name = self.name
var config = user.flexibleSyncConfiguration(initialSubscriptions: { subscriptions in
subscriptions.append(QuerySubscription<SwiftTypesSyncObject>(query: {
let date = isFirstOpen.wrappedValue ? Calendar.current.date(
Expand All @@ -708,7 +717,7 @@ class AsyncFlexibleSyncTests: SwiftSyncTestCase {
value: -20,
to: Date())
isFirstOpen.wrappedValue = false
return $0.stringCol == self.name && $0.dateCol < Date() && $0.dateCol > date!
return $0.stringCol == name && $0.dateCol < Date() && $0.dateCol > date!
}))
}, rerunOnOpen: true)
config.objectTypes = [SwiftTypesSyncObject.self, SwiftPerson.self]
Expand Down Expand Up @@ -825,7 +834,7 @@ class AsyncFlexibleSyncTests: SwiftSyncTestCase {
.subscribe(name: "8 or older")
realm.syncSession!.suspend()
let ex = XCTestExpectation(description: "no attempt to re-create subscription, returns immediately")
Task {
Task { @MainActor in
_ = try await realm.objects(SwiftPerson.self)
.where { $0.firstName == name && $0.age >= 8 }
.subscribe(name: "8 or older")
Expand Down Expand Up @@ -875,7 +884,7 @@ class AsyncFlexibleSyncTests: SwiftSyncTestCase {
let user = try await createUser()
var config = user.flexibleSyncConfiguration()
config.objectTypes = [SwiftPerson.self]
let realm = try await Realm(configuration: config, actor: MainActor.shared)
let realm = try await Realm(configuration: config)
let results1 = try await realm.objects(SwiftPerson.self)
.where { $0.firstName == name && $0.age > 8 }.subscribe(waitForSync: .onCreation)
XCTAssertEqual(results1.count, 2)
Expand All @@ -890,12 +899,18 @@ class AsyncFlexibleSyncTests: SwiftSyncTestCase {

@CustomGlobalActor
func testSubscribeOnRealmConfinedCustomActor() async throws {
try await populateSwiftPerson()
nonisolated(unsafe) let unsafeSelf = self
try await unsafeSelf.populateSwiftPerson()

let user = try await createUser()
var config = user.flexibleSyncConfiguration()
config.objectTypes = [SwiftPerson.self]
#if compiler(<6)
let realm = try await Realm(configuration: config, actor: CustomGlobalActor.shared)
#else
let realm = try await Realm.open(configuration: config)
#endif
let name = self.name
let results1 = try await realm.objects(SwiftPerson.self)
.where { $0.firstName == name && $0.age > 8 }.subscribe(waitForSync: .onCreation)
XCTAssertEqual(results1.count, 2)
Expand Down Expand Up @@ -957,6 +972,7 @@ class AsyncFlexibleSyncTests: SwiftSyncTestCase {
XCTAssertEqual(realm.subscriptions.first!.name, "sub1")
}

@MainActor
func testUnsubscribeNoExistingMatch() async throws {
try await populateSwiftPerson()
let realm = try await openRealm()
Expand Down Expand Up @@ -1153,6 +1169,7 @@ class AsyncFlexibleSyncTests: SwiftSyncTestCase {

// MARK: - Custom Column

@MainActor
func testCustomColumnFlexibleSyncSchema() throws {
let realm = try openRealm()
for property in realm.schema.objectSchema.first(where: { $0.className == "SwiftCustomColumnObject" })!.properties {
Expand Down
Loading

0 comments on commit a4df969

Please sign in to comment.