[Bug or ByDesign?] unowned optional values not allowed


(Karl) #1

Currently it’s not possible to have an unowned optional value. E.g:

class A {
          unowned var parent : A? // ‘unowned’ may only be applied to class and class-bound protocol types, not ‘A?'
          deinit {
            if let p = parent { print("Bye, mom!") }
            print("deallocating")
        }
}

Sometimes you want an unowned value, but it doesn’t actually need to be set.

In a specific case I was working on, we wanted to use a private embedded struct to wrap some functionality away as a unit, but we need a reference back to the enclosing instance. We could have a weak reference, but that comes with additional overheads, and it’s unnecessary because that struct code will all get inlined and the reference will just be a pointer back to ‘self’ (it would be cool if the compiler could detect that and just not emit the variable at all, but I don’t think it’ll do that). In any case, in order to initialise it with the parent that reference needs to be an optional/implicitly-unwrapped-optional (so that it can be initialised to nil and then set after the parent calls super.init).

Given that weak optionals work, I’m tempted to think it’s a bug, but I’m asking in case it was intentionally omitted.


(Jordan Rose) #2

Longstanding bug, rdar://problem/17277899 <rdar://problem/17277899>. Surprisingly few people have asked for it.

Jordan

···

On Jul 3, 2016, at 23:29, Karl via swift-users <swift-users@swift.org> wrote:

Currently it’s not possible to have an unowned optional value. E.g:

class A {
         unowned var parent : A? // ‘unowned’ may only be applied to class and class-bound protocol types, not ‘A?'
         deinit {
           if let p = parent { print("Bye, mom!") }
           print("deallocating")
       }
}

Sometimes you want an unowned value, but it doesn’t actually need to be set.

In a specific case I was working on, we wanted to use a private embedded struct to wrap some functionality away as a unit, but we need a reference back to the enclosing instance. We could have a weak reference, but that comes with additional overheads, and it’s unnecessary because that struct code will all get inlined and the reference will just be a pointer back to ‘self’ (it would be cool if the compiler could detect that and just not emit the variable at all, but I don’t think it’ll do that). In any case, in order to initialise it with the parent that reference needs to be an optional/implicitly-unwrapped-optional (so that it can be initialised to nil and then set after the parent calls super.init).

Given that weak optionals work, I’m tempted to think it’s a bug, but I’m asking in case it was intentionally omitted.

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Zhao Xin) #3

According to you description, you should use

weak var parent:A!

Zhaoxin

···

On Mon, Jul 4, 2016 at 2:29 PM, Karl via swift-users <swift-users@swift.org> wrote:

Currently it’s not possible to have an unowned optional value. E.g:

class A {
          unowned var parent : A? // ‘unowned’ may only be applied to
class and class-bound protocol types, not ‘A?'
          deinit {
            if let p = parent { print("Bye, mom!") }
            print("deallocating")
        }
}

Sometimes you want an unowned value, but it doesn’t actually need to be
set.

In a specific case I was working on, we wanted to use a private embedded
struct to wrap some functionality away as a unit, but we need a reference
back to the enclosing instance. We could have a weak reference, but that
comes with additional overheads, and it’s unnecessary because that struct
code will all get inlined and the reference will just be a pointer back to
‘self’ (it would be cool if the compiler could detect that and just not
emit the variable at all, but I don’t think it’ll do that). In any case, in
order to initialise it with the parent that reference needs to be an
optional/implicitly-unwrapped-optional (so that it can be initialised to
nil and then set after the parent calls super.init).

Given that weak optionals work, I’m tempted to think it’s a bug, but I’m
asking in case it was intentionally omitted.

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Karl) #4

Good to know, thanks.

Maybe not enough people know/care about the overheads of weak references?

Since the WWDC Swift performance talk I’ve been more conscious of eliminating unnecessary retains/releases. That goes for weak references as well, as (certainly on Obj-C), accessing the value means acquiring a lock to ensure nobody is trying to zero that reference while you read it: http://opensource.apple.com//source/objc4/objc4-493.9/runtime/objc-arr.mm (see: objc_loadWeak). It’s basically never going to be in contention, but it’s still more overhead than a simple pointer.

Karl

···

On 5 Jul 2016, at 18:21, Jordan Rose <jordan_rose@apple.com> wrote:

Longstanding bug, rdar://problem/17277899 <rdar://problem/17277899>. Surprisingly few people have asked for it.

Jordan