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