Objects referenced by protocol type cannot be mutated
| Originator: | mark.adams86 | ||
| Number: | rdar://22413130 | Date Originated: | 8/24/2015 |
| Status: | Behaves correctly | Resolved: | 9/2/2015 |
| Product: | Developer Tools | Product Version: | Xcode 7.0 beta 6 (7A192o) |
| Classification: | Other Bug | Reproducible: | Always |
Summary:
Objects referenced abstractly by protocol cannot be mutated by changing var properties declared in the protocol. See the attached playground for an example of the issue.
The issue can be partially worked around by either:
1. Capturing the property into an explicit var temporary variable and modifying it. Results in a warning that "var was never mutated".
2. Making the protocol a 'class' protocol. Not ideal, but doable.
3. Referencing the objects by their concrete type instead of by the protocol they conform to.
Steps to Reproduce:
1. Declare a non-class protocol that has a variable property with a getter and setter.
2. Declare an object (class or struct, doesn't matter) that holds an array of objects, typed as an array of the protocol and not the concrete type.
3. Iterate over the collection with for/in syntax and attempt to mutate the object via the property declared in the protocol.
Expected Results:
Expected that the collection of objects would be mutated without raising an error.
Actual Results:
Received a compiler error. "Cannot assign to property: 'object' is a 'let' constant"
Version:
Xcode 7.0 beta 6 (7A192o)
OS X 10.10.5 (14F27)
Notes:
Configuration:
Occurs reliably in Xcode 7.0 beta 6 (7A192o) when compiling an iOS app written in Swift 2, against iOS 8.0 and 9.0.
Attachments:
'Playground.playground.zip' was successfully uploaded.
-----------
This issue behaves as intended based on the following:
This is correct behavior. Consider a case like this:
protocol P { var x: Int { get set } }
struct S: P { var x: Int }
class C: P { var x: Int }
func foo(p: P) { p.x += 1 }
foo(S(x: 1))
Since the protocol is not class-constrained, the protocol value ‘p’ may contain a struct. To mutate the property, it needs to be able to potentially mutate the value in-place, so it must be a ‘var’ or ‘inout’ binding.
Please update your bug report to let us know if this is still an issue for you.
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!