> On 10 Nov 2016, at 21:42, Jay Abbott <[email protected]> wrote:
> 
> Consider this code:
> 
> struct Pet {
>     let name: String
>     weak var owner: Person?
> 
>     init(name: String, owner: Person?) {
>         self.name = name
>         self.owner = owner
>         owner?.pet = self
>     }
> 
>     mutating func transferOwnership(to newOwner: Person) {
>         let previousOwner = owner
>         owner = newOwner
>         newOwner.pet = self
>         if(previousOwner != nil) {
>             previousOwner!.pet = nil
>         }
>     }
> 
>     func feed() {
>     }
> }
> 
> class Person {
>     let name: String
>     var pet: Pet?
> 
>     init(name: String) {
>         self.name = name
>     }
> 
>     func givePetAway(to someone: Person) {
>         if pet != nil {
>             pet!.transferOwnership(to: someone)
>             //pet!.feed()
>         }
>     }
> }
> 
> let bert = Person(name: "Bert")
> let ernie = Person(name: "Ernie")
> var elmo = Pet(name: "Elmo", owner: nil)
> 
> elmo.transferOwnership(to: bert)
> print("Bert's pet is \(bert.pet) - Ernie's pet is \(ernie.pet)")
> 
> bert.givePetAway(to: ernie)
> print("Bert's pet is \(bert.pet) - Ernie's pet is \(ernie.pet)")
> This works as expected, but if you uncomment pet!.feed() in givePetAway(to:) 
> it will crash, because the mutating function modifies the two-way 
> relationship between pet and owner.
> 
> In the code I use if pet != nil to demonstrate, in your proposal for unwrap, 
> if I used it to unwrap pet (a value-type, but accessed through self so it can 
> be modified after unwrapping because it’s not nil at the moment) the compiler 
> would assume I could use it and pet.feed() would crash, just as pet!.feed() 
> does now. In your proposal for type narrowing, it would be the same problem. 
> This is like your foo.value example from the proposal.
> 
> I don’t think you can get around the fact that the compiler can’t guarantee a 
> type-narrowed or even unwrapped mutable value, which is why if let works as 
> it does with an immutable snapshot.
> 
> However, type narrowing for immutable values would still be good.
> 

This isn't a problem of mutability, it's a problem due to the use of a 
reference type (Person); this is what the classes and concurrency section is 
supposed to be describing, but perhaps I haven't made it clear enough. So in 
the example you've given self.pet can't be unwrapped because self is a 
reference type, thus you need to either use force unwrapping either with the 
unwrap! keyword or direct force unwrapping like you've used (since behind the 
scenes it's the same thing).

You are right though that the resulting error isn't necessarily a concurrency 
issue, so I'll make a note of this for the proposed new error, and also clarify 
that the reference type restriction doesn't just apply to the property itself, 
but also to whatever it belongs to (and so-on up the chain, so if any part of 
foo.bar.a.b.c is a reference type it can't be soft unwrapped).
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to