[swift-evolution] [Draft] @selfsafe: a new way to avoid reference cycles

David Hart david at hartbit.com
Sun Feb 19 07:41:44 CST 2017


I must admit I find this proposal very weird.

• it only handles strong references to self. While the APIs we work with mostly direct us towards accidental references cycles including self in closures, I would want a compiler feature to be much more generic.
• I'm not a fan of "magically" fixing reference cycles in certain APIs. It creates special cases, inconsistencies this will create will make it that much worse for newcomers to understand reference cycles and for advanced users to reasons about reference cycles (always having to check the API to check if it handles this special magic).

On 19 Feb 2017, at 09:15, Brent Royal-Gordon via swift-evolution <swift-evolution at swift.org> wrote:

>> On Feb 18, 2017, at 5:24 PM, Matthew Johnson via swift-evolution <swift-evolution at swift.org> wrote:
>> 
>> This proposal introduces the `@selfsafe` function argument attribute which together with a `withWeakSelf` property on values of function type.  Together these features enable library authors to create APIs can be statically verified to never extend the lifetime of the `self` a function they take may have captured.
> 
> Both of these mechanisms are weirdly ad hoc. They involve the callee assuming things about the caller that are not necessarily correct—in particular, that the caller's `self` is going to, directly or indirectly, hold a strong reference to the callee's `self`.
> 
> For instance, suppose you've read too many design pattern books, and you're using the Command Pattern:
> 
>    class DeleteRecordCommand: Command {
>        let record: Record
>        
>        func execute(with viewController: RecordViewController) {
>            let alert = UIAlertController(title: "Really delete?", preferredStyle: .alert)
>            
>            alert.addAction(UIAlertAction(title: "Delete", style: .destructive) { _ in
>                self.record.delete()
>                viewController.performSegue(withIdentifier: "Cancel", sender: self)
>            })
>            alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
>            
>            viewController.present(alert)
>        }
>    }
> 
> Now, imagine that the `UIAlertAction` initializer used `@selfsafe`, hoping to prevent incorrect use of `self`. Well, that would be totally wrong in this case—it would weaken `self`, which *needs* to be strong, and leave `viewController` strong, when it's creating a retain cycle. `@selfsafe` didn't prevent a bug—it introduced another one, without any visible sign of it in the code.
> 
> *The problem is not `self`.* The problem is that you need to pay attention to memory management in Swift. And that's a tradeoff that's baked into the language.
> 
> -- 
> Brent Royal-Gordon
> Architechies
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution



More information about the swift-evolution mailing list