Skip to content

Commit 90ee606

Browse files
committed
Sema: Refactor CSApply in preparation for curry thunks
1 parent 783ea28 commit 90ee606

File tree

3 files changed

+100
-85
lines changed

3 files changed

+100
-85
lines changed

include/swift/AST/Expr.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3838,11 +3838,14 @@ class AutoClosureExpr : public AbstractClosureExpr {
38383838
/// The body of an autoclosure always consists of a single expression.
38393839
Expr *getSingleExpressionBody() const;
38403840

3841-
/// Unwraps a curry thunk.
3841+
/// Unwraps a curry thunk. Basically, this gives you what the old AST looked
3842+
/// like, before Sema started building curry thunks. This is really only
3843+
/// meant for legacy usages.
38423844
///
3843-
/// If this is a double curry thunk, return the original DeclRefExpr.
3844-
/// If this is a single curry thunk, return the ApplyExpr for the self call.
3845-
/// Otherwise, return null.
3845+
/// The behavior is as follows, based on the kind:
3846+
/// - for double curry thunks, returns the original DeclRefExpr.
3847+
/// - for single curry thunks, returns the ApplyExpr for the self call.
3848+
/// - otherwise, returns nullptr for convenience.
38463849
Expr *getUnwrappedCurryThunkExpr() const;
38473850

38483851
// Implement isa/cast/dyncast/etc.

lib/Sema/CSApply.cpp

Lines changed: 69 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,8 @@ namespace {
535535
cs.cacheExprTypes(base);
536536

537537
return buildMemberRef(base, SourceLoc(), overload, loc, locator,
538-
locator, implicit, semantics);
538+
locator, implicit, /*extraUncurryLevel=*/false,
539+
semantics);
539540
}
540541

541542
if (isa<TypeDecl>(decl) && !isa<ModuleDecl>(decl)) {
@@ -675,11 +676,6 @@ namespace {
675676
prev = result;
676677
}
677678

678-
// Invalid case -- direct call of a metatype. Has one less argument
679-
// application because there's no ".init".
680-
if (isa<ApplyExpr>(ExprStack.back()))
681-
argCount--;
682-
683679
return argCount;
684680
}
685681

