Add something like [unowned self] syntax for passing instance methods into closure parameters without creating retain cycles


(Benjamin Spratling) #1

Nick, I like where you’re headed with the instance-methods-as-closures idea. Here’s where I’m headed with it:

Closures are too often used to write the contents of what should be another function, producing code similar to the “pyramid of doom” avoided by guard. I now generally write as little code as possible in a closure, and use it merely to dispatch out to a private function as quickly as possible. This means I really do want classes to reference their own functions. I look at closures more as providing the captured scope as the "void* context" that goes along with an old C function reference, as opposed to being the scope in which the code should be written.

I loved the “get a closure to implicit self using nothing but the function name” feature of Swift, but after running over a dead line by spending 1.5 days with 3 other developers trying to find a retain cycle caused by its use, we added it to our list of reasons to not merge code, hereafter referred to as “the list". This from a guy who used to write flawless manual retain/release code, back in the day.

Incidentally, we also put “unowned" on "the list". We always use “weak” instead. The bottom line is unowned CAN crash, and weak can’t. There is no way to know if a call to unowned will crash or not. So we prefer to write code that can’t crash. (No, we don’t force-unwrap weak optionals, “!” is on "the list”, and we nicknamed it the “Russian Roulette operator”) So instead of “something like [unowned self] syntax...”, I’m suggesting “something like [weak self] syntax..."

So I’d prefer something like “weakself?.functionName” to produce a closure which wraps a weak-self reference and a call to the given method if self isn’t nil. This seems like a trivial task for the compiler when return types are Void or Optional. Given the expectations of optional chaining, and the zeroing behavior of any not-owned relationship, I’m not sure it makes sense to demand a non-optional return type for a call to a parent. So I don’t think such a feature even needs to worry about what if the expected return type isn’t optional.

I’d be happy to see any of the following syntaxes:

weakself.functionName
weakself?.functionName
?functionName
welf.functionName
self?.functionName
weak(self)?.functionName

Obviously, one work around is to declare a protocol, and pass self, letting the receiving class store a weak reference. But declaring protocols for every single closure reference is a bit tedious. Literally just the back and forth on naming them is a waste of time. And there’s the running joke that we’d just tack “able” on the end of the method name.

Another work around is to create several generic classes which generate closures which weakly capture self and an unapplied method reference, and overloaded functions or operators to provide the correct class. Unfortunately, this still requires writing “self” explicitly, and also explicitly writing the type of self to obtain an unapplied method reference.

Given our experience, I would consider giving a warning when an implicit-self closure goes into an @escaping context.

  class SomeClass {
  var someFunction:(()->())?
  func setup() {
    prepare(closure: trigger) //this should probably be a warning
  }
  func prepare(closure:@escaping()->()) {
    someFunction = closure
  }
  func trigger() {
  }
  }

Self is already required when used inside an closure, for exactly this reason.
Perhaps we should require the developer to write explicit “self” or “self?” to indicate strong or weak capture of self.
  prepare(closure: self.trigger) //ok, strong self
  prepare(closure: self?.trigger) //ok, weak self
Or if they would like to use unowned,
  prepare(closure: RussianRoulette(self).trigger) // :wink:

In the end, however, closures do occasionally capture non-instance-property scope, which would need to be adapted in the wrapping closure around the call to another method, so the number of no-adapting-needed methods may be quite low. I expect given current priorities that this wouldn’t make it in to Swift 3.1. But given the severity of the consequences and the simplicity of the implementation, I would hope it would make it by Swift 4.

-Ben Spratling


(Karl) #2

Weak references can have a non-trivial amount of overhead in high-performance code. In some cases you can guarantee that a pointer should never be null - and that if it is, a serious logic error has occcurred and you *should* crash.
  
I prefer crashing to running in an inconsistent state. Who knows what can happen in the latter case - data corruption? I'd prefer to crash, get a report and fix the bug.
  
