Files
swift-mirror/test/ClangImporter/objc_async.swift
Becca Royal-Gordon 7549278314 Allow imported types to add a Sendable conformance
...by using `__attribute__((swift_attr("@Sendable")))`. `@_nonSendable` will "beat" `@Sendable`, while `@_nonSendable(_assumed)` will not.

This commit also checks if `SwiftAttr` supports `#pragma clang attribute` and, if it does, defines `__SWIFT_ATTR_SUPPORTS_SENDABLE_DECLS` in imported headers so they know they can apply these attributes in an auditing style.
2021-11-12 23:13:29 -08:00

196 lines
5.9 KiB
Swift

// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -I %S/Inputs/custom-modules -disable-availability-checking %s -verify -warn-concurrency
// REQUIRES: objc_interop
// REQUIRES: concurrency
import Foundation
import ObjCConcurrency
@MainActor func onlyOnMainActor() { }
func testSlowServer(slowServer: SlowServer) async throws {
let _: Int = await slowServer.doSomethingSlow("mail")
let _: Bool = await slowServer.checkAvailability()
let _: String = try await slowServer.findAnswer()
let _: String = try await slowServer.findAnswerFailingly()
let (aOpt, b) = try await slowServer.findQAndA()
if let a = aOpt { // make sure aOpt is optional
print(a)
}
let _: String = b // make sure b is non-optional
let _: String = try await slowServer.findAnswer()
let _: Void = await slowServer.doSomethingFun("jump")
let _: (Int) -> Void = slowServer.completionHandler
// async version
let _: Int = await slowServer.doSomethingConflicted("thinking")
// still async version...
let _: Int = slowServer.doSomethingConflicted("thinking")
// expected-error@-1{{expression is 'async' but is not marked with 'await'}}{{16-16=await }}
// expected-note@-2{{call is 'async'}}
let _: String? = try await slowServer.fortune()
let _: Int = try await slowServer.magicNumber(withSeed: 42)
await slowServer.serverRestart("localhost")
await slowServer.serverRestart("localhost", atPriority: 0.8)
_ = await slowServer.allOperations()
let _: Int = await slowServer.bestName("hello")
let _: Int = await slowServer.customize("hello")
let _: String = await slowServer.dance("slide")
let _: String = await slowServer.__leap(17)
slowServer.repeatTrick("jump") // expected-error{{missing argument for parameter 'completionHandler' in call}}
_ = try await slowServer.someAsyncMethod()
_ = await slowServer.operations()
_ = await slowServer.runOnMainThread()
}
func testSlowServerSynchronous(slowServer: SlowServer) {
// synchronous version
let _: Int = slowServer.doSomethingConflicted("thinking")
slowServer.poorlyNamed("hello") { (i: Int) in print(i) }
slowServer.customize(with: "hello") { (i: Int) in print(i) }
slowServer.dance("jig") { s in print(s + "") }
slowServer.leap(17) { s in print(s + "") }
slowServer.repeatTrick("jump") { i in print(i + 1) }
let s = slowServer.operations
_ = s + []
slowServer.runOnMainThread { s in
print(s)
onlyOnMainActor() // okay because runOnMainThread has a @MainActor closure
}
slowServer.overridableButRunsOnMainThread { s in
print(s)
onlyOnMainActor() // okay because parameter has @_unsafeMainActor
}
let _: Int = slowServer.overridableButRunsOnMainThread // expected-error{{cannot convert value of type '(((String) -> Void)?) -> Void' to specified type 'Int'}}
}
func testSlowServerOldSchool(slowServer: SlowServer) {
slowServer.doSomethingSlow("mail") { i in
_ = i
}
_ = slowServer.allOperations
}
func testSendable(fn: () -> Void) { // expected-note{{parameter 'fn' is implicitly non-sendable}}
doSomethingConcurrently(fn)
// expected-error@-1{{passing non-sendable parameter 'fn' to function expecting a @Sendable closure}}
doSomethingConcurrentlyButUnsafe(fn) // okay, @Sendable not part of the type
var x = 17
doSomethingConcurrently {
print(x) // expected-error{{reference to captured var 'x' in concurrently-executing code}}
x = x + 1 // expected-error{{mutation of captured var 'x' in concurrently-executing code}}
// expected-error@-1{{reference to captured var 'x' in concurrently-executing code}}
}
}
func testSendableInAsync() async {
var x = 17
doSomethingConcurrentlyButUnsafe {
x = 42 // expected-error{{mutation of captured var 'x' in concurrently-executing code}}
}
print(x)
}
func testSendableClasses(sendable: SendableClass, nonSendable: NonSendableClass) async {
func takesSendable<T: Sendable>(_: T) {}
takesSendable(sendable) // no-error
takesSendable(nonSendable) // expected-FIXME-warning{{something about missing conformance}}
doSomethingConcurrently {
print(sendable) // no-error
print(nonSendable) // expected-warning{{cannot use parameter 'nonSendable' with a non-sendable type 'NonSendableClass' from concurrently-executed code}}
}
}
// Check import of attributes
func globalAsync() async { }
actor MySubclassCheckingSwiftAttributes : ProtocolWithSwiftAttributes {
func syncMethod() { } // expected-note 2{{calls to instance method 'syncMethod()' from outside of its actor context are implicitly asynchronous}}
nonisolated func independentMethod() {
syncMethod() // expected-error{{ctor-isolated instance method 'syncMethod()' can not be referenced from a non-isolated context}}
}
nonisolated func nonisolatedMethod() {
}
@MainActor func mainActorMethod() {
syncMethod() // expected-error{{actor-isolated instance method 'syncMethod()' can not be referenced from the main actor}}
}
@MainActor func uiActorMethod() { }
}
// Sendable conformance inference for imported types.
func acceptCV<T: Sendable>(_: T) { }
func testCV(r: NSRange) {
acceptCV(r)
}
// Global actor (unsafe) isolation.
actor SomeActor { }
@globalActor
struct SomeGlobalActor {
static let shared = SomeActor()
}
class MyButton : NXButton {
@MainActor func testMain() {
onButtonPress() // okay
}
@SomeGlobalActor func testOther() {
onButtonPress() // expected-error{{call to main actor-isolated instance method 'onButtonPress()' in a synchronous global actor 'SomeGlobalActor'-isolated context}}
}
func test() {
onButtonPress() // okay
}
}
func testButtons(mb: MyButton) {
mb.onButtonPress()
}
func testMirrored(instance: ClassWithAsync) async {
await instance.instanceAsync()
await instance.protocolMethod()
await instance.customAsyncName()
}
@MainActor class MyToolbarButton : NXButton {
var count = 5
func f() {
Task {
let c = count
print(c)
}
}
}