@@ -737,6 +733,11 @@ namespace {
737733
unsigned maxArgCount = getNaturalArgumentCount(member);
738734
unsigned depth = ExprStack.size() - getArgCount(maxArgCount);
739735

736+
// Invalid case -- direct call of a metatype. Has one less argument
737+
// application because there's no ".init".
738+
if (isa<ApplyExpr>(ExprStack.back()))
739+
depth++;
740+
740741
// Create the opaque opened value. If we started with a
741742
// metatype, it's a metatype.
742743
Type opaqueType = archetype;
@@ -804,7 +805,7 @@ namespace {
804805
SelectedOverload overload, DeclNameLoc memberLoc,
805806
ConstraintLocatorBuilder locator,
806807
ConstraintLocatorBuilder memberLocator, bool Implicit,
807-
AccessSemantics semantics) {
808+
bool extraUncurryLevel, AccessSemantics semantics) {
808809
auto choice = overload.choice;
809810
auto openedType = overload.openedType;
810811
auto openedFullType = overload.openedFullType;
@@ -830,15 +831,14 @@ namespace {
830831

831832
// Build a member reference.
832833
auto memberRef = resolveConcreteDeclRef(member, memberLocator);
833-
auto refTy = solution.simplifyType(openedFullType);
834834

835835
// If we're referring to the member of a module, it's just a simple
836836
// reference.
837837
if (baseTy->is<ModuleType>()) {
838838
assert(semantics == AccessSemantics::Ordinary &&
839839
"Direct property access doesn't make sense for this");
840840
auto ref = new (context) DeclRefExpr(memberRef, memberLoc, Implicit);
841-
cs.setType(ref, refTy);
841+
cs.setType(ref, simplifyType(openedFullType));
842842
ref->setFunctionRefKind(choice.getFunctionRefKind());
843843
auto *DSBI = cs.cacheType(new (context) DotSyntaxBaseIgnoredExpr(
844844
base, dotLoc, ref, cs.getType(ref)));
@@ -857,6 +857,11 @@ namespace {
857857
return result;
858858
}
859859

860+
bool isUnboundInstanceMember =
861+
(!baseIsInstance && member->isInstanceMember());
862+
863+
auto refTy = simplifyType(openedFullType);
864+
860865
// The formal type of the 'self' value for the member's declaration.
861866
Type containerTy = getBaseType(refTy->castTo<FunctionType>());
862867

@@ -866,39 +871,21 @@ namespace {
866871

867872
// If we opened up an existential when referencing this member, update
868873
// the base accordingly.
874+
bool openedExistential = false;
875+
876+
// For a partial application, we have to open the existential inside
877+
// the thunk itself.
869878
auto knownOpened = solution.OpenedExistentialTypes.find(
870879
getConstraintSystem().getConstraintLocator(
871880
memberLocator));
872-
bool openedExistential = false;
873881
if (knownOpened != solution.OpenedExistentialTypes.end()) {
882+
// Open the existential before performing the member reference.
874883
base = openExistentialReference(base, knownOpened->second, member);
875884
baseTy = knownOpened->second;
876885
selfTy = baseTy;
877886
openedExistential = true;
878887
}
879888

880-
// If this is a method whose result type is dynamic Self, or a
881-
// construction, replace the result type with the actual object type.
882-
Type dynamicSelfFnType;
883-
if (!member->getDeclContext()->getSelfProtocolDecl()) {
884-
if (auto func = dyn_cast<AbstractFunctionDecl>(member)) {
885-
if (func->hasDynamicSelfResult() &&
886-
!baseTy->getOptionalObjectType()) {
887-
refTy = refTy->replaceCovariantResultType(containerTy, 2);
888-
if (!baseTy->isEqual(containerTy)) {
889-
dynamicSelfFnType = refTy->replaceCovariantResultType(baseTy, 2);
890-
}
891-
}
892-
} else if (auto *decl = dyn_cast<VarDecl>(member)) {
893-
if (decl->getValueInterfaceType()->hasDynamicSelfType()) {
894-
refTy = refTy->replaceCovariantResultType(containerTy, 1);
895-
if (!baseTy->isEqual(containerTy)) {
896-
dynamicSelfFnType = refTy->replaceCovariantResultType(baseTy, 1);
897-
}
898-
}
899-
}
900-
}
901-
902889
// References to properties with accessors and storage usually go
903890
// through the accessors, but sometimes are direct.
904891
if (auto *VD = dyn_cast<VarDecl>(member)) {
@@ -952,9 +939,9 @@ namespace {
952939

953940
// If the base was an opened existential, erase the opened
954941
// existential.
955-
if (openedExistential &&
956-
refType->hasOpenedExistential(knownOpened->second)) {
957-
refType = refType->eraseOpenedExistential(knownOpened->second);
942+
if (openedExistential) {
943+
refType = refType->eraseOpenedExistential(
944+
baseTy->castTo<OpenedArchetypeType>());
958945
}
959946

960947
cs.setType(ref, refType);
@@ -1003,7 +990,7 @@ namespace {
1003990

1004991
// For properties, build member references.
1005992
if (isa<VarDecl>(member)) {
1006-
if (!baseIsInstance && member->isInstanceMember()) {
993+
if (isUnboundInstanceMember) {
1007994
assert(memberLocator.getBaseLocator() &&
1008995
cs.UnevaluatedRootExprs.count(
1009996
memberLocator.getBaseLocator()->getAnchor()) &&
@@ -1020,39 +1007,60 @@ namespace {
10201007
memberLoc, Implicit, semantics);
10211008
memberRefExpr->setIsSuper(isSuper);
10221009

1023-
// Skip the synthesized 'self' input type of the opened type.
10241010
cs.setType(memberRefExpr, simplifyType(openedType));
10251011
Expr *result = memberRefExpr;
10261012
closeExistential(result, locator);
1027-
if (dynamicSelfFnType) {
1028-
result = new (context) CovariantReturnConversionExpr(result,
1029-
dynamicSelfFnType);
1030-
cs.cacheType(result);
1031-
cs.setType(result, simplifyType(openedType));
1013+
1014+
if (cast<VarDecl>(member)->getValueInterfaceType()
1015+
->hasDynamicSelfType()) {
1016+
if (!baseTy->isEqual(containerTy)) {
1017+
result = new (context) CovariantReturnConversionExpr(
1018+
result, simplifyType(openedType));
1019+
cs.cacheType(result);
1020+
}
10321021
}
10331022
return forceUnwrapIfExpected(result, choice, memberLocator);
10341023
}
1035-
1024+
1025+
if (member->getInterfaceType()->hasDynamicSelfType())
1026+
refTy = refTy->replaceCovariantResultType(containerTy, 2);
1027+
10361028
// Handle all other references.
10371029
auto declRefExpr = new (context) DeclRefExpr(memberRef, memberLoc,
10381030
Implicit, semantics);
10391031
declRefExpr->setFunctionRefKind(choice.getFunctionRefKind());
1032+
declRefExpr->setType(refTy);
10401033
cs.setType(declRefExpr, refTy);
10411034
Expr *ref = declRefExpr;
10421035

1043-
// If the reference needs to be converted, do so now.
1044-
if (dynamicSelfFnType) {
1045-
ref = new (context) CovariantFunctionConversionExpr(ref,
1036+
// If this is a method whose result type is dynamic Self, or a
1037+
// construction, replace the result type with the actual object type.
1038+
if (!member->getDeclContext()->getSelfProtocolDecl()) {
1039+
if (auto func = dyn_cast<AbstractFunctionDecl>(member)) {
1040+
if (func->hasDynamicSelfResult() &&
1041+
!baseTy->getOptionalObjectType()) {
1042+
if (!baseTy->isEqual(containerTy)) {
1043+
auto dynamicSelfFnType = refTy->replaceCovariantResultType(baseTy, 2);
1044+
ref = new (context) CovariantFunctionConversionExpr(ref,
10461045
dynamicSelfFnType);
1047-
cs.cacheType(ref);
1046+
cs.cacheType(ref);
1047+
}
1048+
}
1049+
}
10481050
}
10491051

10501052
ApplyExpr *apply;
10511053
if (isa<ConstructorDecl>(member)) {
10521054
// FIXME: Provide type annotation.
10531055
ref = forceUnwrapIfExpected(ref, choice, memberLocator);
10541056
apply = new (context) ConstructorRefCallExpr(ref, base);
1055-
} else if (!baseIsInstance && member->isInstanceMember()) {
1057+
} else if (isUnboundInstanceMember) {
1058+
auto refType = cs.simplifyType(openedType);
1059+
if (!cs.getType(ref)->isEqual(refType)) {
1060+
ref = new (context) FunctionConversionExpr(ref, refType);
1061+
cs.cacheType(ref);
1062+
}
1063+
10561064
// Reference to an unbound instance method.
10571065
Expr *result = new (context) DotSyntaxBaseIgnoredExpr(base, dotLoc,
10581066
ref,
@@ -2339,7 +2347,7 @@ namespace {
23392347
return buildMemberRef(
23402348
expr->getBase(), expr->getDotLoc(), selected, expr->getNameLoc(),
23412349
cs.getConstraintLocator(expr), memberLocator, expr->isImplicit(),
2342-
expr->getAccessSemantics());
2350+
/*extraUncurryLevel=*/false, expr->getAccessSemantics());
23432351
}
23442352

23452353
Expr *visitDynamicMemberRefExpr(DynamicMemberRefExpr *expr) {
@@ -2382,7 +2390,8 @@ namespace {
23822390
auto *exprLoc = cs.getConstraintLocator(expr);
23832391
auto result = buildMemberRef(
23842392
base, expr->getDotLoc(), selected, expr->getNameLoc(), exprLoc,
2385-
memberLocator, expr->isImplicit(), AccessSemantics::Ordinary);
2393+
memberLocator, expr->isImplicit(), /*extraUncurryLevel=*/true,
2394+
AccessSemantics::Ordinary);
23862395
if (!result)
23872396
return nullptr;
23882397

@@ -2530,7 +2539,8 @@ namespace {
25302539
if (cs.getType(base)->is<AnyMetatypeType>()) {
25312540
return buildMemberRef(
25322541
base, dotLoc, overload, nameLoc, cs.getConstraintLocator(expr),
2533-
ctorLocator, implicit, AccessSemantics::Ordinary);
2542+
ctorLocator, implicit, /*extraUncurryLevel=*/true,
2543+
AccessSemantics::Ordinary);
25342544
}
25352545

25362546
// The subexpression must be either 'self' or 'super'.
@@ -2703,7 +2713,8 @@ namespace {
27032713
case OverloadChoiceKind::DeclViaDynamic:
27042714
return buildMemberRef(base, dotLoc, selected, nameLoc,
27052715
cs.getConstraintLocator(expr), memberLocator,
2706-
implicit, AccessSemantics::Ordinary);
2716+
implicit, /*extraUncurryLevel=*/false,
2717+
AccessSemantics::Ordinary);
27072718

27082719
case OverloadChoiceKind::TupleIndex: {
27092720
Type toType = simplifyType(cs.getType(expr));
@@ -6547,7 +6558,8 @@ static Expr *buildCallAsFunctionMethodRef(
65476558
auto *fn = apply->getFn();
65486559
auto *declRef = rewriter.buildMemberRef(
65496560
fn, /*dotLoc*/ SourceLoc(), selected, DeclNameLoc(fn->getEndLoc()),
6550-
calleeLoc, calleeLoc, /*implicit*/ true, AccessSemantics::Ordinary);
6561+
calleeLoc, calleeLoc, /*implicit*/ true,
6562+
/*extraUncurryLevel=*/true, AccessSemantics::Ordinary);
65516563
if (!declRef)
65526564
return nullptr;
65536565
declRef->setImplicit(apply->isImplicit());
@@ -6581,7 +6593,8 @@ ExprRewriter::finishApplyDynamicCallable(ApplyExpr *apply,
65816593
// Construct expression referencing the `dynamicallyCall` method.
65826594
auto member = buildMemberRef(fn, SourceLoc(), selected,
65836595
DeclNameLoc(method->getNameLoc()), loc, loc,
6584-
/*implicit*/ true, AccessSemantics::Ordinary);
6596+
/*implicit=*/true, /*extraUncurryLevel=*/true,
6597+
AccessSemantics::Ordinary);
65856598

65866599
// Construct argument to the method (either an array or dictionary
65876600
// expression).
@@ -6942,7 +6955,8 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
69426955
// constructor call expr itself has the apply's 'implicitness'.
69436956
Expr *declRef = buildMemberRef(fn, /*dotLoc=*/SourceLoc(), *selected,
69446957
DeclNameLoc(fn->getEndLoc()), locator,
6945-
ctorLocator, /*Implicit=*/true,
6958+
ctorLocator, /*implicit=*/true,
6959+
/*extraUncurryLevel=*/true,
69466960
AccessSemantics::Ordinary);
69476961
if (!declRef)
69486962
return nullptr;

lib/Sema/ConstraintSystem.cpp

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1454,28 +1454,8 @@ ConstraintSystem::getTypeOfMemberReference(
14541454

14551455
openedType = openedType->removeArgumentLabels(numRemovedArgumentLabels);
14561456

1457-
if (!outerDC->getSelfProtocolDecl()) {
1458-
// Class methods returning Self as well as constructors get the
1459-
// result replaced with the base object type.
1460-
if (auto func = dyn_cast<AbstractFunctionDecl>(value)) {
1461-
if (func->hasDynamicSelfResult() &&
1462-
!baseObjTy->getOptionalObjectType()) {
1463-
openedType = openedType->replaceCovariantResultType(baseObjTy, 2);
1464-
}
1465-
} else if (auto *decl = dyn_cast<SubscriptDecl>(value)) {
1466-
if (decl->getElementInterfaceType()->hasDynamicSelfType()) {
1467-
openedType = openedType->replaceCovariantResultType(baseObjTy, 2);
1468-
}
1469-
} else if (auto *decl = dyn_cast<VarDecl>(value)) {
1470-
if (decl->getValueInterfaceType()->hasDynamicSelfType()) {
1471-
openedType = openedType->replaceCovariantResultType(baseObjTy, 1);
1472-
}
1473-
}
1474-
}
1475-
14761457
// If we are looking at a member of an existential, open the existential.
14771458
Type baseOpenedTy = baseObjTy;
1478-
14791459
if (baseObjTy->isExistentialType()) {
14801460
auto openedArchetype = OpenedArchetypeType::get(baseObjTy);
14811461
OpenedExistentialTypes.push_back({ getConstraintLocator(locator),
@@ -1484,8 +1464,7 @@ ConstraintSystem::getTypeOfMemberReference(
14841464
}
14851465

14861466
// Constrain the 'self' object type.
1487-
auto openedFnType = openedType->castTo<FunctionType>();
1488-
auto openedParams = openedFnType->getParams();
1467+
auto openedParams = openedType->castTo<FunctionType>()->getParams();
14891468
assert(openedParams.size() == 1);
14901469

14911470
Type selfObjTy = openedParams.front().getPlainType()->getMetatypeInstanceType();
@@ -1513,16 +1492,35 @@ ConstraintSystem::getTypeOfMemberReference(
15131492
}
15141493

15151494
// Compute the type of the reference.
1516-
Type type;
1495+
Type type = openedType;
1496+
1497+
if (!outerDC->getSelfProtocolDecl()) {
1498+
// Class methods returning Self as well as constructors get the
1499+
// result replaced with the base object type.
1500+
if (auto func = dyn_cast<AbstractFunctionDecl>(value)) {
1501+
if (func->hasDynamicSelfResult() &&
1502+
!baseObjTy->getOptionalObjectType()) {
1503+
type = type->replaceCovariantResultType(baseObjTy, 2);
1504+
}
1505+
} else if (auto *decl = dyn_cast<SubscriptDecl>(value)) {
1506+
if (decl->getElementInterfaceType()->hasDynamicSelfType()) {
1507+
type = type->replaceCovariantResultType(baseObjTy, 2);
1508+
}
1509+
} else if (auto *decl = dyn_cast<VarDecl>(value)) {
1510+
if (decl->getValueInterfaceType()->hasDynamicSelfType()) {
1511+
type = type->replaceCovariantResultType(baseObjTy, 1);
1512+
}
1513+
}
1514+
}
1515+
15171516
if (hasAppliedSelf) {
15181517
// For a static member referenced through a metatype or an instance
15191518
// member referenced through an instance, strip off the 'self'.
1520-
type = openedFnType->getResult();
1519+
type = type->castTo<FunctionType>()->getResult();
15211520
} else {
15221521
// For an unbound instance method reference, replace the 'Self'
15231522
// parameter with the base type.
1524-
openedType = openedFnType->replaceSelfParameterType(baseObjTy);
1525-
type = openedType;
1523+
type = type->replaceSelfParameterType(baseObjTy);
15261524
}
15271525

15281526
// When accessing protocol members with an existential base, replace

0 commit comments

Comments
 (0)