[swift-evolution] Preserving non-mutability of methods of an existential or generic object

Hooman Mehr hooman at mac.com
Thu Dec 21 20:01:21 CST 2017


The title is confusing, let me clarify by example:

We have this protocol with a mutating method:

protocol P { mutating func f(_ x: Int) -> Int }

And a conforming class (which has to conform with a non-mutating method):

class C: P { func f(_ x: Int) -> Int { return x } }

An instance of this class can be used with a let constant:

let c = C()
c.f(1) // OK
 
If we make it an existential object conforming to P, the immutability of the method will be erased:

let c: AnyObject & P = C()
c.f(1) // Cannot use mutating member on immutable value: 'c' is a 'let' constant

A generic context has the same issue:

func f<T: AnyObject & P>(_ arg: T)-> Int { return arg.f(1) } // Cannot use mutating member on immutable value: ‘arg' is a 'let' constant

My question: 

Is it too much work to preserve method non-mutability in in these cases?

The workaround I am using is this:

protocol Q: class, P { func f(_ x: Int) -> Int } // 'Refine' it to be non-mutating.
extension C: Q {}

// Now these work:
let c: Q = C()
c.f(1) // OK
func f<T: Q>(_ arg: T)-> Int { return arg.f(1) } // OK

This workaround creates a lot of duplication and is hard to maintain. It is not something that I do often, but when I do, it is pretty annoying. 

Supplemental questions:

Have you guys ever ran into this?
Is there already a bug tracking this? 


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20171221/95dfcecc/attachment.html>


More information about the swift-evolution mailing list