SE-0258: Property Wrappers (third review)

@Douglas_Gregor more feedback incoming.

I think we should generalize the following three rules further:

  • The wrappedValue property and (if present) init(initialValue:) of a property wrapper type shall have the same access as the property wrapper type.
  • The projectedValue property, if present, shall have the same access as the property wrapper type.
  • The init() initializer, if present, shall have the same access as the property wrapper type.

None of there rules, except the part about wrappedValue, should require same access level as the wrapper itself.

  • The author of a wrapper type should decide wether or not the client should have access to any of the wrappers initializers. If non are present then the client shouldn‘t be able to wrap his properties with that particular wrapper, it might be an implementation detail or artifact that the wrapper type itself must leak to the client as it‘s potentially used somewhere as a normal type in public API‘s. In the same spirit the author might want to implement an internal init() with some special default while my client should only ever wrap his properties using the public init(initialValue:). You can invert the access level of the previous example as the author might want to expose init() but keep init(initialValue:) internally. Therefore there is no need to require any initializer to have a particular access level, that should remain the wrapper authors decision.

  • I mentioned upthread that with the current design we can safely allow retroactive extensions of projectedValue but at users risk that the wrapper author might add his own implementation of that property in the future and break users code (this is true for any extension of types that the user does not own). I think we do not need projectedValue to have the same access level the wrapper. On a public wrapper the projectedValue might be an implementation detail that should only generate projections internally. This still plays well with future access_level(projection) that can be used by the module author to limit or expose specific projections explicitly.

Both access level restrictions are unnecessary limitations that limit the flexibility of wrapper usage. If there are no inference mechanics involved like for wrappedValue then we should generalize these rules further and make these parts of the type behave literally the same way they behave today.

2 Likes