tem
(GalaxySwift)
1
My code:
aString.map { // 🛑 Cannot infer return type for closure with multiple statements; add explicit type to disambiguate
if shouldWrap {
return tagStart + String($0) + tagEnd }
else {
return String($0)
}
}
To close the return type inference hole I thought it would be simplest to just specify the type parameter T, but then I get this error message:
aString.map<String> { // 🛑 Cannot specialize a non-generic definition
But the declaration of String.map looks like this:
public func map<T>(_ transform: (Character) throws -> T) rethrows -> [T]
I'm not sure but I think that error message is wrong. This is a generic definition, is it not? And if so, why can't I specialize it?
I also tried adding the parentheses in case it was a trailing closure issue but it is not so.
For now, I wrote out the closure signature like so:
char -> String in
young
(rtSwift)
2
Or use ternary:
aString.map {
shouldWrap ? tagStart + String($0) + tagEnd : String($0)
}
tem
(GalaxySwift)
3
Yeah, that fixes the original error by changing the "complex closure" back to a simple one. 
There is no syntax for explicitly specifying type arguments to a function. Instead, you're supposed to use type inference. From Generics.rst:
We require that all type parameters for a generic function be deducible. We introduce this restriction so that we can avoid introducing a syntax for explicitly specifying type arguments to a generic function, e.g.,:
var y : Int = cast<Int>(x) // not permitted: < is the less-than operator
This syntax is horribly ambiguous in C++, and with good type argument deduction, should not be necessary in Swift.
This is a good solution, and probably the one I'd use. Another possible solution is to use the return type to aid type deduction:
let processedStrings: [String] = aString.map { ... }
With that being said, I think the diagnostic for aString.map<String> { could be made a bit more clear. Perhaps Function calls do not allow explicit type arguments could be a better message?
5 Likes
Ben_Cohen
(Ben Cohen)
5
The bad diagnostic appears to be related to literals:
extension ExpressibleByIntegerLiteral {
func f<T>(_ t: T) { }
}
let s = ""
let i = 0
i.f<String>(s) // Cannot explicitly specialize a generic function
1.f<String>(s) // Cannot specialize a non-generic definition
3 Likes
tem
(GalaxySwift)
6
Thanks for the info! That rationale kind of makes sense to me, even though it's a bit inconsistent that I'm allowed to use the explicit syntax with type names like Set<Int>.
Another possible solution is to use the return type to aid type deduction
I actually also have .joined() chained in my code so that doesn't work.
Perhaps Function calls do not allow explicit type arguments could be a better message?
Yes, that would be better!
Hm, in my code I'm actually not using a literal.
Ben_Cohen
(Ben Cohen)
7
Looks like you can trigger the same bad diagnostic from something that just doesn't type check properly...
let s = ""
let i = 2
// String.f doesn't exist
s.f<Int16>(i) { }