-
Notifications
You must be signed in to change notification settings - Fork 10.6k
Description
| Previous ID | SR-7268 |
| Radar | rdar://problem/38817096 |
| Original Reporter | @atrick |
| Type | Improvement |
| Status | Closed |
| Resolution | Done |
Additional Detail from JIRA
| Votes | 0 |
| Component/s | Compiler |
| Labels | Improvement |
| Assignee | @jckarter |
| Priority | Medium |
md5: e48aca74fdd947f40063a338b94cec45
relates to:
- SR-7248 Simultaneous access when using non-class-bound protocol
Issue Description:
Currently, SILGen emits a nonmutating setter call as a mutation of the underlying access path. Enough jargon. This is what happens to an innocent fruit basket:
public protocol Fruit {
var seeds: Int { get nonmutating set }
}
class Apple: Fruit {
init() {}
var seeds: Int = 0
}
public class Basket {
var fruit: Fruit = Apple()
}
public func foo(basket: Basket) {
basket.fruit.seeds = 3
}foo will begin an exclusive modify of `fruit`, call materializeForSet, execute the writeback, and end the exlusive access.
However, the fruit isn't actually being modified (according to this silly class-based model, the seeds aren't part of the value). So, we should not need exclusive access to fruit, and we shouldn't need to materializeForSet or writeback. Just getting a reference to its seeds and calling the setter should be fine.
In addition to performance, this actually affects semantics. Fixing this is backward source compatible though, so this is a good improvement to make any time.
protocol P {
var s: String? { get nonmutating set }
}
class C: P {
init() {}
var s: String? {
didSet {
foo()
}
}
static var shared: P = C()
}
func foo() {
print(C.shared.s ?? "")
}
C.shared.s = "boo"