Skip to content

Commit 0781aee

Browse files
authored
Merge pull request swiftlang#16896 from xedin/cs-params-cache
[CSSolver] Add closure parameter type caching
2 parents b34c245 + 2558060 commit 0781aee

12 files changed

+170
-200
lines changed

lib/AST/Decl.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2138,8 +2138,10 @@ Type ValueDecl::getInterfaceType() const {
21382138
}
21392139

21402140
void ValueDecl::setInterfaceType(Type type) {
2141-
if (!type.isNull() && isa<ParamDecl>(this)) {
2142-
assert(!type->is<InOutType>() && "caller did not pass a base type");
2141+
if (!type.isNull()) {
2142+
assert(!type->hasTypeVariable() && "Type variable in interface type");
2143+
if (isa<ParamDecl>(this))
2144+
assert(!type->is<InOutType>() && "caller did not pass a base type");
21432145
}
21442146
// lldb creates global typealiases with archetypes in them.
21452147
// FIXME: Add an isDebugAlias() flag, like isDebugVar().
@@ -2152,9 +2154,8 @@ void ValueDecl::setInterfaceType(Type type) {
21522154
isa<AbstractClosureExpr>(getDeclContext()))) {
21532155
assert(!type->hasArchetype() &&
21542156
"Archetype in interface type");
2155-
assert(!type->hasTypeVariable() &&
2156-
"Archetype in interface type");
21572157
}
2158+
21582159
TypeAndAccess.setPointer(type);
21592160
}
21602161

lib/IDE/CodeCompletion.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2019,6 +2019,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
20192019
auto *GenericSig = VD->getInnermostDeclContext()
20202020
->getGenericSignatureOfContext();
20212021

2022+
assert(VD->hasValidSignature());
20222023
Type T = VD->getInterfaceType();
20232024

