Weak references in generic types


(Howard Lovatt) #1

Hi,

I am wanting to use weak references in generic data structures; in the
example below Array, but in general any generic type. I can almost get it
to work :frowning:

My experiments started off well; the following works:

// Array of weak references OK
struct WeakReference<T: AnyObject> {
    weak var value: T?
}
class C {
    var i: Int = 0
}
let c = C() // Strong reference to prevent collection
let weakCs = [WeakReference(value: c)] // OK
print("C: \(weakCs[0].value!.i)") // 0

I can add a protocol:

// Array of weak references that implements a protocol OK
protocol P: AnyObject { // Note AnyObject
    var i: Int { get }
}
class CP: P {
    var i: Int = 0
}
let cP = CP() // Strong reference to prevent collection
let weakCPs = [WeakReference(value: cP)] // OK
print("CP: \(weakCPs[0].value!.i)") // 0

But when I want an array of weak references to the protocol I get an error:

// Array of weak references of a protocol not OK
let weakPs: [WeakReference<P>] = [WeakReference(value: cP)] // Using 'P' as
a concrete type conforming to protocol 'AnyObject' is not supported
print("P: \(weakPs[0].value!.i)") // 0

Is there something I have missed?

The error message, "Using 'P' as a concrete type conforming to protocol
'AnyObject' is not supported", implies that it is a temporary limitation of
the compiler; is this going to be fixed? Should I lodge a bug report?

Thanks in advance for any advice,

  -- Howard.


(Howard Lovatt) #2

Playing around I found that if you make the protocol @objc instead of
AnyObject then it works :). EG:

struct WeakReference<T: AnyObject> {
    weak var value: T?
}
@objc protocol P { // Note @objc, class or AnyObject does not work
    var i: Int { get }
}
class CP: P {
    var i: Int = 0
}
let weakPs: [WeakReference<P>] = [WeakReference(value: cP)] // Note typed
as `[WeakReference<P>]`
print("P: \(weakPs[0].value!.i)") // 0

Not a 'pure' Swift solution :(, but OK in my case.

  -- Howard.

···

On 29 August 2016 at 16:21, Howard Lovatt <howard.lovatt@gmail.com> wrote:

Hi,

I am wanting to use weak references in generic data structures; in the
example below Array, but in general any generic type. I can almost get it
to work :frowning:

My experiments started off well; the following works:

// Array of weak references OK
struct WeakReference<T: AnyObject> {
    weak var value: T?
}
class C {
    var i: Int = 0
}
let c = C() // Strong reference to prevent collection
let weakCs = [WeakReference(value: c)] // OK
print("C: \(weakCs[0].value!.i)") // 0

I can add a protocol:

// Array of weak references that implements a protocol OK
protocol P: AnyObject { // Note AnyObject
    var i: Int { get }
}
class CP: P {
    var i: Int = 0
}
let cP = CP() // Strong reference to prevent collection
let weakCPs = [WeakReference(value: cP)] // OK
print("CP: \(weakCPs[0].value!.i)") // 0

But when I want an array of weak references to the protocol I get an error:

// Array of weak references of a protocol not OK
let weakPs: [WeakReference<P>] = [WeakReference(value: cP)] // Using 'P'
as a concrete type conforming to protocol 'AnyObject' is not supported
print("P: \(weakPs[0].value!.i)") // 0

Is there something I have missed?

The error message, "Using 'P' as a concrete type conforming to protocol
'AnyObject' is not supported", implies that it is a temporary limitation of
the compiler; is this going to be fixed? Should I lodge a bug report?

Thanks in advance for any advice,

  -- Howard.


(Karl) #3

Your problem is protocol self-conformance. In the first example, you’re creating WeakReference<CP>. CP conforms to P and to AnyObject. In the second example, you’re creating WeakReference<P>. P does not conform to P or to AnyObject.

As for why @objc fixes it? … ¯\_(ツ)_/¯ all bets are off whenever @objc gets involved in anything.

Karl

···

On 1 Sep 2016, at 03:23, Howard Lovatt via swift-users <swift-users@swift.org> wrote:

Playing around I found that if you make the protocol @objc instead of AnyObject then it works :). EG:

