Skip to content

Commit b8cfaf7

Browse files
committed
[CSClosure] Make sure that partially resolved params/result gets their type variables referenced
It's possible to declare explicit parameter/result type without providing generic arguments, in such situation they'd be "opened" as type variables and inferred from the contextual type or the body. Type variable collector needs to account for that and include such inner type variables into scope of an isolated closure.
1 parent e5db01b commit b8cfaf7

File tree

1 file changed

+35
-25
lines changed

1 file changed

+35
-25
lines changed

lib/Sema/CSClosure.cpp

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -61,34 +61,36 @@ class TypeVariableRefFinder : public ASTWalker {
6161

6262
private:
6363
void inferVariables(Type type) {
64-
auto *typeVar = type->getWithoutSpecifierType()->getAs<TypeVariableType>();
65-
if (!typeVar)
66-
return;
67-
64+
type = type->getWithoutSpecifierType();
6865
// Record the type variable itself because it has to
6966
// be in scope even when already bound.
70-
ReferencedVars.insert(typeVar);
71-
72-
// It is possible that contextual type of a parameter/result
73-
// has been assigned to e.g. an anonymous or named argument
74-
// early, to facilitate closure type checking. Such a
75-
// type can have type variables inside e.g.
76-
//
77-
// func test<T>(_: (UnsafePointer<T>) -> Void) {}
78-
//
79-
// test { ptr in
80-
// ...
81-
// }
82-
//
83-
// Type variable representing `ptr` in the body of
84-
// this closure would be bound to `UnsafePointer<$T>`
85-
// in this case, where `$T` is a type variable for a
86-
// generic parameter `T`.
87-
auto simplifiedTy = CS.getFixedTypeRecursive(typeVar, /*wantRValue=*/false);
67+
if (auto *typeVar = type->getAs<TypeVariableType>()) {
68+
ReferencedVars.insert(typeVar);
69+
70+
// It is possible that contextual type of a parameter/result
71+
// has been assigned to e.g. an anonymous or named argument
72+
// early, to facilitate closure type checking. Such a
73+
// type can have type variables inside e.g.
74+
//
75+
// func test<T>(_: (UnsafePointer<T>) -> Void) {}
76+
//
77+
// test { ptr in
78+
// ...
79+
// }
80+
//
81+
// Type variable representing `ptr` in the body of
82+
// this closure would be bound to `UnsafePointer<$T>`
83+
// in this case, where `$T` is a type variable for a
84+
// generic parameter `T`.
85+
type = CS.getFixedTypeRecursive(typeVar, /*wantRValue=*/false);
86+
87+
if (type->isEqual(typeVar))
88+
return;
89+
}
8890

89-
if (!simplifiedTy->isEqual(typeVar) && simplifiedTy->hasTypeVariable()) {
91+
if (type->hasTypeVariable()) {
9092
SmallPtrSet<TypeVariableType *, 4> typeVars;
91-
simplifiedTy->getTypeVariables(typeVars);
93+
type->getTypeVariables(typeVars);
9294
ReferencedVars.insert(typeVars.begin(), typeVars.end());
9395
}
9496
}
@@ -113,8 +115,16 @@ class UnresolvedClosureParameterCollector : public ASTWalker {
113115
auto *decl = DRE->getDecl();
114116
if (isa<ParamDecl>(decl)) {
115117
if (auto type = CS.getTypeIfAvailable(decl)) {
116-
if (auto *typeVar = type->getAs<TypeVariableType>())
118+
if (auto *typeVar = type->getAs<TypeVariableType>()) {
117119
Vars.insert(typeVar);
120+
} else if (type->hasTypeVariable()) {
121+
// Parameter or result type could be only partially
122+
// resolved e.g. `{ (x: X) -> Void in ... }` where
123+
// `X` is a generic type.
124+
SmallPtrSet<TypeVariableType *, 4> typeVars;
125+
type->getTypeVariables(typeVars);
126+
Vars.insert(typeVars.begin(), typeVars.end());
127+
}
118128
}
119129
}
120130
}

0 commit comments

Comments
 (0)