Skip to content

Commit 7d28a4f

Browse files
committed
[TypeChecker] NFC: Add more property wrapper tests
1 parent 047f51f commit 7d28a4f

File tree

3 files changed

+130
-0
lines changed

3 files changed

+130
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
@typeWrapper
2+
public struct Wrapper<S> {
3+
var underlying: S
4+
5+
public init(memberwise: S) {
6+
print("Wrapper.init(\(memberwise))")
7+
self.underlying = memberwise
8+
}
9+
10+
public subscript<V>(storageKeyPath path: WritableKeyPath<S, V>) -> V {
11+
get {
12+
print("in getter")
13+
return underlying[keyPath: path]
14+
}
15+
set {
16+
print("in setter => \(newValue)")
17+
underlying[keyPath: path] = newValue
18+
}
19+
}
20+
}
21+
22+
@Wrapper
23+
public class Person<T> {
24+
public var name: String
25+
public var projects: [T]
26+
}

test/Interpreter/type_wrappers.swift

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -parse-as-library -emit-library -emit-module-path %t/type_wrapper_defs.swiftmodule -module-name type_wrapper_defs %S/Inputs/type_wrapper_defs.swift -o %t/%target-library-name(type_wrapper_defs)
3+
// RUN: %target-build-swift -ltype_wrapper_defs -module-name main -I %t -L %t %s -o %t/a.out
4+
// RUN: %target-run %t/a.out | %FileCheck %s
5+
6+
import type_wrapper_defs
7+
8+
var p: Person<String> = .init(name: "P", projects: ["A", "B"])
9+
// CHECK: Wrapper.init($Storage(name: "P", projects: ["A", "B"]))
10+
11+
print(p.name)
12+
// CHECK: in getter
13+
// CHECK-NEXT: P
14+
print(p.projects)
15+
// CHECK: in getter
16+
// CHECK-NEXT: ["A", "B"]
17+
18+
p.name = "OtherP"
19+
// CHECK: in setter => OtherP
20+
p.projects.append("C")
21+
// CHECK: in getter
22+
// CHECK-NEXT: in setter => ["A", "B", "C"]
23+
24+
25+
func addProjects<T>(p: inout Person<T>, _ newProjects: [T]) {
26+
p.projects.append(contentsOf: newProjects)
27+
}
28+
29+
addProjects(p: &p, ["D"])
30+
// CHECK: in getter
31+
// CHECK: in setter => ["A", "B", "C", "D"]
32+
33+
print(p.name)
34+
// CHECK: in getter
35+
// CHECK-NEXT: OtherP
36+
37+
print(p.projects)
38+
// CHECK: in getter
39+
// CHECK-NEXT: ["A", "B", "C", "D"]

test/type/type_wrapper.swift

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,68 @@ struct InaccessibleOrInvalidSubscripts<S> {
8282
get { true }
8383
}
8484
}
85+
86+
@typeWrapper
87+
struct NoopWrapper<S> {
88+
init(memberwise: S) {}
89+
90+
subscript<V>(storageKeyPath path: KeyPath<S, V>) -> V {
91+
get { fatalError() }
92+
set { }
93+
}
94+
}
95+
96+
@NoopWrapper
97+
struct A {
98+
var a: String
99+
var b: Int
100+
}
101+
102+
@NoopWrapper
103+
class GenericA<K: Hashable, V> {
104+
var data: [K: V]
105+
}
106+
107+
@NoopWrapper // expected-error {{type wrapper attribute 'NoopWrapper' can only be applied to a class, struct}}
108+
protocol P {
109+
}
110+
111+
@NoopWrapper // expected-error {{type wrapper attribute 'NoopWrapper' can only be applied to a class, struct}}
112+
enum E {
113+
var x: Int { get { 42 } }
114+
}
115+
116+
func testWrappedTypeAccessChecking() {
117+
let a = A(a: "", b: 42) // synthesized init
118+
let b = GenericA(data: ["ultimate question": 42]) // generic synthesized init
119+
120+
_ = a.a // Ok
121+
_ = b.data // Ok
122+
}
123+
124+
struct Parent {
125+
@typeWrapper
126+
struct Wrapper<S> {
127+
init(memberwise: S) {}
128+
129+
subscript<V>(storageKeyPath path: KeyPath<S, V>) -> V {
130+
get { fatalError() }
131+
set { }
132+
}
133+
}
134+
}
135+
136+
func testLocalWithNestedWrapper() {
137+
@Parent.Wrapper
138+
class WithNestedWrapper<T> {
139+
var test: [T]
140+
141+
var computed: String {
142+
get { "" }
143+
}
144+
}
145+
146+
let t = WithNestedWrapper(test: [1, 2]) // synthesized init
147+
_ = t.test // Ok
148+
_ = t.computed // Ok
149+
}

0 commit comments

Comments
 (0)