Another way to address this might be by allowing property behaviors, a feature 
proposed in 
https://github.com/apple/swift-evolution/blob/master/proposals/0030-property-behavior-decls.md
 to allow for factoring out property implementations, could also apply to 
`case` declarations. "Weak" and "unowned" could be considered to be property 
behaviors once we have them, so you'd write something like:

class Foo {
  var parent: Foo?
    behavior weak
}

to define a property with "weak" behavior. We could potentially allow you to 
apply behaviors to 'case' associated values too:

enum ParentChild {
  case Parent(Parent) behavior unowned
  case Child(Parent) behavior unowned
}

-Joe

> On May 3, 2016, at 8:07 AM, 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