Up to now, the plan for read accessors has been:
- improve compiler support for them to ensure they're demonstrating their theoretical performance advantages
- fix any bugs that arise as part of adopting read accessors more widely
- switch the default opaque access strategy (used in e.g. protocol dispatch) over to use a read accessor instead of a getter
- carve out an implicit exception so that getters are used for storage that produces sufficiently trivial/small types
- carve out explicit exceptions (using an underscored attribute for now) for particular storage declarations (e.g.
CustomStringConvertible.description) that are expected to roughly never return an existing value and thus benefit from using a read accessor
We've made a lot of progress on the first two, and I have a patch that does the third successfully (although it still causes a lot of test failures). As part of winnowing down the test failures, I started going through the stdlib to look at the last task: trying to find storage declarations that I should opt out and force to use getters. It turns out that there are a lot of protocol requirements that are pretty much destined to have computed implementations —
beginIndex, most things in
_NSSwiftValue.value, etc. — and relatively few protocol requirements that really ought to use a read accessor instead. In fact, it's at the point that I'm strongly inclined to switch the polarity of this work: leave getters as the default behavior and require storage declarations (at least in protocols) to opt in to using a read accessor in the opaque access pattern. I would then go through the stdlib and change specific declarations to use read accessors in their opaque pattern.
It has always been a goal of the ownership feature to allow the compiler to make a strong guarantee about certain accesses not causing semantically-visible copies (and ultimately even yielding the exact address of the storage). Making that guarantee through an opaque access requires the use of read accessors. Now, there are at least two reasons why some accesses simply cannot use read accessors: first off,
@objc protocols exist, but even ignoring them, it was inevitable that we'd provide some way to force the use of getters on a protocol requirement, and that annotation necessarily inhibits the guarantee. So this change is just raising the profile of that exception quite a bit: it now requires that either the access is non-opaque or that it's only done through declarations that use opaque read accessors. But I think we can live with that.
The side-benefit of changing the plan is that I may have time to improve the ABI in some other ways, e.g. around key paths.