Skip to content

Commit 067583a

Browse files
committed
[CS] Merge VarRefCollector & UnresolvedVarCollector
These now do basically the same thing, merge their implementations.
1 parent 09bb346 commit 067583a

File tree

3 files changed

+68
-123
lines changed

3 files changed

+68
-123
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6193,6 +6193,39 @@ class ConjunctionElementProducer : public BindingProducer<ConjunctionElement> {
61936193
}
61946194
};
61956195

6196+
/// Find any references to not yet resolved outer VarDecls (including closure
6197+
/// parameters) used in the body of a conjunction element (e.g closures, taps,
6198+
/// if/switch expressions). This is required because isolated conjunctions, just
6199+
/// like single-expression closures, have to be connected to type variables they
6200+
/// are going to use, otherwise they'll get placed in a separate solver
6201+
/// component and would never produce a solution.
6202+
class VarRefCollector : public ASTWalker {
6203+
ConstraintSystem &CS;
6204+
llvm::SmallSetVector<TypeVariableType *, 4> TypeVars;
6205+
6206+
public:
6207+
VarRefCollector(ConstraintSystem &cs) : CS(cs) {}
6208+
6209+
/// Infer the referenced type variables from a given decl.
6210+
void inferTypeVars(Decl *D);
6211+
6212+
MacroWalking getMacroWalkingBehavior() const override {
6213+
return MacroWalking::Arguments;
6214+
}
6215+
6216+
PreWalkResult<Expr *> walkToExprPre(Expr *expr) override;
6217+
6218+
PreWalkAction walkToDeclPre(Decl *D) override {
6219+
// We only need to walk into PatternBindingDecls, other kinds of decls
6220+
// cannot reference outer vars.
6221+
return Action::VisitChildrenIf(isa<PatternBindingDecl>(D));
6222+
}
6223+
6224+
ArrayRef<TypeVariableType *> getTypeVars() const {
6225+
return TypeVars.getArrayRef();
6226+
}
6227+
};
6228+
61966229
/// Determine whether given type is a known one
61976230
/// for a key path `{Writable, ReferenceWritable}KeyPath`.
61986231
bool isKnownKeyPathType(Type type);

lib/Sema/CSGen.cpp

Lines changed: 33 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -846,63 +846,42 @@ namespace {
846846
};
847847
} // end anonymous namespace
848848

