Skip to content

Commit 7f64b68

Browse files
author
Mark Lacey
committed
Improve handling of types in constraint system.
Several fixes in order to make handling of types more consistent. In particular: - Expression types used within the constraint system itself always use the type map. - Prior to calling out to any TypeChecker functions, the types are written back into the expression tree. After the call, the types are read back into the constraint system type map. - Some calls to directly set types on the expressions are reintroduced in places they make sense (e.g. when building up new expressions that are then passed to typeCheckExpressionShallow). ConstraintSystem::setType() is still setting the type on the expression nodes at the moment, because there is still some incorrect handling of types that I need to track down (in particular some issues related to closures do not appear to be handled correctly). Similarly, when we cache the types in the constraint system map, we are not clearing them from the expression tree yet. The diagnostics have not been updated at all to use the types from the constraint system where appropriate, and that will need to happen as well before we can remove the write from ConstraintSystem::setType() into the expression and enable the clearing of the expression tree type when we cache it in the constraint system.
1 parent dfa41d6 commit 7f64b68

File tree

4 files changed

+167
-54
lines changed

4 files changed

+167
-54
lines changed

lib/Sema/CSApply.cpp

Lines changed: 83 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -470,9 +470,8 @@ namespace {
470470

471471
// Build a reference to the protocol requirement.
472472
Expr *base =
473-
cs.cacheType(TypeExpr::createImplicitHack(loc.getBaseNameLoc(),
474-
baseTy,
475-
ctx));
473+
TypeExpr::createImplicitHack(loc.getBaseNameLoc(), baseTy, ctx);
474+
cs.cacheExprTypes(base);
476475

477476
return buildMemberRef(base, openedType, SourceLoc(), decl,
478477
loc, openedFnType->getResult(),
@@ -778,6 +777,7 @@ namespace {
778777
// If the member is a constructor, verify that it can be legally
779778
// referenced from this base.
780779
if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
780+
cs.setExprTypes(base);
781781
if (!tc.diagnoseInvalidDynamicConstructorReferences(base, memberLoc,
782782
baseMeta, ctor, SuppressDiagnostics))
783783
return nullptr;
@@ -1436,13 +1436,14 @@ namespace {
14361436
ConcreteDeclRef fnDeclRef(fn);
14371437
auto fnRef = new (tc.Context) DeclRefExpr(fnDeclRef, DeclNameLoc(loc),
14381438
/*Implicit=*/true);
1439-
cs.setType(fnRef, fn->getInterfaceType());
1439+
fnRef->setType(fn->getInterfaceType());
14401440
fnRef->setFunctionRefKind(FunctionRefKind::SingleApply);
1441+
cs.setExprTypes(value);
14411442
Expr *call = CallExpr::createImplicit(tc.Context, fnRef, { value }, { });
14421443
if (tc.typeCheckExpressionShallow(call, dc))
14431444
return nullptr;
14441445

1445-
cs.cacheType(call);
1446+
cs.cacheExprTypes(call);
14461447

14471448
// The return type of _bridgeErrorToNSError is formally
14481449
// 'AnyObject' to avoid stdlib-to-Foundation dependencies, but it's
@@ -1477,11 +1478,18 @@ namespace {
14771478
tc.conformsToProtocol(valueType, bridgedProto, cs.DC,
14781479
(ConformanceCheckFlags::InExpression|
14791480
ConformanceCheckFlags::Used))) {
1481+
cs.setExprTypes(value);
1482+
14801483
// Form the call.
1481-
return cs.cacheType(
1484+
auto result =
14821485
tc.callWitness(value, cs.DC, bridgedProto, *conformance,
14831486
tc.Context.Id_bridgeToObjectiveC,
1484-
{ }, diag::broken_bridged_to_objc_protocol));
1487+
{ }, diag::broken_bridged_to_objc_protocol);
1488+
1489+
if (result)
1490+
cs.cacheExprTypes(result);
1491+
1492+
return result;
14851493
}
14861494

14871495
// If there is an Error conformance, try bridging as an error.
@@ -1626,6 +1634,9 @@ namespace {
16261634
// Form the call and type-check it.
16271635
Expr *call = CallExpr::createImplicit(tc.Context, fnRef, args,
16281636
{ Identifier(), Identifier() });
1637+
cs.cacheSubExprTypes(call);
1638+
cs.setSubExprTypes(call);
1639+
16291640
if (tc.typeCheckExpressionShallow(call, dc))
16301641
return nullptr;
16311642

@@ -2078,6 +2089,8 @@ namespace {
20782089
member,
20792090
DeclNameLoc(expr->getStartLoc()),
20802091
/*Implicit=*/true);
2092+
cs.cacheSubExprTypes(memberRef);
2093+
cs.setSubExprTypes(memberRef);
20812094
bool failed = tc.typeCheckExpressionShallow(memberRef, cs.DC);
20822095
cs.cacheExprTypes(memberRef);
20832096
assert(!failed && "Could not reference string interpolation witness");
@@ -2189,12 +2202,21 @@ namespace {
21892202
if (!isa<TupleExpr>(expr->getArg()))
21902203
return nullptr;
21912204
auto tupleArg = cast<TupleExpr>(expr->getArg());
2192-
for (auto elt : tupleArg->getElements())
2205+
for (auto elt : tupleArg->getElements()) {
2206+
cs.setExprTypes(elt);
21932207
args.push_back(elt);
2208+
}
21942209
DeclName constrName(tc.getObjectLiteralConstructorName(expr));
2210+
2211+
cs.cacheExprTypes(base);
2212+
cs.setExprTypes(base);
2213+
21952214
Expr *semanticExpr = tc.callWitness(base, dc, proto, *conformance,
21962215
constrName, args,
21972216
diag::object_literal_broken_proto);
2217+
if (semanticExpr)
2218+
cs.cacheExprTypes(semanticExpr);
2219+
21982220
expr->setSemanticExpr(semanticExpr);
21992221
return expr;
22002222
}
@@ -2661,22 +2683,27 @@ namespace {
26612683
}
26622684

26632685
Type argType = TupleType::get(typeElements, tc.Context);
2664-
Expr *arg = cs.cacheType(
2686+
Expr *arg =
26652687
TupleExpr::create(tc.Context, SourceLoc(),
26662688
expr->getElements(),
26672689
names,
26682690
{ },
26692691
SourceLoc(), /*HasTrailingClosure=*/false,
26702692
/*Implicit=*/true,
2671-
argType));
2693+
argType);
2694+
2695+
cs.cacheExprTypes(typeRef);
2696+
cs.setExprTypes(typeRef);
2697+
26722698
Expr *result = tc.callWitness(typeRef, dc, arrayProto, *conformance,
26732699
name, arg, diag::array_protocol_broken);
26742700
if (!result)
26752701
return nullptr;
26762702

2703+
cs.cacheExprTypes(result);
2704+
26772705
expr->setSemanticExpr(result);
26782706
cs.setType(expr, arrayTy);
2679-
cs.cacheSubExprTypes(expr);
26802707

26812708
// If the array element type was defaulted, note that in the expression.
26822709
if (solution.DefaultedConstraints.count(cs.getConstraintLocator(expr)))
@@ -2734,25 +2761,28 @@ namespace {
27342761

27352762
Type argType = TupleType::get(typeElements, tc.Context);
27362763
Expr *arg =
2737-
cs.cacheType(
27382764
TupleExpr::create(tc.Context, expr->getLBracketLoc(),
27392765
expr->getElements(),
27402766
names,
27412767
{ },
27422768
expr->getRBracketLoc(),
27432769
/*HasTrailingClosure=*/false,
27442770
/*Implicit=*/false,
2745-
argType));
2771+
argType);
2772+
2773+
cs.cacheExprTypes(typeRef);
2774+
cs.setExprTypes(typeRef);
27462775

27472776
Expr *result = tc.callWitness(typeRef, dc, dictionaryProto,
27482777
*conformance, name, arg,
27492778
diag::dictionary_protocol_broken);
27502779
if (!result)
27512780
return nullptr;
27522781

2782+
cs.cacheExprTypes(result);
2783+
27532784
expr->setSemanticExpr(result);
27542785
cs.setType(expr, dictionaryTy);
2755-
cs.cacheSubExprTypes(expr);
27562786

27572787
// If the dictionary key or value type was defaulted, note that in the
27582788
// expression.
@@ -3244,8 +3274,11 @@ namespace {
32443274
if (*choice == 0) {
32453275
// Convert the subexpression.
32463276
Expr *sub = expr->getSubExpr();
3277+
3278+
cs.setExprTypes(sub);
32473279
if (tc.convertToType(sub, toType, cs.DC))
32483280
return nullptr;
3281+
cs.cacheExprTypes(sub);
32493282

32503283
expr->setSubExpr(sub);
32513284
cs.setType(expr, toType);
@@ -3528,11 +3561,11 @@ namespace {
35283561
bool invalid = tc.typeCheckExpression(callExpr, cs.DC,
35293562
TypeLoc::withoutLoc(valueType),
35303563
CTP_CannotFail);
3564+
cs.cacheExprTypes(callExpr);
3565+
35313566
(void) invalid;
35323567
assert(!invalid && "conversion cannot fail");
35333568

3534-
cs.cacheExprTypes(callExpr);
3535-
35363569
E->setSemanticExpr(callExpr);
35373570
return E;
35383571
}
@@ -4211,11 +4244,11 @@ getCallerDefaultArg(ConstraintSystem &cs, DeclContext *dc,
42114244
bool invalid = tc.typeCheckExpression(init, dc,
42124245
TypeLoc::withoutLoc(defArgType),
42134246
CTP_CannotFail);
4247+
cs.cacheExprTypes(init);
4248+
42144249
assert(!invalid && "conversion cannot fail");
42154250
(void)invalid;
42164251

4217-
cs.cacheExprTypes(init);
4218-
42194252
return {init, defArg.first};
42204253
}
42214254

@@ -4812,7 +4845,7 @@ Expr *ExprRewriter::coerceCallArguments(
48124845
// Total hack: In Swift 3 mode, argument labels are ignored when calling
48134846
// function type with a single Any parameter.
48144847
if (paramType->isAny()) {
4815-
if (auto tupleArgType = dyn_cast<TupleType>(arg->getType().getPointer())) {
4848+
if (auto tupleArgType = dyn_cast<TupleType>(cs.getType(arg).getPointer())) {
48164849
if (tupleArgType->getNumElements() == 1) {
48174850
matchCanFail = true;
48184851
}
@@ -6022,15 +6055,20 @@ Expr *ExprRewriter::convertLiteral(Expr *literal,
60226055
// Call the builtin conversion operation.
60236056
// FIXME: Bogus location info.
60246057
Expr *base =
6025-
cs.cacheType(TypeExpr::createImplicitHack(literal->getLoc(), type,
6026-
tc.Context));
6058+
TypeExpr::createImplicitHack(literal->getLoc(), type, tc.Context);
6059+
6060+
cs.cacheExprTypes(base);
6061+
cs.setExprTypes(base);
6062+
cs.setExprTypes(literal);
6063+
60276064
Expr *result = tc.callWitness(base, dc,
60286065
builtinProtocol, *builtinConformance,
60296066
builtinLiteralFuncName,
60306067
literal,
60316068
brokenBuiltinProtocolDiag);
60326069
if (result)
6033-
cs.setType(result, type);
6070+
cs.cacheExprTypes(result);
6071+
60346072
return result;
60356073
}
60366074

@@ -6081,14 +6119,18 @@ Expr *ExprRewriter::convertLiteral(Expr *literal,
60816119

60826120
// Convert the resulting expression to the final literal type.
60836121
// FIXME: Bogus location info.
6084-
Expr *base =
6085-
cs.cacheType(TypeExpr::createImplicitHack(literal->getLoc(), type,
6086-
tc.Context));
6122+
Expr *base = TypeExpr::createImplicitHack(literal->getLoc(), type,
6123+
tc.Context);
6124+
cs.cacheExprTypes(base);
6125+
cs.setExprTypes(base);
6126+
cs.setExprTypes(literal);
6127+
60876128
literal = tc.callWitness(base, dc,
60886129
protocol, *conformance, literalFuncName,
60896130
literal, brokenProtocolDiag);
60906131
if (literal)
6091-
cs.setType(literal, type);
6132+
cs.cacheExprTypes(literal);
6133+
60926134
return literal;
60936135
}
60946136

@@ -6321,7 +6363,7 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
63216363
assert(arg->getNumElements() == 2 && "should have two arguments");
63226364
auto nonescaping = arg->getElements()[0];
63236365
auto body = arg->getElements()[1];
6324-
auto bodyFnTy = body->getType()->castTo<FunctionType>();
6366+
auto bodyFnTy = cs.getType(body)->castTo<FunctionType>();
63256367
auto escapableType = bodyFnTy->getInput();
63266368
auto resultType = bodyFnTy->getResult();
63276369

@@ -6418,7 +6460,9 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
64186460
cs.setType(apply, fnType->getResult());
64196461
apply->setIsSuper(isSuper);
64206462

6463+
cs.setExprTypes(apply);
64216464
Expr *result = tc.substituteInputSugarTypeForResult(apply);
6465+
cs.cacheExprTypes(result);
64226466

64236467
// Try closing the existential, if there is one.
64246468
closeExistential(result, locator);
@@ -7131,13 +7175,8 @@ Expr *TypeChecker::callWitness(Expr *base, DeclContext *dc,
71317175
// Construct an empty constraint system and solution.
71327176
ConstraintSystem cs(*this, dc, ConstraintSystemOptions());
71337177

7134-
cs.cacheExprTypes(base);
7135-
for (auto *e : arguments) {
7136-
cs.cacheExprTypes(e);
7137-
}
7138-
71397178
// Find the witness we need to use.
7140-
auto type = cs.getType(base);
7179+
auto type = base->getType();
71417180
assert(!type->hasTypeVariable() &&
71427181
"Building call to witness with unresolved base type!");
71437182

@@ -7164,7 +7203,7 @@ Expr *TypeChecker::callWitness(Expr *base, DeclContext *dc,
71647203
// Form a reference to the witness itself.
71657204
Type openedFullType, openedType;
71667205
std::tie(openedFullType, openedType)
7167-
= cs.getTypeOfMemberReference(cs.getType(base), witness,
7206+
= cs.getTypeOfMemberReference(base->getType(), witness,
71687207
/*isTypeReference=*/false,
71697208
/*isDynamicResult=*/false,
71707209
FunctionRefKind::DoubleApply,
@@ -7177,7 +7216,7 @@ Expr *TypeChecker::callWitness(Expr *base, DeclContext *dc,
71777216
auto argLabels = witness->getFullName().getArgumentNames();
71787217
if (arguments.size() == 1 &&
71797218
(isVariadicWitness(witness) ||
7180-
argumentNamesMatch(cs.getType(arguments[0]), argLabels))) {
7219+
argumentNamesMatch(arguments[0]->getType(), argLabels))) {
71817220
call = CallExpr::create(Context, unresolvedDot, arguments[0], { },
71827221
{ }, /*hasTrailingClosure=*/false,
71837222
/*implicit=*/true);
@@ -7203,18 +7242,18 @@ Expr *TypeChecker::callWitness(Expr *base, DeclContext *dc,
72037242
/*implicit=*/true);
72047243
}
72057244

7206-
cs.cacheExprTypes(call);
7207-
72087245
// Add the conversion from the argument to the function parameter type.
72097246
cs.addConstraint(ConstraintKind::ArgumentTupleConversion,
7210-
cs.getType(call->getArg()),
7247+
call->getArg()->getType(),
72117248
openedType->castTo<FunctionType>()->getInput(),
72127249
cs.getConstraintLocator(call,
72137250
ConstraintLocator::ApplyArgument));
72147251

72157252
// Solve the system.
72167253
SmallVector<Solution, 1> solutions;
72177254

7255+
cs.cacheExprTypes(call);
7256+
72187257
// If the system failed to produce a solution, post any available diagnostics.
72197258
if (cs.solve(solutions) || solutions.size() != 1) {
72207259
cs.salvage(solutions, base);
@@ -7289,15 +7328,19 @@ Solution::convertBooleanTypeToBuiltinI1(Expr *expr, ConstraintLocator *locator)
72897328
builtinMethod,
72907329
DeclNameLoc(expr->getLoc()),
72917330
/*Implicit=*/true);
7331+
cs.cacheSubExprTypes(memberRef);
7332+
cs.setSubExprTypes(memberRef);
72927333
bool failed = tc.typeCheckExpressionShallow(memberRef, cs.DC);
7293-
cs.cacheType(memberRef);
7334+
cs.cacheExprTypes(memberRef);
72947335
assert(!failed && "Could not reference witness?");
72957336
(void)failed;
72967337

72977338
// Call the builtin method.
72987339
expr = CallExpr::createImplicit(ctx, memberRef, { }, { });
7340+
cs.cacheSubExprTypes(expr);
7341+
cs.setSubExprTypes(expr);
72997342
failed = tc.typeCheckExpressionShallow(expr, cs.DC);
7300-
cs.cacheType(expr);
7343+
cs.cacheExprTypes(expr);
73017344
assert(!failed && "Could not call witness?");
73027345
(void)failed;
73037346

lib/Sema/CSGen.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2327,7 +2327,7 @@ namespace {
23272327
outputTy = fnType->getResult();
23282328
}
23292329
} else if (auto TE = dyn_cast<TypeExpr>(fnExpr)) {
2330-
outputTy = TE->getInstanceType();
2330+
outputTy = CS.getInstanceType(TE);
23312331
NominalTypeDecl *NTD = nullptr;
23322332

23332333
if (auto nominalType = outputTy->getAs<NominalType>()) {
@@ -2976,7 +2976,7 @@ Expr *ConstraintSystem::generateConstraintsShallow(Expr *expr) {
29762976
// Sanitize the expression.
29772977
expr = SanitizeExpr(getTypeChecker()).walkToExprPost(expr);
29782978

2979-
cacheExprTypes(expr);
2979+
cacheSubExprTypes(expr);
29802980

29812981
// Visit the top-level expression generating constraints.
29822982
ConstraintGenerator cg(*this);

0 commit comments

Comments
 (0)