[swift-evolution] [Proposal] Property behaviors

Joe Groff jgroff at apple.com
Thu Dec 17 15:02:03 CST 2015


> On Dec 17, 2015, at 11:12 AM, Matthew Johnson <matthew at anandabits.com> wrote:
> 
> I’ve really been looking forward to this proposal and I like this idea in general.  I may have comments about specific details after giving it more thought.
> 
> I have one significant concern that is worth mentioning immediately.  I would consider it extremely unfortunate if a delayed property behavior was considered sufficient in support of multi-phase initialization.  Using a property behavior for that purpose gives no guarantee that the value is actually initialized at some point during instance initialization.  IMO this is a major flaw.  A runtime error might occur when accessing a delayed property after initialization is supposed to be complete.
> 
> Delayed property behaviors may have appropriate use cases but IMO they are not an adequate substitute for something that provides stronger guarantees for the common case of multi-phase initialization.
> 
> I very strongly prefer to see direct language support for multi-phase initialization.  The compiler could provide most of the initialization guarantees it does for regular let properties.  It could enforce single assignment in the initializer body and could prevent the initializer body itself from reading the delayed property before assignment.  

Even without any compiler support, I think implementing (delayed) as a behavior will be an improvement over the status quo. You get none of these guarantees with a `var T!` property either, and you also lose safety from some jerk resetting the property to `nil` or changing the property again after it's supposed to stop being mutated. Being a library feature also doesn't preclude a `delayed` behavior from offering diagnostics in common cases. One of our design goals for the SIL layer was to support dataflow-sensitive diagnostics like this; even though integers and arithmetic are implemented as library features, we run optimization passes that fold literal constant arithmetic down and raise errors when constant values aren't able to statically fit in their containing types. We could do something similar for a production-quality `(delayed)` implementation in the standard library.

> The only guarantee that may not be possible is method calls to self during the second phase of initialization, but prior to assignment of all delayed properties (whether directly or by passing self to another instance) are potentially dangerous if they caused a read to a delayed property.  The potential for error is significantly narrower with direct language support.  As this is a very common use case (possibly the most common use case for delayed properties) I strongly believe it warrants direct language support.

Yeah, statically guaranteeing initialization phase order across method calls is tricky if you don't have type state or linear types, which until recently have been fairly esoteric features (though Rust is making the latter more prominent). I think implementing `delayed` as proposed still improves the static and dynamic safety of multi-phase initialization over what we have, and it doesn't shut the door to further refinement in the future.

-Joe


More information about the swift-evolution mailing list