849-
namespace {
850-
851-
// Collect any variable references whose types involve type variables,
852-
// because there will be a dependency on those type variables once we have
853-
// generated constraints for the closure/tap body. This includes references
854-
// to other closure params such as in `{ x in { x }}` where the inner
855-
// closure is dependent on the outer closure's param type, as well as
856-
// cases like `for i in x where bar({ i })` where there's a dependency on
857-
// the type variable for the pattern `i`.
858-
struct VarRefCollector : public ASTWalker {
859-
ConstraintSystem &cs;
860-
llvm::SmallPtrSet<TypeVariableType *, 4> varRefs;
861-
862-
VarRefCollector(ConstraintSystem &cs) : cs(cs) {}
863-
864-
bool shouldWalkCaptureInitializerExpressions() override { return true; }
849+
void VarRefCollector::inferTypeVars(Decl *D) {
850+
// We're only interested in VarDecls.
851+
if (!isa_and_nonnull<VarDecl>(D))
852+
return;
865853

866-
MacroWalking getMacroWalkingBehavior() const override {
867-
return MacroWalking::Arguments;
868-
}
854+
auto ty = CS.getTypeIfAvailable(D);
855+
if (!ty)
856+
return;
869857

870-
PreWalkResult<Expr *> walkToExprPre(Expr *expr) override {
871-
// Retrieve type variables from references to var decls.
872-
if (auto *declRef = dyn_cast<DeclRefExpr>(expr)) {
873-
if (auto *varDecl = dyn_cast<VarDecl>(declRef->getDecl())) {
874-
if (auto varType = cs.getTypeIfAvailable(varDecl)) {
875-
varType->getTypeVariables(varRefs);
876-
}
877-
}
878-
}
858+
SmallPtrSet<TypeVariableType *, 4> typeVars;
859+
ty->getTypeVariables(typeVars);
860+
TypeVars.insert(typeVars.begin(), typeVars.end());
861+
}
879862

880-
// FIXME: We can see UnresolvedDeclRefExprs here because we have
881-
// not yet run preCheckExpression() on the entire closure body
882-
// yet.
883-
//
884-
// We could consider pre-checking more eagerly.
885-
if (auto *declRef = dyn_cast<UnresolvedDeclRefExpr>(expr)) {
886-
auto name = declRef->getName();
887-
auto loc = declRef->getLoc();
888-
if (name.isSimpleName() && loc.isValid()) {
889-
auto *varDecl =
890-
dyn_cast_or_null<VarDecl>(ASTScope::lookupSingleLocalDecl(
891-
cs.DC->getParentSourceFile(), name.getFullName(), loc));
892-
if (varDecl)
893-
if (auto varType = cs.getTypeIfAvailable(varDecl))
894-
varType->getTypeVariables(varRefs);
895-
}
863+
ASTWalker::PreWalkResult<Expr *>
864+
VarRefCollector::walkToExprPre(Expr *expr) {
865+
if (auto *DRE = dyn_cast<DeclRefExpr>(expr))
866+
inferTypeVars(DRE->getDecl());
867+
868+
// FIXME: We can see UnresolvedDeclRefExprs here because we don't walk into
869+
// patterns when running preCheckExpression, since we don't resolve patterns
870+
// until CSGen. We ought to consider moving pattern resolution into
871+
// pre-checking, which would allow us to pre-check patterns normally.
872+
if (auto *declRef = dyn_cast<UnresolvedDeclRefExpr>(expr)) {
873+
auto name = declRef->getName();
874+
auto loc = declRef->getLoc();
875+
if (name.isSimpleName() && loc.isValid()) {
876+
auto *SF = CS.DC->getParentSourceFile();
877+
auto *D = ASTScope::lookupSingleLocalDecl(SF, name.getFullName(), loc);
878+
inferTypeVars(D);
896879
}
897-
898-
return Action::Continue(expr);
899-
}
900-
901-
PreWalkAction walkToDeclPre(Decl *D) override {
902-
return Action::VisitChildrenIf(isa<PatternBindingDecl>(D));
903880
}
904-
};
881+
return Action::Continue(expr);
882+
}
905883

884+
namespace {
906885
class ConstraintGenerator : public ExprVisitor<ConstraintGenerator, Type> {
907886
ConstraintSystem &CS;
908887
DeclContext *CurDC;
@@ -1309,8 +1288,8 @@ struct VarRefCollector : public ASTWalker {
13091288

13101289
body->walk(refCollector);
13111290

1312-
referencedVars.append(refCollector.varRefs.begin(),
1313-
refCollector.varRefs.end());
1291+
auto vars = refCollector.getTypeVars();
1292+
referencedVars.append(vars.begin(), vars.end());
13141293
}
13151294
}
13161295

@@ -2971,9 +2950,7 @@ struct VarRefCollector : public ASTWalker {
29712950
if (!inferredType || inferredType->hasError())
29722951
return Type();
29732952

2974-
SmallVector<TypeVariableType *, 4> referencedVars{
2975-
refCollector.varRefs.begin(), refCollector.varRefs.end()};
2976-
2953+
auto referencedVars = refCollector.getTypeVars();
29772954
CS.addUnsolvedConstraint(
29782955
Constraint::create(CS, ConstraintKind::FallbackType, closureType,
29792956
inferredType, locator, referencedVars));

lib/Sema/CSSyntacticElement.cpp

Lines changed: 2 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -239,71 +239,6 @@ class TypeVariableRefFinder : public ASTWalker {
239239
}
240240
};
241241

242-
/// Find any references to not yet resolved outer VarDecls (including closure
243-
/// parameters) used in the body of the inner closure. This is required because
244-
/// isolated conjunctions, just like single-expression closures, have
245-
/// to be connected to type variables they are going to use, otherwise
246-
/// they'll get placed in a separate solver component and would never
247-
/// produce a solution.
248-
class UnresolvedVarCollector : public ASTWalker {
249-
ConstraintSystem &CS;
250-
251-
llvm::SmallSetVector<TypeVariableType *, 4> Vars;
252-
253-
public:
254-
UnresolvedVarCollector(ConstraintSystem &cs) : CS(cs) {}
255-
256-
MacroWalking getMacroWalkingBehavior() const override {
257-
return MacroWalking::Arguments;
258-
}
259-
260-
PreWalkResult<Expr *> walkToExprPre(Expr *expr) override {
261-
if (auto *DRE = dyn_cast<DeclRefExpr>(expr)) {
262-
auto *decl = DRE->getDecl();
263-
if (isa<VarDecl>(decl)) {
264-
if (auto type = CS.getTypeIfAvailable(decl)) {
265-
if (auto *typeVar = type->getAs<TypeVariableType>()) {
266-
Vars.insert(typeVar);
267-
} else if (type->hasTypeVariable()) {
268-
// Parameter or result type could be only partially
269-
// resolved e.g. `{ (x: X) -> Void in ... }` where
270-
// `X` is a generic type.
271-
SmallPtrSet<TypeVariableType *, 4> typeVars;
272-
type->getTypeVariables(typeVars);
273-
Vars.insert(typeVars.begin(), typeVars.end());
274-
}
275-
}
276-
}
277-
}
278-
279-
// FIXME: We can see UnresolvedDeclRefExprs here because we don't walk into
280-
// patterns when running preCheckExpression, since we don't resolve patterns
281-
// until CSGen. We ought to consider moving pattern resolution into
282-
// pre-checking, which would allow us to pre-check patterns normally.
283-
if (auto *declRef = dyn_cast<UnresolvedDeclRefExpr>(expr)) {
284-
auto name = declRef->getName();
285-
auto loc = declRef->getLoc();
286-
if (name.isSimpleName() && loc.isValid()) {
287-
auto *varDecl =
288-
dyn_cast_or_null<VarDecl>(ASTScope::lookupSingleLocalDecl(
289-
CS.DC->getParentSourceFile(), name.getFullName(), loc));
290-
if (varDecl) {
291-
if (auto varType = CS.getTypeIfAvailable(varDecl)) {
292-
SmallPtrSet<TypeVariableType *, 4> typeVars;
293-
varType->getTypeVariables(typeVars);
294-
Vars.insert(typeVars.begin(), typeVars.end());
295-
}
296-
}
297-
}
298-
}
299-
return Action::Continue(expr);
300-
}
301-
302-
ArrayRef<TypeVariableType *> getVariables() const {
303-
return Vars.getArrayRef();
304-
}
305-
};
306-
307242
// MARK: Constraint generation
308243

309244
/// Check whether it makes sense to convert this element into a constraint.
@@ -387,7 +322,7 @@ static void createConjunction(ConstraintSystem &cs,
387322
isIsolated = true;
388323
}
389324

390-
UnresolvedVarCollector paramCollector(cs);
325+
VarRefCollector paramCollector(cs);
391326

392327
for (const auto &entry : elements) {
393328
ASTNode element = std::get<0>(entry);
@@ -415,7 +350,7 @@ static void createConjunction(ConstraintSystem &cs,
415350
if (constraints.empty())
416351
return;
417352

418-
for (auto *externalVar : paramCollector.getVariables())
353+
for (auto *externalVar : paramCollector.getTypeVars())
419354
referencedVars.push_back(externalVar);
420355

421356
cs.addUnsolvedConstraint(Constraint::createConjunction(

0 commit comments

Comments
 (0)