Karl
  
   This (https://itunes.apple.com/app/apple-store/id922793622?pt=814382&mt=8&ct=how_i_email) is how I Email now

···

  
On Sep 13, 2016 at 11:07 am, <Benjamin Spratling via swift-evolution (mailto:swift-evolution@swift.org)> wrote:
  
Nick, I like where you’re headed with the instance-methods-as-closures idea. Here’s where I’m headed with it:

Closures are too often used to write the contents of what should be another function, producing code similar to the “pyramid of doom” avoided by guard. I now generally write as little code as possible in a closure, and use it merely to dispatch out to a private function as quickly as possible. This means I really do want classes to reference their own functions. I look at closures more as providing the captured scope as the "void* context" that goes along with an old C function reference, as opposed to being the scope in which the code should be written.

I loved the “get a closure to implicit self using nothing but the function name” feature of Swift, but after running over a dead line by spending 1.5 days with 3 other developers trying to find a retain cycle caused by its use, we added it to our list of reasons to not merge code, hereafter referred to as “the list". This from a guy who used to write flawless manual retain/release code, back in the day.

Incidentally, we also put “unowned" on "the list". We always use “weak” instead. The bottom line is unowned CAN crash, and weak can’t. There is no way to know if a call to unowned will crash or not. So we prefer to write code that can’t crash. (No, we don’t force-unwrap weak optionals, “!” is on "the list”, and we nicknamed it the “Russian Roulette operator”) So instead of “something like [unowned self] syntax...”, I’m suggesting “something like [weak self] syntax..."

So I’d prefer something like “weakself?.functionName” to produce a closure which wraps a weak-self reference and a call to the given method if self isn’t nil. This seems like a trivial task for the compiler when return types are Void or Optional. Given the expectations of optional chaining, and the zeroing behavior of any not-owned relationship, I’m not sure it makes sense to demand a non-optional return type for a call to a parent. So I don’t think such a feature even needs to worry about what if the expected return type isn’t optional.

I’d be happy to see any of the following syntaxes:

weakself.functionName
weakself?.functionName
?functionName
welf.functionName
self?.functionName
weak(self)?.functionName

Obviously, one work around is to declare a protocol, and pass self, letting the receiving class store a weak reference. But declaring protocols for every single closure reference is a bit tedious. Literally just the back and forth on naming them is a waste of time. And there’s the running joke that we’d just tack “able” on the end of the method name.

Another work around is to create several generic classes which generate closures which weakly capture self and an unapplied method reference, and overloaded functions or operators to provide the correct class. Unfortunately, this still requires writing “self” explicitly, and also explicitly writing the type of self to obtain an unapplied method reference.

Given our experience, I would consider giving a warning when an implicit-self closure goes into an @escaping context.

class SomeClass {
var someFunction:(()->())?
func setup() {
prepare(closure: trigger) //this should probably be a warning
}
func prepare(closure:@escaping()->()) {
someFunction = closure
}
func trigger() {
}
}

Self is already required when used inside an closure, for exactly this reason.
Perhaps we should require the developer to write explicit “self” or “self?” to indicate strong or weak capture of self.
prepare(closure: self.trigger) //ok, strong self
prepare(closure: self?.trigger) //ok, weak self
Or if they would like to use unowned,
prepare(closure: RussianRoulette(self).trigger) // :wink:

In the end, however, closures do occasionally capture non-instance-property scope, which would need to be adapted in the wrapping closure around the call to another method, so the number of no-adapting-needed methods may be quite low. I expect given current priorities that this wouldn’t make it in to Swift 3.1. But given the severity of the consequences and the simplicity of the implementation, I would hope it would make it by Swift 4.

-Ben Spratling

_______________________________________________
swift-evolution mailing list (mailto:listswift-evolution@swift.orghttps)
swift-evolution@swift.org (mailto:listswift-evolution@swift.orghttps)
https (mailto:listswift-evolution@swift.orghttps)://lists.swift.org/mailman/listinfo/swift-evolution


(Kevin Nattinger) #3

Well, then also add an unowned convenience.
But I’ve never been handed a story from UX that said, “As a user, when ____ I want the app to crash.”
Using weak, the compiler can tell me when I’ve missed a possible case where it’s nil.

Honestly, I’d be fine with / prefer only allowing unowned (at all) if it’s @noescape, if that, requiring strong or weak for anything that escapes. That seems to go along with swift’s emphasis on safety.

···

On Sep 13, 2016, at 10:29 AM, Benjamin Spratling via swift-evolution <swift-evolution@swift.org> wrote:

But the point here is to get closure references that don’t create retain cycles. Obviously, there’s desire for both weak and unowned variants without the syntactic overhead of a full closure.

