Swift 2.2: Removing partial application of super method calls


(David Farler) #1

Hi all,

I'd like to propose removing partial application of super method calls (except bare `super.foo` which implicitly captures `self`) in Swift 2.2.

This is motivated by the upcoming removal of curried function declaration syntax in Swift 3 combined with making super method calls dynamically dispatched instead of statically dispatched as they are now, which is scheduled to land in Swift 2.2.

The reason why dynamic dispatch is a motivator is mostly driven by implementation details, specifically how we emit partial application thunks. These thunks ultimately result in a static function reference, which is called immediately, or a dynamic dispatch through a class method. Now, you might be wondering how class methods differ from dynamic dispatch via super methods. Class methods use dynamic dispatch through the instance pointer to the class metadata for the vtable lookup, whereas super method dynamic dispatch loads the statically known superclass's metadata instead.

The logic around curry thunk emission is rather complicated so I'd like to go ahead and make partial applications based in `super` disallowed, rather than invest time in an area we'll be ripping up in Swift 3 and increase risk for regressions in Swift 2.2.

The implementation for disallowing this is dead simple and I've already got a patch for that. I should also mention that I can't safely turn on the new dynamic super method dispatch mechanics in Swift 2.2 until we address this one way or the other. I do have progress on emitting curry thunks for these kinds of partial applications but it is a rather large patch that I'd like to avoid for Swift 2.2 if possible.

David


(David Farler) #2

I'd like to add that this would only apply to super invocation of non-final methods. Final methods always terminate with a static function reference, so the existing curry thunk mechanisms will continue to work with those until we remove them.

David

···

On Dec 7, 2015, at 1:51 PM, David Farler <dfarler@apple.com> wrote:

Hi all,

I'd like to propose removing partial application of super method calls (except bare `super.foo` which implicitly captures `self`) in Swift 2.2.

This is motivated by the upcoming removal of curried function declaration syntax in Swift 3 combined with making super method calls dynamically dispatched instead of statically dispatched as they are now, which is scheduled to land in Swift 2.2.

The reason why dynamic dispatch is a motivator is mostly driven by implementation details, specifically how we emit partial application thunks. These thunks ultimately result in a static function reference, which is called immediately, or a dynamic dispatch through a class method. Now, you might be wondering how class methods differ from dynamic dispatch via super methods. Class methods use dynamic dispatch through the instance pointer to the class metadata for the vtable lookup, whereas super method dynamic dispatch loads the statically known superclass's metadata instead.

The logic around curry thunk emission is rather complicated so I'd like to go ahead and make partial applications based in `super` disallowed, rather than invest time in an area we'll be ripping up in Swift 3 and increase risk for regressions in Swift 2.2.

The implementation for disallowing this is dead simple and I've already got a patch for that. I should also mention that I can't safely turn on the new dynamic super method dispatch mechanics in Swift 2.2 until we address this one way or the other. I do have progress on emitting curry thunks for these kinds of partial applications but it is a rather large patch that I'd like to avoid for Swift 2.2 if possible.

David


(David Farler) #3

Here's a draft of the proposal:

https://github.com/bitjammer/swift-evolution/blob/remove-partial-super/proposals/0008-remove-partial-application-super.md

David

···

On Dec 7, 2015, at 3:37 PM, David Farler <dfarler@apple.com> wrote:

I'd like to add that this would only apply to super invocation of non-final methods. Final methods always terminate with a static function reference, so the existing curry thunk mechanisms will continue to work with those until we remove them.

David

On Dec 7, 2015, at 1:51 PM, David Farler <dfarler@apple.com> wrote:

Hi all,

I'd like to propose removing partial application of super method calls (except bare `super.foo` which implicitly captures `self`) in Swift 2.2.

This is motivated by the upcoming removal of curried function declaration syntax in Swift 3 combined with making super method calls dynamically dispatched instead of statically dispatched as they are now, which is scheduled to land in Swift 2.2.

The reason why dynamic dispatch is a motivator is mostly driven by implementation details, specifically how we emit partial application thunks. These thunks ultimately result in a static function reference, which is called immediately, or a dynamic dispatch through a class method. Now, you might be wondering how class methods differ from dynamic dispatch via super methods. Class methods use dynamic dispatch through the instance pointer to the class metadata for the vtable lookup, whereas super method dynamic dispatch loads the statically known superclass's metadata instead.

The logic around curry thunk emission is rather complicated so I'd like to go ahead and make partial applications based in `super` disallowed, rather than invest time in an area we'll be ripping up in Swift 3 and increase risk for regressions in Swift 2.2.