struct WeakReference<T: AnyObject> {
    weak var value: T?
}
@objc protocol P { // Note @objc, class or AnyObject does not work
    var i: Int { get }
}
class CP: P {
    var i: Int = 0
}
let weakPs: [WeakReference<P>] = [WeakReference(value: cP)] // Note typed as `[WeakReference<P>]`
print("P: \(weakPs[0].value!.i)") // 0
Not a 'pure' Swift solution :(, but OK in my case.

  -- Howard.

On 29 August 2016 at 16:21, Howard Lovatt <howard.lovatt@gmail.com <mailto:howard.lovatt@gmail.com>> wrote:
Hi,

I am wanting to use weak references in generic data structures; in the example below Array, but in general any generic type. I can almost get it to work :frowning:

My experiments started off well; the following works:

// Array of weak references OK
struct WeakReference<T: AnyObject> {
    weak var value: T?
}
class C {
    var i: Int = 0
}
let c = C() // Strong reference to prevent collection
let weakCs = [WeakReference(value: c)] // OK
print("C: \(weakCs[0].value!.i)") // 0

I can add a protocol:

// Array of weak references that implements a protocol OK
protocol P: AnyObject { // Note AnyObject
    var i: Int { get }
}
class CP: P {
    var i: Int = 0
}
let cP = CP() // Strong reference to prevent collection
let weakCPs = [WeakReference(value: cP)] // OK
print("CP: \(weakCPs[0].value!.i)") // 0

But when I want an array of weak references to the protocol I get an error:

// Array of weak references of a protocol not OK
let weakPs: [WeakReference<P>] = [WeakReference(value: cP)] // Using 'P' as a concrete type conforming to protocol 'AnyObject' is not supported
print("P: \(weakPs[0].value!.i)") // 0

Is there something I have missed?

The error message, "Using 'P' as a concrete type conforming to protocol 'AnyObject' is not supported", implies that it is a temporary limitation of the compiler; is this going to be fixed? Should I lodge a bug report?

Thanks in advance for any advice,

  -- Howard.

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


(Howard Lovatt) #4

@Karl,

You say "In the second example, you’re creating WeakReference<P>. P does
not conform to P or to AnyObject.", but P does conform to AnyObject.

I suspect it is a compiler limitation/ bug.

-- Howard.

···

On Thursday, 1 September 2016, Karl <razielim@gmail.com> wrote:

On 1 Sep 2016, at 03:23, Howard Lovatt via swift-users < > swift-users@swift.org > <javascript:_e(%7B%7D,'cvml','swift-users@swift.org');>> wrote:

Playing around I found that if you make the protocol @objc instead of
AnyObject then it works :). EG:

struct WeakReference<T: AnyObject> {
    weak var value: T?
}
@objc protocol P { // Note @objc, class or AnyObject does not work
    var i: Int { get }
}
class CP: P {
    var i: Int = 0
}
let weakPs: [WeakReference<P>] = [WeakReference(value: cP)] // Note typed
as `[WeakReference<P>]`
print("P: \(weakPs[0].value!.i)") // 0