On Sep 13, 2016, at 12:22 PM, Karl Wagner <razielim@gmail.com <mailto:razielim@gmail.com>> wrote:

Weak references can have a non-trivial amount of overhead in high-performance code. In some cases you can guarantee that a pointer should never be null - and that if it is, a serious logic error has occcurred and you *should* crash.

I prefer crashing to running in an inconsistent state. Who knows what can happen in the latter case - data corruption? I'd prefer to crash, get a report and fix the bug.

Karl

This <https://itunes.apple.com/app/apple-store/id922793622?pt=814382&mt=8&ct=how_i_email> is how I Email now

On Sep 13, 2016 at 11:07 am, <Benjamin Spratling via swift-evolution <mailto:swift-evolution@swift.org>> wrote:

Nick, I like where you’re headed with the instance-methods-as-closures idea. Here’s where I’m headed with it:

Closures are too often used to write the contents of what should be another function, producing code similar to the “pyramid of doom” avoided by guard. I now generally write as little code as possible in a closure, and use it merely to dispatch out to a private function as quickly as possible. This means I really do want classes to reference their own functions. I look at closures more as providing the captured scope as the "void* context" that goes along with an old C function reference, as opposed to being the scope in which the code should be written.

I loved the “get a closure to implicit self using nothing but the function name” feature of Swift, but after running over a dead line by spending 1.5 days with 3 other developers trying to find a retain cycle caused by its use, we added it to our list of reasons to not merge code, hereafter referred to as “the list". This from a guy who used to write flawless manual retain/release code, back in the day.

Incidentally, we also put “unowned" on "the list". We always use “weak” instead. The bottom line is unowned CAN crash, and weak can’t. There is no way to know if a call to unowned will crash or not. So we prefer to write code that can’t crash. (No, we don’t force-unwrap weak optionals, “!” is on "the list”, and we nicknamed it the “Russian Roulette operator”) So instead of “something like [unowned self] syntax...”, I’m suggesting “something like [weak self] syntax..."

So I’d prefer something like “weakself?.functionName” to produce a closure which wraps a weak-self reference and a call to the given method if self isn’t nil. This seems like a trivial task for the compiler when return types are Void or Optional. Given the expectations of optional chaining, and the zeroing behavior of any not-owned relationship, I’m not sure it makes sense to demand a non-optional return type for a call to a parent. So I don’t think such a feature even needs to worry about what if the expected return type isn’t optional.

I’d be happy to see any of the following syntaxes:

weakself.functionName
weakself?.functionName
?functionName
welf.functionName
self?.functionName
weak(self)?.functionName

Obviously, one work around is to declare a protocol, and pass self, letting the receiving class store a weak reference. But declaring protocols for every single closure reference is a bit tedious. Literally just the back and forth on naming them is a waste of time. And there’s the running joke that we’d just tack “able” on the end of the method name.

Another work around is to create several generic classes which generate closures which weakly capture self and an unapplied method reference, and overloaded functions or operators to provide the correct class. Unfortunately, this still requires writing “self” explicitly, and also explicitly writing the type of self to obtain an unapplied method reference.

Given our experience, I would consider giving a warning when an implicit-self closure goes into an @escaping context.

  class SomeClass {
  var someFunction:(()->())?
  func setup() {
    prepare(closure: trigger) //this should probably be a warning
  }
  func prepare(closure:@escaping()->()) {
    someFunction = closure
  }
  func trigger() {
  }
  }

Self is already required when used inside an closure, for exactly this reason.
Perhaps we should require the developer to write explicit “self” or “self?” to indicate strong or weak capture of self.
  prepare(closure: self.trigger) //ok, strong self
  prepare(closure: self?.trigger) //ok, weak self
Or if they would like to use unowned,
  prepare(closure: RussianRoulette(self).trigger) // :wink:

In the end, however, closures do occasionally capture non-instance-property scope, which would need to be adapted in the wrapping closure around the call to another method, so the number of no-adapting-needed methods may be quite low. I expect given current priorities that this wouldn’t make it in to Swift 3.1. But given the severity of the consequences and the simplicity of the implementation, I would hope it would make it by Swift 4.

-Ben Spratling

_______________________________________________
swift-evolution mailing list <mailto:listswift-evolution@swift.orghttps>
swift-evolution@swift.org <mailto:listswift-evolution@swift.orghttps>
https <mailto:listswift-evolution@swift.orghttps>://lists.swift.org/mailman/listinfo/swift-evolution <http://lists.swift.org/mailman/listinfo/swift-evolution>

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