The implementation for disallowing this is dead simple and I've already got a patch for that. I should also mention that I can't safely turn on the new dynamic super method dispatch mechanics in Swift 2.2 until we address this one way or the other. I do have progress on emitting curry thunks for these kinds of partial applications but it is a rather large patch that I'd like to avoid for Swift 2.2 if possible.

David


(Chris Lattner) #4

Here's a draft of the proposal:

https://github.com/bitjammer/swift-evolution/blob/remove-partial-super/proposals/0008-remove-partial-application-super.md

Hi David,

Sorry for the delay, things have been busy lately :-)

" Currying will be removed in Swift 3.0 so, rather than invest more engineering in those mechanisms, I propose that we disallow partial application of non-final methods through super, except where the self parameter is implicitly captured.”

This isn’t true. The proposal you’re referring to removes the “func f(a : Int)(b : Int)” syntax, but methods will still be curried. It will still be perfectly legal to do:

class Foo {
  func bar() {}
}

let fn = Foo.bar
fn()

So, I think that in a perfect world, the implementation would lazily generate curry thunks for super partial applications, and we would keep the current behavior. However, if it is a significant implementation burden, I’d support doing a survey of existing code to see how widely used this is. I suspect it is rare, and if you can prove this, we may be able to knowingly break compatibility in this case in the service of getting the ABI stability.

-Chris

···

On Dec 9, 2015, at 5:46 PM, David Farler via swift-evolution <swift-evolution@swift.org> wrote:

David

On Dec 7, 2015, at 3:37 PM, David Farler <dfarler@apple.com <mailto:dfarler@apple.com>> wrote:

I'd like to add that this would only apply to super invocation of non-final methods. Final methods always terminate with a static function reference, so the existing curry thunk mechanisms will continue to work with those until we remove them.

David

On Dec 7, 2015, at 1:51 PM, David Farler <dfarler@apple.com <mailto:dfarler@apple.com>> wrote:

Hi all,

I'd like to propose removing partial application of super method calls (except bare `super.foo` which implicitly captures `self`) in Swift 2.2.

This is motivated by the upcoming removal of curried function declaration syntax in Swift 3 combined with making super method calls dynamically dispatched instead of statically dispatched as they are now, which is scheduled to land in Swift 2.2.

The reason why dynamic dispatch is a motivator is mostly driven by implementation details, specifically how we emit partial application thunks. These thunks ultimately result in a static function reference, which is called immediately, or a dynamic dispatch through a class method. Now, you might be wondering how class methods differ from dynamic dispatch via super methods. Class methods use dynamic dispatch through the instance pointer to the class metadata for the vtable lookup, whereas super method dynamic dispatch loads the statically known superclass's metadata instead.

The logic around curry thunk emission is rather complicated so I'd like to go ahead and make partial applications based in `super` disallowed, rather than invest time in an area we'll be ripping up in Swift 3 and increase risk for regressions in Swift 2.2.

The implementation for disallowing this is dead simple and I've already got a patch for that. I should also mention that I can't safely turn on the new dynamic super method dispatch mechanics in Swift 2.2 until we address this one way or the other. I do have progress on emitting curry thunks for these kinds of partial applications but it is a rather large patch that I'd like to avoid for Swift 2.2 if possible.

David

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


(Chris Lattner) #5

Here's a draft of the proposal:

https://github.com/bitjammer/swift-evolution/blob/remove-partial-super/proposals/0008-remove-partial-application-super.md

Hi David,

Sorry for the delay, things have been busy lately :-)

" Currying will be removed in Swift 3.0 so, rather than invest more engineering in those mechanisms, I propose that we disallow partial application of non-final methods through super, except where the self parameter is implicitly captured.”

This isn’t true. The proposal you’re referring to removes the “func f(a : Int)(b : Int)” syntax, but methods will still be curried. It will still be perfectly legal to do:

class Foo {
  func bar() {}
}

let fn = Foo.bar
fn()

Sorry, the example should have been:

let fn = Foo.bar
fn(myFoo)()

and:

let fn2 = myFoo.bar
fn2()

-Chris

···

On Dec 10, 2015, at 10:00 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:
On Dec 9, 2015, at 5:46 PM, David Farler via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

So, I think that in a perfect world, the implementation would lazily generate curry thunks for super partial applications, and we would keep the current behavior. However, if it is a significant implementation burden, I’d support doing a survey of existing code to see how widely used this is. I suspect it is rare, and if you can prove this, we may be able to knowingly break compatibility in this case in the service of getting the ABI stability.

-Chris

David

On Dec 7, 2015, at 3:37 PM, David Farler <dfarler@apple.com <mailto:dfarler@apple.com>> wrote:

