Hello,
This is a new pitch to allow explicitly specializing generic functions. Notice
that potential ambiguity with initialisers and how I’m currently trying to
avoid it. Please let me know what you think!
David
Allow explicit specialization of generic functions
Proposal: SE-XXXX
<https://github.com/apple/swift-evolution/blob/master/proposals/XXXX-allow-explicit-specialization-generic-functions.md>
Author: David Hart <https://github.com/hartbit>, Douglas Gregor
<https://github.com/DougGregor>
Status: TBD
Review manager: TBD
<https://github.com/hartbit/swift-evolution/tree/allow-explicit-types-generic-functions#introduction>Introduction
This proposal allows bypassing the type inference engine and explicitly
specializing type arguments of generic functions.
<https://github.com/hartbit/swift-evolution/tree/allow-explicit-types-generic-functions#motivation>Motivation
In Swift, generic type parameters are inferred by the argument or return value
types as follows:
func foo<T>(t: T) { ... }
foo(5) // infers T = Int
There exists certain scenarios when a programmer wants to explicitly specialize
a generic function. Swift does not allow it, so we resort to giving hints to
the inference engine:
let f1 = foo as ((Int) -> Void)
let f2: (Int) -> Void = foo
let f3 = foo<Int> // error: Cannot explicitly specialize a generic function
func bar<T>() -> T { ... }
let b1 = bar() as Int
let b2: Int = bar()
let b3 = bar<Int>() // error: Cannot explicitly specialize a generic function
This behaviour is not very consistent with generic types which allow
specialization:
let array: Array<Int> = Array<Int>(arrayLiteral: 1, 2, 3)
Therefore, this proposal seeks to make the above errors valid specializations:
let f3 = foo<Int> // explicitly specialized to (Int) -> Void
let b3 = bar<Int>() // explicitly specialized to () -> Int
An ambiguous scenario arrises when we wish to specialize initializer functions:
struct Foo<T: RawRepresentable where T.RawValue == String> {
let storage: T
init<U: CustomStringConvertible>(_ value: U) {
storage = T(rawValue: value.description)!
}
}
enum Bar: String, CustomStringConvertible {
case foobar = "foo"
var description: String {
return self.rawValue
}
}
let a = Foo<Bar>(Bar.foobar)
Does this specialization specialize the struct's or the initializer's generic
type? The proposal solves this ambiguity by requiring initializer generic type
specialization to use the init syntax:
let a = Foo<Bar>.init<Bar>(Bar.foobar)
<https://github.com/hartbit/swift-evolution/tree/allow-explicit-types-generic-functions#detailed-design>Detailed
Design
Function calls are fairly straight forward and have their grammar modified as
follows:
function-call-expression → postfix-expression generic-argument-clauseopt
parenthesized-expression
function-call-expression → postfix-expression generic-argument-clauseopt
parenthesized-expressionopt trailing-closure
To allow initializers to be called with explicit specialization, we need to use
the Initializer Expression. Its grammar is modified to:
initializer-expression → postfix-expression . init
generic-argument-clauseopt
initializer-expression → postfix-expression . init
generic-argument-clauseopt ( argument-names )
<https://github.com/hartbit/swift-evolution/tree/allow-explicit-types-generic-functions#impact-on-existing-code>Impact
on Existing Code
This proposal is purely additive and will have no impact on existing code.
<https://github.com/hartbit/swift-evolution/tree/allow-explicit-types-generic-functions#alternatives-considered>Alternatives
Considered
Not adopting this proposal for Swift._______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution