[swift-evolution] [Pitch] Flattening the function type of unapplied instance methods

Joe Groff jgroff at apple.com
Mon Feb 22 16:52:54 CST 2016

Today, you can reference an instance property as a member of its type to access it as a fully unbound function, which is currently curried:

struct Foo {
  var x: Int
  func foo(y y: Int) { return x + y }

let foo = Foo.foo
foo(Foo(x: 1))(y: 2) // returns 3

However, this is problematic for `mutating` methods. Since the first argument is `inout`, the mutation window for the parameter formally ends before the second argument can be applied to complete the call. Currently we miscompile this, and form a closure over a dangling pointer, leading to undefined behavior:

struct Bar {
  var x = 0
  mutating func bar() { x += 1 }

let bar = Bar.bar
var a = Bar()
bar(&a)() // This might appear to work, if we don't optimize too hard

let closure: () -> ()
do {
  var b = Bar()
  closure = bar(&b)
closure() // This scribbles dead stack space

var c = Bar() {
  didSet { print("c was set") }

bar(&c)() // This will scribble over c after didSet is called, if not worse

We can close this hole by disallowing a reference to Bar.bar, like we already disallow partial applications. However, I think it would be in line with our other simplifications of the function type system to change the type of `Bar.bar` and other unapplied instance method references to no longer be curried. In addition to providing a model for unapplied instance methods that works with mutating methods, this would also eliminate a type difference between free functions and methods of the same arity, allowing for easier code reuse. For instance, `reduce` takes a closure of type (State, Element) -> State. Flattening the formal type of instance methods would allow binary methods to be used as-is with `reduce`, like binary free functions can:

func sumOfInts(ints: [Int]) -> Int { 
  return ints.reduce(0, combine: +)
func unionOfSets<T>(sets: [Set<T>]) -> Set<T> { 
  return ints.reduce([], combine: Set.union)

What do you all think?

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160222/d212ebb1/attachment.html>

More information about the swift-evolution mailing list