I'd like to add that this would only apply to super invocation of non-final methods. Final methods always terminate with a static function reference, so the existing curry thunk mechanisms will continue to work with those until we remove them.

David

On Dec 7, 2015, at 1:51 PM, David Farler <dfarler@apple.com <mailto:dfarler@apple.com>> wrote:

Hi all,

I'd like to propose removing partial application of super method calls (except bare `super.foo` which implicitly captures `self`) in Swift 2.2.

This is motivated by the upcoming removal of curried function declaration syntax in Swift 3 combined with making super method calls dynamically dispatched instead of statically dispatched as they are now, which is scheduled to land in Swift 2.2.

The reason why dynamic dispatch is a motivator is mostly driven by implementation details, specifically how we emit partial application thunks. These thunks ultimately result in a static function reference, which is called immediately, or a dynamic dispatch through a class method. Now, you might be wondering how class methods differ from dynamic dispatch via super methods. Class methods use dynamic dispatch through the instance pointer to the class metadata for the vtable lookup, whereas super method dynamic dispatch loads the statically known superclass's metadata instead.

The logic around curry thunk emission is rather complicated so I'd like to go ahead and make partial applications based in `super` disallowed, rather than invest time in an area we'll be ripping up in Swift 3 and increase risk for regressions in Swift 2.2.

The implementation for disallowing this is dead simple and I've already got a patch for that. I should also mention that I can't safely turn on the new dynamic super method dispatch mechanics in Swift 2.2 until we address this one way or the other. I do have progress on emitting curry thunks for these kinds of partial applications but it is a rather large patch that I'd like to avoid for Swift 2.2 if possible.

David

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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


(David Farler) #6

Here's a draft of the proposal:

https://github.com/bitjammer/swift-evolution/blob/remove-partial-super/proposals/0008-remove-partial-application-super.md

Hi David,

Sorry for the delay, things have been busy lately :slight_smile:

No problem! The activity has been intense and it's great.

" Currying will be removed in Swift 3.0 so, rather than invest more engineering in those mechanisms, I propose that we disallow partial application of non-final methods through super, except where the self parameter is implicitly captured.”

This isn’t true. The proposal you’re referring to removes the “func f(a : Int)(b : Int)” syntax, but methods will still be curried. It will still be perfectly legal to do:

class Foo {
  func bar() {}
}

let fn = Foo.bar
fn()

Yes, that's what I had meant actually but the wording was probably too broad.

So, I think that in a perfect world, the implementation would lazily generate curry thunks for super partial applications, and we would keep the current behavior. However, if it is a significant implementation burden, I’d support doing a survey of existing code to see how widely used this is. I suspect it is rare, and if you can prove this, we may be able to knowingly break compatibility in this case in the service of getting the ABI stability.

-Chris

It's probably not too burdensome in an absolute sense but it is more effort to thread the right information through a mechanism that expects arbitrary levels of currying. I figured it might be better to plug it into a (potentially) simpler system after we would only expect certain uncurry levels. Maybe that's not a good bet, though! Things are working as they are now but I can really make either work. What do you think?

···

On Dec 10, 2015, at 22:00, Chris Lattner <clattner@apple.com> wrote:

On Dec 9, 2015, at 5:46 PM, David Farler via swift-evolution <swift-evolution@swift.org> wrote:

David

On Dec 7, 2015, at 3:37 PM, David Farler <dfarler@apple.com> wrote:

I'd like to add that this would only apply to super invocation of non-final methods. Final methods always terminate with a static function reference, so the existing curry thunk mechanisms will continue to work with those until we remove them.

David

On Dec 7, 2015, at 1:51 PM, David Farler <dfarler@apple.com> wrote:

Hi all,

I'd like to propose removing partial application of super method calls (except bare `super.foo` which implicitly captures `self`) in Swift 2.2.

This is motivated by the upcoming removal of curried function declaration syntax in Swift 3 combined with making super method calls dynamically dispatched instead of statically dispatched as they are now, which is scheduled to land in Swift 2.2.

The reason why dynamic dispatch is a motivator is mostly driven by implementation details, specifically how we emit partial application thunks. These thunks ultimately result in a static function reference, which is called immediately, or a dynamic dispatch through a class method. Now, you might be wondering how class methods differ from dynamic dispatch via super methods. Class methods use dynamic dispatch through the instance pointer to the class metadata for the vtable lookup, whereas super method dynamic dispatch loads the statically known superclass's metadata instead.

The logic around curry thunk emission is rather complicated so I'd like to go ahead and make partial applications based in `super` disallowed, rather than invest time in an area we'll be ripping up in Swift 3 and increase risk for regressions in Swift 2.2.