(Benjamin Spratling) #4

Well, then also add an unowned convenience.
But I’ve never been handed a story from UX that said, “As a user, when ____ I want the app to crash.”
Using weak, the compiler can tell me when I’ve missed a possible case where it’s nil.
But the point here is to get closure references that don’t create retain cycles. Obviously, there’s desire for both weak and unowned variants without the syntactic overhead of a full closure.

···

On Sep 13, 2016, at 12:22 PM, Karl Wagner <razielim@gmail.com> wrote:

Weak references can have a non-trivial amount of overhead in high-performance code. In some cases you can guarantee that a pointer should never be null - and that if it is, a serious logic error has occcurred and you *should* crash.

I prefer crashing to running in an inconsistent state. Who knows what can happen in the latter case - data corruption? I'd prefer to crash, get a report and fix the bug.

Karl

This <https://itunes.apple.com/app/apple-store/id922793622?pt=814382&mt=8&ct=how_i_email> is how I Email now

On Sep 13, 2016 at 11:07 am, <Benjamin Spratling via swift-evolution <mailto:swift-evolution@swift.org>> wrote:

Nick, I like where you’re headed with the instance-methods-as-closures idea. Here’s where I’m headed with it:

Closures are too often used to write the contents of what should be another function, producing code similar to the “pyramid of doom” avoided by guard. I now generally write as little code as possible in a closure, and use it merely to dispatch out to a private function as quickly as possible. This means I really do want classes to reference their own functions. I look at closures more as providing the captured scope as the "void* context" that goes along with an old C function reference, as opposed to being the scope in which the code should be written.

I loved the “get a closure to implicit self using nothing but the function name” feature of Swift, but after running over a dead line by spending 1.5 days with 3 other developers trying to find a retain cycle caused by its use, we added it to our list of reasons to not merge code, hereafter referred to as “the list". This from a guy who used to write flawless manual retain/release code, back in the day.

Incidentally, we also put “unowned" on "the list". We always use “weak” instead. The bottom line is unowned CAN crash, and weak can’t. There is no way to know if a call to unowned will crash or not. So we prefer to write code that can’t crash. (No, we don’t force-unwrap weak optionals, “!” is on "the list”, and we nicknamed it the “Russian Roulette operator”) So instead of “something like [unowned self] syntax...”, I’m suggesting “something like [weak self] syntax..."

So I’d prefer something like “weakself?.functionName” to produce a closure which wraps a weak-self reference and a call to the given method if self isn’t nil. This seems like a trivial task for the compiler when return types are Void or Optional. Given the expectations of optional chaining, and the zeroing behavior of any not-owned relationship, I’m not sure it makes sense to demand a non-optional return type for a call to a parent. So I don’t think such a feature even needs to worry about what if the expected return type isn’t optional.

I’d be happy to see any of the following syntaxes:

weakself.functionName
weakself?.functionName
?functionName
welf.functionName
self?.functionName
weak(self)?.functionName

Obviously, one work around is to declare a protocol, and pass self, letting the receiving class store a weak reference. But declaring protocols for every single closure reference is a bit tedious. Literally just the back and forth on naming them is a waste of time. And there’s the running joke that we’d just tack “able” on the end of the method name.

Another work around is to create several generic classes which generate closures which weakly capture self and an unapplied method reference, and overloaded functions or operators to provide the correct class. Unfortunately, this still requires writing “self” explicitly, and also explicitly writing the type of self to obtain an unapplied method reference.

Given our experience, I would consider giving a warning when an implicit-self closure goes into an @escaping context.

  class SomeClass {
  var someFunction:(()->())?
  func setup() {
    prepare(closure: trigger) //this should probably be a warning
  }
  func prepare(closure:@escaping()->()) {
    someFunction = closure
  }
  func trigger() {
  }
  }

Self is already required when used inside an closure, for exactly this reason.
Perhaps we should require the developer to write explicit “self” or “self?” to indicate strong or weak capture of self.
  prepare(closure: self.trigger) //ok, strong self
  prepare(closure: self?.trigger) //ok, weak self
Or if they would like to use unowned,
  prepare(closure: RussianRoulette(self).trigger) // :wink:

