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 
> <[email protected]> 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
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to