Not a 'pure' Swift solution :(, but OK in my case.

  -- Howard.

On 29 August 2016 at 16:21, Howard Lovatt <howard.lovatt@gmail.com > <javascript:_e(%7B%7D,'cvml','howard.lovatt@gmail.com');>> wrote:

Hi,

I am wanting to use weak references in generic data structures; in the
example below Array, but in general any generic type. I can almost get it
to work :frowning:

My experiments started off well; the following works:

// Array of weak references OK
struct WeakReference<T: AnyObject> {
    weak var value: T?
}
class C {
    var i: Int = 0
}
let c = C() // Strong reference to prevent collection
let weakCs = [WeakReference(value: c)] // OK
print("C: \(weakCs[0].value!.i)") // 0

I can add a protocol:

// Array of weak references that implements a protocol OK
protocol P: AnyObject { // Note AnyObject
    var i: Int { get }
}
class CP: P {
    var i: Int = 0
}
let cP = CP() // Strong reference to prevent collection
let weakCPs = [WeakReference(value: cP)] // OK
print("CP: \(weakCPs[0].value!.i)") // 0

But when I want an array of weak references to the protocol I get an
error:

// Array of weak references of a protocol not OK
let weakPs: [WeakReference<P>] = [WeakReference(value: cP)] // Using 'P'
as a concrete type conforming to protocol 'AnyObject' is not supported
print("P: \(weakPs[0].value!.i)") // 0

Is there something I have missed?

The error message, "Using 'P' as a concrete type conforming to protocol
'AnyObject' is not supported", implies that it is a temporary limitation of
the compiler; is this going to be fixed? Should I lodge a bug report?

Thanks in advance for any advice,

  -- Howard.

_______________________________________________
swift-users mailing list
swift-users@swift.org
<javascript:_e(%7B%7D,'cvml','swift-users@swift.org');>
https://lists.swift.org/mailman/listinfo/swift-users

Your problem is protocol self-conformance. In the first example, you’re
creating WeakReference<CP>. CP conforms to P and to AnyObject. In the
second example, you’re creating WeakReference<P>. P does not conform to P
or to AnyObject.

As for why @objc fixes it? … ¯\_(ツ)_/¯ all bets are off whenever @objc
gets involved in anything.

Karl

--
-- Howard.


(Karl) #5

What I'm trying to say is that P is a protocol and not a class, so it does not conform to AnyObject. P does not conform to P.
  
It is in some sense a language limitation that we cant express what you're talking about. If we weren't using mailing lists it would be easier to search for "protocol self-conformance" on swift-evo and to read the earlier discussion about it.

···

  
On Sep 2, 2016 at 1:04 am, <Howard Lovatt (mailto:howard.lovatt@gmail.com)> wrote:
  
@Karl,

You say "In the second example, you’re creating WeakReference<P>. P does not conform to P or to AnyObject.", but P does conform to AnyObject.
  
I suspect it is a compiler limitation/ bug.
  
  -- Howard.

On Thursday, 1 September 2016, Karl <razielim@gmail.com (mailto:razielim@gmail.com)> wrote:
  
>
>
>
>
> >
> > On 1 Sep 2016, at 03:23, Howard Lovatt via swift-users <swift-users@swift.org (javascript:_e(%7B%7D,'cvml','swift-users@swift.org');)> wrote:
> >
> >
> >
> > Playing around I found that if you make the protocol @objc instead of AnyObject then it works :). EG:
> >
> >
> > >
> > > struct WeakReference<T: AnyObject> {
> > >
> > > weak var value: T?
> > >
> > > }
> > >
> > > @objc protocol P { // Note @objc, class or AnyObject does not work
> > >
> > > var i: Int { get }
> > >
> > > }
> > >
> > > class CP: P {
> > >
> > > var i: Int = 0
> > >
> > > }
> > >
> > > let weakPs: [WeakReference<P>] = [WeakReference(value: cP)] // Note typed as `[WeakReference<P>]`
> > >
> > > print("P: \(weakPs[0].value!.i)") // 0
> > >
> >
> >
> >
> > Not a 'pure' Swift solution :(, but OK in my case.
> >
> >
> >
> >
> >
> >
> >
> > -- Howard.
> >
> >
> > On 29 August 2016 at 16:21, Howard Lovatt <howard.lovatt@gmail.com (javascript:_e(%7B%7D,'cvml','howard.lovatt@gmail.com');)> wrote:
> >
> > >
> > > Hi,
> > >
> > >
> > > I am wanting to use weak references in generic data structures; in the example below Array, but in general any generic type. I can almost get it to work :frowning:
> > >
> > >
> > >
> > > My experiments started off well; the following works:
> > >
> > >
> > >
> > > >
> > > > // Array of weak references OK
> > > >
> > > > struct WeakReference<T: AnyObject> {
> > > >
> > > > weak var value: T?
> > > >
> > > > }
> > > >
> > > > class C {
> > > >
> > > > var i: Int = 0
> > > >
> > > > }
> > > >
> > > > let c = C() // Strong reference to prevent collection
> > > >
> > > > let weakCs = [WeakReference(value: c)] // OK
> > > >
> > > > print("C: \(weakCs[0].value!.i)") // 0
> > > >
> > >
> > > I can add a protocol:
> > >
> > >
> > > >
> > > > // Array of weak references that implements a protocol OK
> > > >
> > > > protocol P: AnyObject { // Note AnyObject
> > > >
> > > > var i: Int { get }
> > > >
> > > > }
> > > >
> > > > class CP: P {
> > > >
> > > > var i: Int = 0
> > > >
> > > > }
> > > >
> > > > let cP = CP() // Strong reference to prevent collection
> > > >
> > > > let weakCPs = [WeakReference(value: cP)] // OK
> > > >
> > > > print("CP: \(weakCPs[0].value!.i)") // 0
> > > >
> > >
> > >
> > >
> > >
> > > But when I want an array of weak references to the protocol I get an error:
> > >
> > >
> > >
> > > >
> > > > // Array of weak references of a protocol not OK
> > > >
> > > > let weakPs: [WeakReference<P>] = [WeakReference(value: cP)] // Using 'P' as a concrete type conforming to protocol 'AnyObject' is not supported
> > > >
> > > > print("P: \(weakPs[0].value!.i)") // 0
> > > >
> > >
> > >
> > >
> > >
> > > Is there something I have missed?
> > >
> > >
> > >
> > > The error message, "Using 'P' as a concrete type conforming to protocol 'AnyObject' is not supported", implies that it is a temporary limitation of the compiler; is this going to be fixed? Should I lodge a bug report?
> > >
> > >
> > >
> > > Thanks in advance for any advice,
> > >
> > >
> > >
> > >
> > > -- Howard.
> > >
> > _______________________________________________
> > swift-users mailing list
> > swift-users@swift.org (javascript:_e(%7B%7D,'cvml','swift-users@swift.org'):wink:
> > https://lists.swift.org/mailman/listinfo/swift-users
> >
>
> Your problem is protocol self-conformance. In the first example, you’re creating WeakReference<CP>. CP conforms to P and to AnyObject. In the second example, you’re creating WeakReference<P>. P does not conform to P or to AnyObject.
>
>
>
> As for why @objc fixes it? … ¯\_(ツ)_/¯ all bets are off whenever @objc gets involved in anything.
>
>
>
> Karl
>
>
  
--
-- Howard.


(Jens Alfke) #6

<sidetrack>
…or if we were using some modern mailing list host like Google Groups or groups.io, that also offers a web view.
</sidetrack>

—Jens

···

On Sep 8, 2016, at 6:28 AM, Karl Wagner via swift-users <swift-users@swift.org> wrote:

It is in some sense a language limitation that we cant express what you're talking about. If we weren't using mailing lists it would be easier to search for "protocol self-conformance" on swift-evo and to read the earlier discussion about it.