func c(_ g: @escaping (Int) -> Void) {}
func a() {
let f: ((Int) -> Void) -> Void
f = { (g) -> Void in
c(g)
}
}
This code prints this useless error message.
error: cannot assign value of type '((Int) -> Void) -> Void' to type '((Int) -> Void) -> Void'
Expected is
error: cannot assign value of type '(@escaping (Int) -> Void) -> Void' to type '((Int) -> Void) -> Void'
I investigated this issue.
In this case, so type check is failed, type for error message is also reconstructed by ConstraintSystem.
CS say this.
`g` in declaration is ParenType( TypeVariableType(1) )
`g` in call of `c` is super type of (Int) -> Void
(TypeVariable ID is dummy for explanation)
CS find (Int) -> Void
as possible binding of TypeVariableType(1).
This is FunctionType
and it has @escaping
by representing isNoEscape == false
internally.
Finally, type of closure at right hand side of assignment is FunctionType ( ParenType( (Int) -> Void ) -> Void )
.
Unfortunately, compiler prints this as ((Int -> Void) -> Void)
.
To print (@escaping (Int -> Void) -> Void)
, isEscaping
flag is needed at ParenType.
But in solving process, ConstraintSystem::simplifyType()
just only replace TypeVariableType
and does not affect ParenType
at one outer side of this.
ParenType
stay here in first time for (g)
,
ofcource it does not have isEscaping
before solving constrains.
I try to rewrite type tree immediately after simplifyType
for this pattern:
FunctionType ( ParenType ( F1: FunctionType(...) ) -> * ), F1 is converted from TypeVariable
.
I have succeeded just rewriting.
But it cause other problem.
Rewriting type tree breaks necessary equality relation.
func callMethodsOnOpaqueFunction<X, Y, U>(
o: OpaqueFunction<X, Y>,
t: @escaping (X) -> Y,
u: U)
{
_ = o.inAndOutTuples(x:
(
t,
{ $0 }
)
)
}
class Opaque<T> {
typealias ObnoxiousTuple = (T, (T) -> T)
func inAndOutTuples(x: ObnoxiousTuple) -> ObnoxiousTuple { return x }
}
class OpaqueFunction<U, V>: Opaque<(U) -> V> {}
With this code, compiler fail AST verification.
tuple_expr element type mismatch:
field: ((X) -> Y) -> (X) -> Y
element: (@escaping (X) -> Y) -> (X) -> Y
I think that to solve this issue,
ConstraintSystem has to track information about @escaping
and whether it is explicit or implicit in AST.
For example, ((Int) -> Void)?
has implicit @escaping
.
And bind this information to type variable.
To do this, current design around ParenType
and FunctionType
is looking bad.
This idea is too hard for my skill so I suspended work.