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

Patrick Smith pgwsmith at gmail.com
Tue May 3 19:15:15 CDT 2016


Why not separate the reference and its info? That way you can make the
reference weak.

  

enum ParentChildRelationship {

  case Son

  case Daughter

}

  

class Parent {

  lazy var son: Child = Child(sonOf: self)

  lazy var daughter: Child = Child(daughterOf: self)

  deinit { print("deinit Parent") }

}

  

class Child {

  weak var parent: Parent?

  var parentRelationship: ParentChildRelationship

  init(parent: Parent, relationship: ParentChildRelationship) {

    self.parent = parent

    self.parentRelationship = relationship

  }

  convenience init(sonOf parent: Parent) {

    self.init(parent: parent, relationship: .Son)

  }

  

  convenience init(daughterOf parent: Parent) {

    self.init(parent: parent, relationship: .Daughter)

  }

  

  deinit { print("deinit Child") }

}

  

  

do {

  let parent = Parent()

  parent.son

  parent.daughter

}

  

  
**Patrick Smith**  

On May 4 2016, at 1:07 am, 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

>

>  

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


More information about the swift-evolution mailing list