The implementation for disallowing this is dead simple and I've already got a patch for that. I should also mention that I can't safely turn on the new dynamic super method dispatch mechanics in Swift 2.2 until we address this one way or the other. I do have progress on emitting curry thunks for these kinds of partial applications but it is a rather large patch that I'd like to avoid for Swift 2.2 if possible.

David

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


(Chris Lattner) #7

I’d suggesting that Joe Groff chime in on this, but my sense is that if there is no overwhelming implementation concern, that we’d prefer to keep currying of super methods. It’s a totally narrow feature, but since we already support it, it would be nice to not regress. Curry all the things :-)

-Chris

···

On Dec 10, 2015, at 10:38 PM, David Farler <dfarler@apple.com> wrote:

" Currying will be removed in Swift 3.0 so, rather than invest more engineering in those mechanisms, I propose that we disallow partial application of non-final methods through super, except where the self parameter is implicitly captured.”

This isn’t true. The proposal you’re referring to removes the “func f(a : Int)(b : Int)” syntax, but methods will still be curried. It will still be perfectly legal to do:

class Foo {
  func bar() {}
}

let fn = Foo.bar
fn()

Yes, that's what I had meant actually but the wording was probably too broad.

So, I think that in a perfect world, the implementation would lazily generate curry thunks for super partial applications, and we would keep the current behavior. However, if it is a significant implementation burden, I’d support doing a survey of existing code to see how widely used this is. I suspect it is rare, and if you can prove this, we may be able to knowingly break compatibility in this case in the service of getting the ABI stability.

-Chris

It's probably not too burdensome in an absolute sense but it is more effort to thread the right information through a mechanism that expects arbitrary levels of currying. I figured it might be better to plug it into a (potentially) simpler system after we would only expect certain uncurry levels. Maybe that's not a good bet, though! Things are working as they are now but I can really make either work. What do you think?


(Slava Pestov) #8

" Currying will be removed in Swift 3.0 so, rather than invest more engineering in those mechanisms, I propose that we disallow partial application of non-final methods through super, except where the self parameter is implicitly captured.”

This isn’t true. The proposal you’re referring to removes the “func f(a : Int)(b : Int)” syntax, but methods will still be curried. It will still be perfectly legal to do:

class Foo {
  func bar() {}
}

let fn = Foo.bar
fn()

Yes, that's what I had meant actually but the wording was probably too broad.

So, I think that in a perfect world, the implementation would lazily generate curry thunks for super partial applications, and we would keep the current behavior. However, if it is a significant implementation burden, I’d support doing a survey of existing code to see how widely used this is. I suspect it is rare, and if you can prove this, we may be able to knowingly break compatibility in this case in the service of getting the ABI stability.

-Chris

It's probably not too burdensome in an absolute sense but it is more effort to thread the right information through a mechanism that expects arbitrary levels of currying. I figured it might be better to plug it into a (potentially) simpler system after we would only expect certain uncurry levels. Maybe that's not a good bet, though! Things are working as they are now but I can really make either work. What do you think?

I’d suggesting that Joe Groff chime in on this, but my sense is that if there is no overwhelming implementation concern, that we’d prefer to keep currying of super methods. It’s a totally narrow feature, but since we already support it, it would be nice to not regress. Curry all the things :slight_smile:

I was thinking one potential use of partially-applied super is something like the following:

class Base {
  func doSomething() {}
  func doSomethingElse() {}
}

class Derived : Base {
  func executeAwesomely(f: () -> ()) { … f() … }

  override func doSomething() {
    executeAwesomely(super.doSomething)
  }

  override func doSomethingElse() {
    executeAwesomely(super.doSomethingElse)
  }
}

I’ve written similar things before in Factor but I’m not sure if that counts as a real use-case :slight_smile:

As David mentioned the curry thunk code is rather complex and duplicates a lot of policy that’s encoded in SILGenApply.cpp. Now that @objc protocol methods can be partially applied, I think the main missing feature here is ‘Proto.someInstanceMethod’ unbound protocol method references. There might be some other corner cases too (dynamic method references perhaps?) It does feel like each corner case adds a sprinkle of ‘if’ statements in random places throughout the code.

How about we keep super.foo around for now. Once we get around to adding all the missing corner cases, we can try to re-organize and simplify the curry thunks implementation, and maybe then decide if we want to drop anything that it does.

Slava

···

On Dec 10, 2015, at 10:57 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 10, 2015, at 10:38 PM, David Farler <dfarler@apple.com <mailto:dfarler@apple.com>> wrote:

-Chris

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