20242025
if (*ExprType) {
@@ -2105,6 +2106,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
21052106
addLeadingDot(Builder);
21062107
Builder.addTextChunk(Name);
21072108
setClangDeclKeywords(VD, Pairs, Builder);
2109+
2110+
if (!VD->hasValidSignature())
2111+
return;
2112+
21082113
// Add a type annotation.
21092114
Type VarType = getTypeOfMember(VD);
21102115
if (VD->getName() != Ctx.Id_self && VD->isInOut()) {

lib/Sema/CSDiag.cpp

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,8 @@ tryDiagnoseTrailingClosureAmbiguity(TypeChecker &tc,
410410
const ParamDecl *param = paramList->getArray().back();
411411

412412
// Sanity-check that the trailing closure corresponds to this parameter.
413-
if (!param->getInterfaceType()->is<AnyFunctionType>())
413+
if (!param->hasValidSignature() ||
414+
!param->getInterfaceType()->is<AnyFunctionType>())
414415
return false;
415416

416417
Identifier trailingClosureLabel = param->getArgumentName();
@@ -2478,11 +2479,11 @@ typeCheckArbitrarySubExprIndependently(Expr *subExpr, TCCOptions options) {
24782479
// none of its arguments are type variables. If so, these type variables
24792480
// would be accessible to name lookup of the subexpression and may thus leak
24802481
// in. Reset them to UnresolvedTypes for safe measures.
2481-
for (auto param : *CE->getParameters()) {
2482-
auto VD = param;
2483-
if (VD->getType()->hasTypeVariable() || VD->getType()->hasError()) {
2484-
VD->setType(CS.getASTContext().TheUnresolvedType);
2485-
VD->setInterfaceType(VD->getType());
2482+
for (auto *param : *CE->getParameters()) {
2483+
if (param->hasValidSignature()) {
2484+
auto type = param->getType();
2485+
assert(!type->hasTypeVariable() && !type->hasError());
2486+
(void)type;
24862487
}
24872488
}
24882489
}
@@ -3826,8 +3827,6 @@ static bool diagnoseImplicitSelfErrors(Expr *fnExpr, Expr *argExpr,
38263827
// Swift Standard Library called 'max' which does accept two arguments,
38273828
// so user might have called that by mistake without realizing that
38283829
// compiler would add implicit 'self.' prefix to the call of 'max'.
3829-
ExprCleaner cleanup(argExpr);
3830-
38313830
auto argType = CS.getType(argExpr);
38323831
// If argument wasn't properly type-checked, let's retry without changing AST.
38333832
if (!argType || argType->hasUnresolvedType() || argType->hasTypeVariable() ||
@@ -6982,7 +6981,8 @@ bool FailureDiagnosis::diagnoseClosureExpr(
69826981
//
69836982
// Handle this by rewriting the arguments to UnresolvedType().
69846983
for (auto VD : *CE->getParameters()) {
6985-
if (VD->getType()->hasTypeVariable() || VD->getType()->hasError()) {
6984+
if (VD->hasType() && (VD->getType()->hasTypeVariable() ||
6985+
VD->getType()->hasError())) {
69866986
VD->setType(CS.getASTContext().TheUnresolvedType);
69876987
VD->setInterfaceType(VD->getType()->getInOutObjectType());
69886988
}
@@ -7008,8 +7008,6 @@ bool FailureDiagnosis::diagnoseClosureExpr(
70087008
// but it's not always reset.
70097009

70107010
if (expectedResultType && !CE->hasExplicitResultType()) {
7011-
ExprCleaner cleaner(CE);
7012-
70137011
auto closure = CE->getSingleExpressionBody();
70147012
ConcreteDeclRef decl = nullptr;
70157013
// Let's try to compute result type without mutating AST and
@@ -8645,7 +8643,8 @@ diagnoseAmbiguousMultiStatementClosure(ClosureExpr *closure) {
86458643
resultExpr->forEachChildExpr([&](Expr *childExpr) -> Expr *{
86468644
if (auto DRE = dyn_cast<DeclRefExpr>(childExpr)) {
86478645
if (auto param = dyn_cast<ParamDecl>(DRE->getDecl())) {
8648-
auto paramType = param->hasType() ? param->getType() : Type();
8646+
auto paramType =
8647+
param->hasValidSignature() ? param->getType() : Type();
86498648
if (!paramType || paramType->hasTypeVariable()) {
86508649
hasUnresolvedParams = true;
86518650
return nullptr;

lib/Sema/CSGen.cpp

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,28 +1353,43 @@ namespace {
13531353
}
13541354

13551355
auto locator = CS.getConstraintLocator(E);
1356-
1357-
// Create an overload choice referencing this declaration and immediately
1358-
// resolve it. This records the overload for use later.
1359-
auto tv = CS.createTypeVariable(locator,
1360-
TVO_CanBindToLValue);
1361-
1362-
OverloadChoice choice =
1363-
OverloadChoice(Type(), E->getDecl(), E->getFunctionRefKind());
1364-
CS.resolveOverload(locator, tv, choice, CurDC);
13651356

1357+
// If this is a 'var' or 'let' declaration with already
1358+
// resolved type, let's favor it.
13661359
if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
1367-
if (VD->getInterfaceType() &&
1368-
!VD->getInterfaceType()->is<TypeVariableType>()) {
1369-
// FIXME: ParamDecls in closures shouldn't get an interface type
1370-
// until the constraint system has been solved.
1371-
auto type = VD->getInterfaceType();
1360+
Type type;
1361+
if (VD->hasInterfaceType()) {
1362+
type = VD->getInterfaceType();
13721363
if (type->hasTypeParameter())
13731364
type = VD->getDeclContext()->mapTypeIntoContext(type);
13741365
CS.setFavoredType(E, type.getPointer());
13751366
}
1367+
1368+
// This can only happen when failure diangostics is trying
1369+
// to type-check expressions inside of a single-statement
1370+
// closure which refer to anonymous parameters, in this case
1371+
// let's either use type as written or allocate a fresh type
1372+
// variable, just like we do for closure type.
1373+
if (auto *PD = dyn_cast<ParamDecl>(VD)) {
1374+
if (!CS.hasType(PD)) {
1375+
if (type && type->hasUnboundGenericType())
1376+
type = CS.openUnboundGenericType(type, locator);
1377+
1378+
CS.setType(
1379+
PD, type ? type
1380+
: CS.createTypeVariable(locator, TVO_CanBindToLValue));
1381+
}
1382+
}
13761383
}
13771384

1385+
// Create an overload choice referencing this declaration and immediately
1386+
// resolve it. This records the overload for use later.
1387+
auto tv = CS.createTypeVariable(locator,
1388+
TVO_CanBindToLValue);
1389+
1390+
OverloadChoice choice =
1391+
OverloadChoice(Type(), E->getDecl(), E->getFunctionRefKind());
1392+
CS.resolveOverload(locator, tv, choice, CurDC);
13781393
return tv;
13791394
}
13801395

@@ -1992,19 +2007,17 @@ namespace {
19922007
// FIXME: Need a better locator for a pattern as a base.
19932008
Type openedType = CS.openUnboundGenericType(type, locator);
19942009
assert(!param->isImmutable() || !openedType->is<InOutType>());
1995-
param->setType(openedType->getInOutObjectType());
1996-
param->setInterfaceType(openedType->getInOutObjectType());
2010+
CS.setType(param, openedType->getInOutObjectType());
19972011
continue;
19982012
}
19992013

20002014
// Otherwise, create a fresh type variable.
2001-
Type ty = CS.createTypeVariable(locator, TVO_CanBindToInOut);
2002-
2003-
param->setType(ty);
2004-
param->setInterfaceType(ty);
2015+
CS.setType(param, CS.createTypeVariable(locator, TVO_CanBindToInOut));
20052016
}
2006-
2007-
return params->getType(CS.getASTContext());
2017+
2018+
return params->getType(CS.getASTContext(), [&](ParamDecl *param) {
2019+
return CS.getType(param);
2020+
});
20082021
}
20092022

20102023

@@ -3599,7 +3612,6 @@ bool swift::typeCheckUnresolvedExpr(DeclContext &DC,
35993612
auto *TC = static_cast<TypeChecker*>(DC.getASTContext().getLazyResolver());
36003613
ConstraintSystem CS(*TC, &DC, Options);
36013614
Parent = Parent->walk(SanitizeExpr(CS));
3602-
CleanupIllFormedExpressionRAII cleanup(Parent);
36033615
InferUnresolvedMemberConstraintGenerator MCG(E, CS);
36043616
ConstraintWalker cw(MCG);
36053617
Parent->walk(cw);

lib/Sema/CSSimplify.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -786,7 +786,7 @@ matchCallArguments(ConstraintSystem &cs, ConstraintKind kind,
786786

787787
llvm::SmallBitVector defaultMap =
788788
computeDefaultMap(params, callee, calleeLevel);
789-
789+
790790
// Extract the arguments.
791791
auto args = decomposeArgType(argType, argLabels);
792792

lib/Sema/CSSolver.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -837,11 +837,6 @@ bool ConstraintSystem::Candidate::solve(
837837
// Set up expression type checker timer for the candidate.
838838
cs.Timer.emplace(E, cs);
839839

840-
// Cleanup after constraint system generation/solving,
841-
// because it would assign types to expressions, which
842-
// might interfere with solving higher-level expressions.
843-
ExprCleaner cleaner(E);
844-
845840
// Generate constraints for the new system.
846841
if (auto generatedExpr = cs.generateConstraints(E)) {
847842
E = generatedExpr;

lib/Sema/CalleeCandidateInfo.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,13 @@ static bool isSubstitutableFor(Type type, ArchetypeType *archetype,
5858

5959
UncurriedCandidate::UncurriedCandidate(ValueDecl *decl, unsigned level)
6060
: declOrExpr(decl), level(level), substituted(false) {
61-
62-
if (auto *PD = dyn_cast<ParamDecl>(decl))
63-
entityType = PD->getType();
64-
else {
61+
62+
if (auto *PD = dyn_cast<ParamDecl>(decl)) {
63+
if (PD->hasValidSignature())
64+
entityType = PD->getType();
65+
else
66+
entityType = PD->getASTContext().TheUnresolvedType;
67+
} else {
6568
entityType = decl->getInterfaceType();
6669
auto *DC = decl->getInnermostDeclContext();
6770
if (auto *GFT = entityType->getAs<GenericFunctionType>()) {

lib/Sema/ConstraintSystem.cpp

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -800,20 +800,22 @@ static bool doesStorageProduceLValue(TypeChecker &TC,
800800
!storage->isSetterMutating();
801801
}
802802

803-
Type TypeChecker::getUnopenedTypeOfReference(VarDecl *value, Type baseType,
804-
DeclContext *UseDC,
805-
const DeclRefExpr *base,
806-
bool wantInterfaceType) {
807-
validateDecl(value);
808-
if (!value->hasValidSignature() || value->isInvalid())
809-
return ErrorType::get(Context);
810-
811-
Type requestedType = (wantInterfaceType
812-
? value->getInterfaceType()
813-
: value->getType());
803+
Type ConstraintSystem::getUnopenedTypeOfReference(VarDecl *value, Type baseType,
804+
DeclContext *UseDC,
805+
const DeclRefExpr *base,
806+
bool wantInterfaceType) {
807+
return TC.getUnopenedTypeOfReference(
808+
value, baseType, UseDC,
809+
[&](VarDecl *var) -> Type { return getType(var, wantInterfaceType); },
810+
base, wantInterfaceType);
811+
}
814812

815-
requestedType = requestedType->getWithoutSpecifierType()
816-
->getReferenceStorageReferent();
813+
Type TypeChecker::getUnopenedTypeOfReference(
814+
VarDecl *value, Type baseType, DeclContext *UseDC,
815+
llvm::function_ref<Type(VarDecl *)> getType, const DeclRefExpr *base,
816+
bool wantInterfaceType) {
817+
Type requestedType =
818+
getType(value)->getWithoutSpecifierType()->getReferenceStorageReferent();
817819

818820
// If we're dealing with contextual types, and we referenced this type from
819821
// a different context, map the type.
@@ -1013,8 +1015,8 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value,
10131015

10141016
// Determine the type of the value, opening up that type if necessary.
10151017
bool wantInterfaceType = !varDecl->getDeclContext()->isLocalContext();
1016-
Type valueType = TC.getUnopenedTypeOfReference(varDecl, Type(), useDC, base,
1017-
wantInterfaceType);
1018+
Type valueType =
1019+
getUnopenedTypeOfReference(varDecl, Type(), useDC, base, wantInterfaceType);
10181020

10191021
assert(!valueType->hasUnboundGenericType() &&
10201022
!valueType->hasTypeParameter());
@@ -1334,9 +1336,8 @@ ConstraintSystem::getTypeOfMemberReference(
13341336
refType = FunctionType::get(indicesTy, elementTy,
13351337
AnyFunctionType::ExtInfo());
13361338
} else {
1337-
refType = TC.getUnopenedTypeOfReference(cast<VarDecl>(value),
1338-
baseTy, useDC, base,
1339-
/*wantInterfaceType=*/true);
1339+
refType = getUnopenedTypeOfReference(cast<VarDecl>(value), baseTy, useDC,
1340+
base, /*wantInterfaceType=*/true);
13401341
}
13411342

13421343
auto selfTy = outerDC->getSelfInterfaceType();

0 commit comments

Comments
 (0)