[swift-evolution] [Pitch] Reference storage for enum associated values

Haravikk swift-evolution at haravikk.me
Tue May 3 17:21:33 CDT 2016


It’s an interesting idea, but with the workaround you’ve found I wonder if it might make more sense to just have Unowned<T> and Weak<T> in the standard library? I’ve already defined these myself to work with a few awkward cases and to allow entries in collections to be weakly referenced.

I mean it’d be nice to have keyword support too; I wonder if could be made more flexible, e.g- let us also write things like:

	let foo:[weak AnyObject] = …

Externally this would appear as if the array were of type AnyObject?, but internally the array would have an actual type of Weak<AnyObject> or whatever. I dunno, just thinking out loud, point being that maybe this isn’t enum specific, even though enum is an important use-case, i.e- a keyword or global function could make this easier to do throughout the language.

> On 3 May 2016, at 16:07, Marc Prud'hommeaux via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 
> The following code currently has a retain cycle and memory leak:
> 
> enum ParentChild {
>     case SonOf(Parent)
>     case DaughterOf(Parent)
> }
> 
> class Parent {
>     lazy var son: Child = Child(parentChild: .SonOf(self))
>     lazy var daughter: Child = Child(parentChild: .DaughterOf(self))
>     deinit { print("deinit Parent") }
> }
> 
> class Child {
>     var parentChild: ParentChild
>     init(parentChild: ParentChild) {
>         self.parentChild = parentChild
>     }
>     deinit { print("deinit Child") }
> }
> 
> 
> do {
>     let parent = Parent()
>     parent.son
>     parent.daughter
> }
> 
> 
> Child.parentChild cannot be declared unowned because ParentChild is a value type. I propose adding the ability to declare the reference storage class for an enum's associated value, like so:
> 
> enum ParentChild {
>     case SonOf(unowned Parent)
>     case DaughterOf(unowned Parent)
> }
> 
> The only current alternative is to have some intermediate reference type that itself holds the reference, akin to the old "Box" type that we used to use to work around enum limitations. E.g., this is our current cumbersome work-around:
> 
> /// An unowned reference to a value, which is useful for maintaining parent-child relations through value types like enums
> public struct UnownedRef<T: AnyObject> {
>     public unowned let value: T
>     public init(_ value: T) { self.value = value }
> }
> 
> enum ParentChild {
>     case SonOf(UnownedRef<Parent>)
>     case DaughterOf(UnownedRef<Parent>)
> }
> 
> 
> class Parent {
>     lazy var son: Child = Child(parentChild: .SonOf(UnownedRef(self)))
>     lazy var daughter: Child = Child(parentChild: .DaughterOf(UnownedRef(self)))
>     deinit { print("deinit Foo") }
> }
> 
> class Child {
>     var parentChild: ParentChild
>     init(parentChild: ParentChild) {
>         self.parentChild = parentChild
>     }
> 
>     deinit { print("deinit Child") }
> }
> 
> The storage type of an enum would, of course, be limited to reference types, and when the storage class is weak, it would require that the stored type be Optional, just like when declaring a weak variable.
> 
> What do people think?
> 
> 	-Marc
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160503/009d71ff/attachment.html>


More information about the swift-evolution mailing list