In the end, however, closures do occasionally capture non-instance-property scope, which would need to be adapted in the wrapping closure around the call to another method, so the number of no-adapting-needed methods may be quite low. I expect given current priorities that this wouldn’t make it in to Swift 3.1. But given the severity of the consequences and the simplicity of the implementation, I would hope it would make it by Swift 4.

-Ben Spratling

_______________________________________________
swift-evolution mailing list <mailto:listswift-evolution@swift.orghttps>
swift-evolution@swift.org <mailto:listswift-evolution@swift.orghttps>
https <mailto:listswift-evolution@swift.orghttps>://lists.swift.org/mailman/listinfo/swift-evolution


(Benjamin Spratling) #5

Going along with the "self." / "self?." from my previous message, perhaps "self!." For unowned?

That said, if there were only an unowned convenience, I would not use it. I'm not going to have that debate here, since I think the value of "weak" is obvious to most developers.

···

Sent from my iPad

On Sep 13, 2016, at 12:38 PM, Kevin Nattinger <swift@nattinger.net> wrote:

On Sep 13, 2016, at 10:29 AM, Benjamin Spratling via swift-evolution <swift-evolution@swift.org> wrote:

Well, then also add an unowned convenience.
But I’ve never been handed a story from UX that said, “As a user, when ____ I want the app to crash.”
Using weak, the compiler can tell me when I’ve missed a possible case where it’s nil.

Honestly, I’d be fine with / prefer only allowing unowned (at all) if it’s @noescape, if that, requiring strong or weak for anything that escapes. That seems to go along with swift’s emphasis on safety.

But the point here is to get closure references that don’t create retain cycles. Obviously, there’s desire for both weak and unowned variants without the syntactic overhead of a full closure.

On Sep 13, 2016, at 12:22 PM, Karl Wagner <razielim@gmail.com> wrote:

Weak references can have a non-trivial amount of overhead in high-performance code. In some cases you can guarantee that a pointer should never be null - and that if it is, a serious logic error has occcurred and you *should* crash.

I prefer crashing to running in an inconsistent state. Who knows what can happen in the latter case - data corruption? I'd prefer to crash, get a report and fix the bug.

Karl

This is how I Email now

On Sep 13, 2016 at 11:07 am, <Benjamin Spratling via swift-evolution> wrote:

Nick, I like where you’re headed with the instance-methods-as-closures idea. Here’s where I’m headed with it:

Closures are too often used to write the contents of what should be another function, producing code similar to the “pyramid of doom” avoided by guard. I now generally write as little code as possible in a closure, and use it merely to dispatch out to a private function as quickly as possible. This means I really do want classes to reference their own functions. I look at closures more as providing the captured scope as the "void* context" that goes along with an old C function reference, as opposed to being the scope in which the code should be written.

I loved the “get a closure to implicit self using nothing but the function name” feature of Swift, but after running over a dead line by spending 1.5 days with 3 other developers trying to find a retain cycle caused by its use, we added it to our list of reasons to not merge code, hereafter referred to as “the list". This from a guy who used to write flawless manual retain/release code, back in the day.

Incidentally, we also put “unowned" on "the list". We always use “weak” instead. The bottom line is unowned CAN crash, and weak can’t. There is no way to know if a call to unowned will crash or not. So we prefer to write code that can’t crash. (No, we don’t force-unwrap weak optionals, “!” is on "the list”, and we nicknamed it the “Russian Roulette operator”) So instead of “something like [unowned self] syntax...”, I’m suggesting “something like [weak self] syntax..."

So I’d prefer something like “weakself?.functionName” to produce a closure which wraps a weak-self reference and a call to the given method if self isn’t nil. This seems like a trivial task for the compiler when return types are Void or Optional. Given the expectations of optional chaining, and the zeroing behavior of any not-owned relationship, I’m not sure it makes sense to demand a non-optional return type for a call to a parent. So I don’t think such a feature even needs to worry about what if the expected return type isn’t optional.

I’d be happy to see any of the following syntaxes:

weakself.functionName
weakself?.functionName
?functionName
welf.functionName
self?.functionName
weak(self)?.functionName

Obviously, one work around is to declare a protocol, and pass self, letting the receiving class store a weak reference. But declaring protocols for every single closure reference is a bit tedious. Literally just the back and forth on naming them is a waste of time. And there’s the running joke that we’d just tack “able” on the end of the method name.

