1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
|
// RUN: %target-run-simple-swift(-parse-as-library -Xfrontend -enable-copy-propagation -Xfrontend -enable-lexical-lifetimes=false -Xfrontend -disable-availability-checking) | %FileCheck %s
// REQUIRES: executable_test
// REQUIRES: concurrency
// rdar://76038845
// REQUIRES: concurrency_runtime
// UNSUPPORTED: back_deployment_runtime
struct Container {
@MainActor static var counter: Int = 10
@MainActor static var this: Container?
var noniso: Int = 20
static func getCount() async -> Int {
return await counter
}
static func getValue() async -> Int? {
return await this?.noniso
}
}
@propertyWrapper
struct SuccessTracker {
private var _stored: Bool
private var numReads : Int = 0 // an unchecked statistic to exercise mutating get
init(initially: Bool) {
self._stored = initially
}
var wrappedValue: Bool {
mutating get {
numReads += 1
return _stored
}
set { _stored = newValue }
}
}
func writeToBool(_ b : inout Bool, _ val : Bool) {
b = val
}
actor List<T : Sendable> {
var head : T
var tail : List<T>?
lazy var hasTail : Bool = (tail != nil)
var computedTail : List<T>? {
get { tail }
}
subscript(_ offset : Int) -> T? {
// since we don't have async subscripts, we just return nil for non-zero inputs! :)
if offset != 0 {
return nil
}
return head
}
/// this silly property is here just for testing wrapped-property access
@SuccessTracker(initially: true) var success : Bool
func setSuccess(_ b : Bool) { writeToBool(&success, b) }
init(_ value : T) {
self.head = value
self.tail = nil
}
init(_ value : T, _ tail : List<T>) {
self.head = value
self.tail = tail
}
func last() async -> T {
switch tail {
case .none:
return head
case .some(let tl):
if await tl.hasTail {
return await tl.last()
}
return await tl.head
}
}
static func tabulate(_ n : Int, _ f : (Int) -> T) -> List<T> {
if n == 0 {
return List<T>(f(n))
}
return List<T>(f(n), tabulate(n-1, f))
}
static func foldr<R>(_ f : (T, R) -> R, _ start : R, _ lst : List<T>) async -> R {
switch await lst.tail {
case .none:
return f(await lst.head, start)
case .some(let tl):
return f(await lst.head, await foldr(f, start, tl))
}
}
}
actor Tester {
/// returns true iff success
func doListTest() async -> Bool {
let n = 4 // if you change this, you'll have to update other stuff too
let ints = List<Int>.tabulate(n, { $0 })
let last1 = await ints.tail!.computedTail!.tail!.tail![0]
let last2 = await ints.last()
guard last1 == last2 else {
print("fail 1")
return false
}
let expected = (n * (n + 1)) / 2
let sum = await List<Int>.foldr({ $0 + $1 }, 0, ints)
guard sum == expected else {
print("fail 2")
return false
}
// CHECK: done list test
// CHECK-NOT: fail
print("done list test")
return true
}
func doPropertyWrapperTest() async -> Bool {
let actor = List<String>("blah")
await actor.setSuccess(false)
guard await actor.success == false else {
print("fail 3")
return false
}
await actor.setSuccess(true)
guard await actor.success == true else {
print("fail 4")
return false
}
// CHECK: done property wrapper test
// CHECK-NOT: fail
print("done property wrapper test")
return true
}
func doContainerTest() async -> Bool {
var total: Int = 0
total += await Container.getCount()
total += await Container.getValue() ?? 0
return total == 10
}
}
@globalActor
struct SillyActor {
actor _Impl {}
static let shared = _Impl()
}
@SillyActor
var test : Tester = Tester()
@SillyActor
var expectedResult : Bool {
get { true }
set {}
}
@main struct RunIt {
static func main() async {
let success = await expectedResult
guard await test.doListTest() == success else {
fatalError("fail list test")
}
guard await test.doPropertyWrapperTest() == success else {
fatalError("fail property wrapper test")
}
guard await test.doContainerTest() == success else {
fatalError("fail container test")
}
// CHECK: done all testing
print("done all testing")
}
}
|