@@ -29,46 +29,18 @@ class TypeVariableRefFinder : public ASTWalker {
29
29
ConstraintSystem &CS;
30
30
ASTNode Parent;
31
31
32
- llvm::SmallSetVector <TypeVariableType *, 2 > referencedVars ;
32
+ llvm::SmallPtrSetImpl <TypeVariableType *> &ReferencedVars ;
33
33
34
34
public:
35
- TypeVariableRefFinder (ConstraintSystem &cs, ASTNode parent)
36
- : CS(cs), Parent(parent) {}
35
+ TypeVariableRefFinder (
36
+ ConstraintSystem &cs, ASTNode parent,
37
+ llvm::SmallPtrSetImpl<TypeVariableType *> &referencedVars)
38
+ : CS(cs), Parent(parent), ReferencedVars(referencedVars) {}
37
39
38
40
std::pair<bool , Expr *> walkToExprPre (Expr *expr) override {
39
41
if (auto *DRE = dyn_cast<DeclRefExpr>(expr)) {
40
- if (auto type = CS.getTypeIfAvailable (DRE->getDecl ())) {
41
- // The logic below is handling not-yet resolved parameter
42
- // types referenced in the body e.g. `$0` or `x`.
43
- if (auto *typeVar = type->getAs <TypeVariableType>()) {
44
- referencedVars.insert (typeVar);
45
-
46
- // It is possible that contextual type of a parameter
47
- // has been assigned to an anonymous of named argument
48
- // early, to facilitate closure type checking. Such a
49
- // type can have type variables inside e.g.
50
- //
51
- // func test<T>(_: (UnsafePointer<T>) -> Void) {}
52
- //
53
- // test { ptr in
54
- // ...
55
- // }
56
- //
57
- // Type variable representing `ptr` in the body of
58
- // this closure would be bound to `UnsafePointer<$T>`
59
- // in this case, where `$T` is a type variable for a
60
- // generic parameter `T`.
61
- auto simplifiedTy =
62
- CS.getFixedTypeRecursive (typeVar, /* wantRValue=*/ false );
63
-
64
- if (!simplifiedTy->isEqual (typeVar) &&
65
- simplifiedTy->hasTypeVariable ()) {
66
- SmallPtrSet<TypeVariableType *, 4 > typeVars;
67
- simplifiedTy->getTypeVariables (typeVars);
68
- referencedVars.insert (typeVars.begin (), typeVars.end ());
69
- }
70
- }
71
- }
42
+ if (auto type = CS.getTypeIfAvailable (DRE->getDecl ()))
43
+ inferVariables (type);
72
44
}
73
45
74
46
return {true , expr};
@@ -80,17 +52,45 @@ class TypeVariableRefFinder : public ASTWalker {
80
52
// explicitly.
81
53
if (isa<ReturnStmt>(stmt)) {
82
54
if (auto *closure = getAsExpr<ClosureExpr>(Parent)) {
83
- auto resultTy = CS.getClosureType (closure)->getResult ();
84
- if (auto *typeVar = resultTy->getAs <TypeVariableType>())
85
- referencedVars.insert (typeVar);
55
+ inferVariables (CS.getClosureType (closure)->getResult ());
86
56
}
87
57
}
88
58
89
59
return {true , stmt};
90
60
}
91
61
92
- ArrayRef<TypeVariableType *> getReferencedVars () const {
93
- return referencedVars.getArrayRef ();
62
+ private:
63
+ void inferVariables (Type type) {
64
+ auto *typeVar = type->getWithoutSpecifierType ()->getAs <TypeVariableType>();
65
+ if (!typeVar)
66
+ return ;
67
+
68
+ // Record the type variable itself because it has to
69
+ // 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 );
88
+
89
+ if (!simplifiedTy->isEqual (typeVar) && simplifiedTy->hasTypeVariable ()) {
90
+ SmallPtrSet<TypeVariableType *, 4 > typeVars;
91
+ simplifiedTy->getTypeVariables (typeVars);
92
+ ReferencedVars.insert (typeVars.begin (), typeVars.end ());
93
+ }
94
94
}
95
95
};
96
96
@@ -151,16 +151,8 @@ static void createConjunction(ConstraintSystem &cs,
151
151
if (!isViableElement (element))
152
152
continue ;
153
153
154
- TypeVariableRefFinder refFinder (cs, locator->getAnchor ());
155
-
156
- // Solvable elements have to bring any of the referenced
157
- // outer context type variables into scope.
158
- if (element.is <Decl *>() || element.is <StmtCondition *>() ||
159
- element.is <Expr *>() || element.isStmt (StmtKind::Return))
160
- element.walk (refFinder);
161
-
162
- constraints.push_back (Constraint::createClosureBodyElement (
163
- cs, element, context, elementLoc, refFinder.getReferencedVars ()));
154
+ constraints.push_back (
155
+ Constraint::createClosureBodyElement (cs, element, context, elementLoc));
164
156
}
165
157
166
158
cs.addUnsolvedConstraint (Constraint::createConjunction (
@@ -1334,3 +1326,21 @@ bool ConstraintSystem::applySolutionToBody(Solution &solution,
1334
1326
closure->setBodyState (ClosureExpr::BodyState::TypeCheckedWithSignature);
1335
1327
return false ;
1336
1328
}
1329
+
1330
+ void ConjunctionElement::findReferencedVariables (
1331
+ ConstraintSystem &cs, SmallPtrSetImpl<TypeVariableType *> &typeVars) const {
1332
+ auto referencedVars = Element->getTypeVariables ();
1333
+ typeVars.insert (referencedVars.begin (), referencedVars.end ());
1334
+
1335
+ if (Element->getKind () != ConstraintKind::ClosureBodyElement)
1336
+ return ;
1337
+
1338
+ ASTNode element = Element->getClosureElement ();
1339
+ auto *locator = Element->getLocator ();
1340
+
1341
+ TypeVariableRefFinder refFinder (cs, locator->getAnchor (), typeVars);
1342
+
1343
+ if (element.is <Decl *>() || element.is <StmtCondition *>() ||
1344
+ element.is <Expr *>() || element.isStmt (StmtKind::Return))
1345
+ element.walk (refFinder);
1346
+ }
0 commit comments