Another work around is to create several generic classes which generate closures which weakly capture self and an unapplied method reference, and overloaded functions or operators to provide the correct class. Unfortunately, this still requires writing “self” explicitly, and also explicitly writing the type of self to obtain an unapplied method reference.

Given our experience, I would consider giving a warning when an implicit-self closure goes into an @escaping context.

  class SomeClass {
  var someFunction:(()->())?
  func setup() {
    prepare(closure: trigger) //this should probably be a warning
  }
  func prepare(closure:@escaping()->()) {
    someFunction = closure
  }
  func trigger() {
  }
  }

Self is already required when used inside an closure, for exactly this reason.
Perhaps we should require the developer to write explicit “self” or “self?” to indicate strong or weak capture of self.
  prepare(closure: self.trigger) //ok, strong self
  prepare(closure: self?.trigger) //ok, weak self
Or if they would like to use unowned,
  prepare(closure: RussianRoulette(self).trigger) // :wink:

In the end, however, closures do occasionally capture non-instance-property scope, which would need to be adapted in the wrapping closure around the call to another method, so the number of no-adapting-needed methods may be quite low. I expect given current priorities that this wouldn’t make it in to Swift 3.1. But given the severity of the consequences and the simplicity of the implementation, I would hope it would make it by Swift 4.

-Ben Spratling

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

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


(Karl) #6

Honestly, I’d be fine with / prefer only allowing unowned (at all) if it’s @noescape, if that, requiring strong or weak for anything that escapes. That seems to go along with swift’s emphasis on safety.

