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

Chris Lattner clattner at apple.com
Wed Feb 24 22:50:11 CST 2016

On Feb 22, 2016, at 2:52 PM, Joe Groff via swift-evolution <swift-evolution at swift.org> wrote:
> 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

Wow, I thought we were banning this, along with the other unsupported partial application cases.  I’d strongly suggest doing that *now* (independently of how the design topic is resolved) since it is such an open tar pit.

> 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.

I see a few possible design points:

1. Disallow partial application of mutating methods.
2. Change all partially applied methods to be an uncurried form (as you propose).
3. Change mutating methods to be uncurried, but leave everything else curried.
4. Change methods on structs/enums(protocols?) to be uncurried, but leave classes curried.

#1 is the safe path.
#2 is the nuclear path.
#3/#4 are the weirdly inconsistent paths.

None of these are really great.  Since you’re advocating for it, I’m very concerned about making partially applied methods be uncurried always (#2).  I have seen a *lot* of people use curried methods on classes (in particular) and this leads to some pretty elegant patterns.  I’d expect any serious discussion of changing this behavior to include a survey of what people are actually using this for, and whether the end result we’d get from this change would be better or worse overall (not just in a single case).


> 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?
> -Joe
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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

More information about the swift-evolution mailing list