What?!?!! That's an extraordinary thing to say.
I don't think you understand what autozeroing weak references are for. They are not there so that you can have gaps in your reasoning of your code, or to allow undefined behaviour. They exist so that you can have a non-retaining pointer (I.e. Unowned), where the pointee's lifetime is independent of the reference. So when the pointee does deallocate at some unknown time, the pointer reverts to nil doesn't just dangle in to invalid memory.
Let's say I have some reusable functionality, like an input handler for text-processing events with a particular behaviour (maybe it does some validation or something, it's not important). I can encapsulate that as a class (maybe it can't be a struct, that's my business. Maybe it has specialised subclasses or requires identity). Now I have my UIViewController, I create and retain an instance of that class, but the object needs to dispatch events back to the UIVC so it needs a non-strong pointer to its parent.
The parent and child have coupled lifetimes. There will never be an orphaned child; and if there is, and it's handling events and dispatching them nowhere, that's a serious flaw in the application logic. Of course users don't want applications to crash, but developers do! When there are failures in the application logic, I want them to be loud and obvious. Otherwise, we might as well remove all preconditions as other runtime assertions as well.
Some of the comments here about unowned references are scary; you should always understand your application logic, and use of unowned pointers is completely safe if you do. If you're using weak references as a shorthand for a lack of understanding of your own code, you have a bigger problem than an esoteric crashing bug.
It's similar to Linus' argument against using kernel debuggers (https://lwn.net/2000/0914/a/lt-debugger.php3). Understanding your code at a level above the source, and being careful, make you a better developer. There are no features in swift which compensate for a lack of understanding about how your code works.


(Rick M) #7

Get off my lawn!

···

On Sep 13, 2016, at 22:34 , Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

It's similar to Linus' argument against using kernel debuggers (https://lwn.net/2000/0914/a/lt-debugger.php3). Understanding your code at a level above the source, and being careful, make you a better developer. There are no features in swift which compensate for a lack of understanding about how your code works.

--
Rick Mann
rmann@latencyzero.com


(Xiaodi Wu) #8

> Honestly, I’d be fine with / prefer only allowing unowned (at all) if
it’s @noescape, if that, requiring strong or weak for anything that
escapes. That seems to go along with swift’s emphasis on safety.

What?!?!! That's an extraordinary thing to say.

I don't think you understand what autozeroing weak references are for.
They are *not* there so that you can have gaps in your reasoning of your
code, or to allow undefined behaviour. They exist so that you can have a
non-retaining pointer (I.e. Unowned), where the pointee's lifetime is
independent of the reference. So when the pointee does deallocate at some
unknown time, the pointer reverts to nil doesn't just dangle in to invalid
memory.

Let's say I have some reusable functionality, like an input handler for
text-processing events with a particular behaviour (maybe it does some
validation or something, it's not important). I can encapsulate that as a
class (maybe it can't be a struct, that's my business. Maybe it has
specialised subclasses or requires identity). Now I have my
UIViewController, I create and retain an instance of that class, but the
object needs to dispatch events back to the UIVC so it needs a non-strong
pointer to its parent.

The parent and child have coupled lifetimes. There will never be an
orphaned child; and if there is, and it's handling events and dispatching
them nowhere, that's a serious flaw in the application logic. Of course
users don't want applications to crash, but developers do! When there are
failures in the application logic, I want them to be loud and obvious.
Otherwise, we might as well remove all preconditions as other runtime
assertions as well.

Some of the comments here about unowned references are scary; you should
always understand your application logic, and use of unowned pointers is
completely safe if you do. If you're using weak references as a shorthand
for a lack of understanding of your own code, you have a bigger problem
than an esoteric crashing bug.

It's similar to Linus' argument against using kernel debuggers (
https://lwn.net/2000/0914/a/lt-debugger.php3). Understanding your code at
a level above the source, and being careful, make you a better developer.
There are no features in swift which compensate for a lack of understanding
about how your code works.

That's a great explanation. I wish I had more time so that I could search
for posts from core team members that can elaborate on this point much
better than I could. But the gist of it, as I understand it, is that
trapping is safe, while proceeding despite an unexpected flaw in memory
handling is unsafe, and Swift chooses safety. This is part of the reasoning
behind why, for instance, "lenient" array indexing is on the
commonly-rejected proposals list.

···

On Tue, Sep 13, 2016 at 10:29 PM, Karl Wagner via swift-evolution < swift-evolution@swift.org> wrote:

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


(Karl) #9

Sorry to hijack the thread, but I was working to fix the fact that we can't have optional unowned pointers in swift and Jordan said he didn't think anybody ever asked for it before. It made me worry about the kind of practices swift is encouraging.

The overhead of using weak pointers isn't massive, but it involves locking and updating global tables (http://stackoverflow.com/questions/23689155/lots-of-overhead-for-weak-property). Unowned pointers don't have this overhead, and can also help you detect errors because they are fail-deadly.

But yeah, I'd like to be able to reference non-owning instance methods.

   This (https://itunes.apple.com/app/apple-store/id922793622?pt=814382&mt=8&ct=how_i_email) is how I Email now

···

On Sep 14, 2016 at 7:45 am, <Rick Mann (mailto:rmann@latencyzero.com)> wrote:

> On Sep 13, 2016, at 22:34 , Xiaodi Wu via swift-evolution <swift-evolution@swift.org (mailto:swift-evolution@swift.org)> wrote:
>
> It's similar to Linus' argument against using kernel debuggers (https://lwn.net/2000/0914/a/lt-debugger.php3). Understanding your code at a level above the source, and being careful, make you a better developer. There are no features in swift which compensate for a lack of understanding about how your code works.

Get off my lawn!

--
Rick Mann
rmann@latencyzero.com (mailto:rmann@latencyzero.com)


(Callionica (Swift)) #10

How do you figure unowned pointers help you detect errors? Dangling
pointers give you no guarantees.

···

On Wednesday, September 14, 2016, Karl Wagner via swift-evolution < swift-evolution@swift.org> wrote:

Sorry to hijack the thread, but I was working to fix the fact that we
can't have optional unowned pointers in swift and Jordan said he didn't
think anybody ever asked for it before. It made me worry about the kind of
practices swift is encouraging.

The overhead of using weak pointers isn't massive, but it involves locking
and updating global tables (http://stackoverflow.com/
questions/23689155/lots-of-overhead-for-weak-property). Unowned pointers
don't have this overhead, and can also help you detect errors because they
are fail-deadly.

But yeah, I'd like to be able to reference non-owning instance methods.

This
<https://itunes.apple.com/app/apple-store/id922793622?pt=814382&mt=8&ct=how_i_email>
is how I Email now

On Sep 14, 2016 at 7:45 am, <Rick Mann > <javascript:_e(%7B%7D,'cvml','rmann@latencyzero.com');>> wrote:

> On Sep 13, 2016, at 22:34 , Xiaodi Wu via swift-evolution <swift-evolution@swift.org <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:
>
> It's similar to Linus' argument against using kernel debuggers (https://lwn.net/2000/0914/a/lt-debugger.php3). Understanding your code at a level above the source, and being careful, make you a better developer. There are no features in swift which compensate for a lack of understanding about how your code works.

Get off my lawn!

--
Rick Mann
rmann@latencyzero.com <javascript:_e(%7B%7D,'cvml','rmann@latencyzero.com');>


(Jordan Rose) #11

Unowned pointers aren't dangling in debug builds; they're more like zombie-detection, where you get a deterministic trap if you access them after the original instance is strong-released for the last time. I can't remember if this is enabled in release builds as well; under -Ounchecked they do become unsafe-unretained.

Jordan

···

On Sep 14, 2016, at 10:51, Callionica (Swift) via swift-evolution <swift-evolution@swift.org> wrote:

How do you figure unowned pointers help you detect errors? Dangling pointers give you no guarantees.

On Wednesday, September 14, 2016, Karl Wagner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Sorry to hijack the thread, but I was working to fix the fact that we can't have optional unowned pointers in swift and Jordan said he didn't think anybody ever asked for it before. It made me worry about the kind of practices swift is encouraging.

The overhead of using weak pointers isn't massive, but it involves locking and updating global tables (http://stackoverflow.com/questions/23689155/lots-of-overhead-for-weak-property). Unowned pointers don't have this overhead, and can also help you detect errors because they are fail-deadly.

But yeah, I'd like to be able to reference non-owning instance methods.

This <https://itunes.apple.com/app/apple-store/id922793622?pt=814382&mt=8&ct=how_i_email> is how I Email now

On Sep 14, 2016 at 7:45 am, <Rick Mann <javascript:_e(%7B%7D,'cvml','rmann@latencyzero.com');>> wrote:

> On Sep 13, 2016, at 22:34 , Xiaodi Wu via swift-evolution <swift-evolution@swift.org <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:

>

> It's similar to Linus' argument against using kernel debuggers (https://lwn.net/2000/0914/a/lt-debugger.php3). Understanding your code at a level above the source, and being careful, make you a better developer. There are no features in swift which compensate for a lack of understanding about how your code works.

Get off my lawn!

--

Rick Mann

rmann@latencyzero.com <javascript:_e(%7B%7D,'cvml','rmann@latencyzero.com');>

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


(Callionica (Swift)) #12

Oh. That's great. Very useful. Thanks for the info.

···

On Thursday, September 15, 2016, Jordan Rose <jordan_rose@apple.com> wrote:

Unowned pointers aren't dangling in debug builds; they're more like
zombie-detection, where you get a deterministic trap if you access them
after the original instance is strong-released for the last time. I can't
remember if this is enabled in release builds as well; under -Ounchecked
they do become unsafe-unretained.

Jordan

On Sep 14, 2016, at 10:51, Callionica (Swift) via swift-evolution < > swift-evolution@swift.org > <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:

How do you figure unowned pointers help you detect errors? Dangling
pointers give you no guarantees.

On Wednesday, September 14, 2016, Karl Wagner via swift-evolution < > swift-evolution@swift.org > <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:

Sorry to hijack the thread, but I was working to fix the fact that we
can't have optional unowned pointers in swift and Jordan said he didn't
think anybody ever asked for it before. It made me worry about the kind of
practices swift is encouraging.

The overhead of using weak pointers isn't massive, but it involves
locking and updating global tables (http://stackoverflow.com/ques
tions/23689155/lots-of-overhead-for-weak-property). Unowned pointers
don't have this overhead, and can also help you detect errors because they
are fail-deadly.

But yeah, I'd like to be able to reference non-owning instance methods.

This
<https://itunes.apple.com/app/apple-store/id922793622?pt=814382&mt=8&ct=how_i_email>
is how I Email now

On Sep 14, 2016 at 7:45 am, <Rick Mann> wrote:

> On Sep 13, 2016, at 22:34 , Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:
>
> It's similar to Linus' argument against using kernel debuggers (https://lwn.net/2000/0914/a/lt-debugger.php3). Understanding your code at a level above the source, and being careful, make you a better developer. There are no features in swift which compensate for a lack of understanding about how your code works.

Get off my lawn!

--
Rick Mann
rmann@latencyzero.com

_______________________________________________

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