mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Sema: Refactor CSApply in preparation for curry thunks
This commit is contained in:
@@ -3838,11 +3838,14 @@ public:
|
||||
/// The body of an autoclosure always consists of a single expression.
|
||||
Expr *getSingleExpressionBody() const;
|
||||
|
||||
/// Unwraps a curry thunk.
|
||||
/// Unwraps a curry thunk. Basically, this gives you what the old AST looked
|
||||
/// like, before Sema started building curry thunks. This is really only
|
||||
/// meant for legacy usages.
|
||||
///
|
||||
/// If this is a double curry thunk, return the original DeclRefExpr.
|
||||
/// If this is a single curry thunk, return the ApplyExpr for the self call.
|
||||
/// Otherwise, return null.
|
||||
/// The behavior is as follows, based on the kind:
|
||||
/// - for double curry thunks, returns the original DeclRefExpr.
|
||||
/// - for single curry thunks, returns the ApplyExpr for the self call.
|
||||
/// - otherwise, returns nullptr for convenience.
|
||||
Expr *getUnwrappedCurryThunkExpr() const;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
|
||||
@@ -535,7 +535,8 @@ namespace {
|
||||
cs.cacheExprTypes(base);
|
||||
|
||||
return buildMemberRef(base, SourceLoc(), overload, loc, locator,
|
||||
locator, implicit, semantics);
|
||||
locator, implicit, /*extraUncurryLevel=*/false,
|
||||
semantics);
|
||||
}
|
||||
|
||||
if (isa<TypeDecl>(decl) && !isa<ModuleDecl>(decl)) {
|
||||
@@ -675,11 +676,6 @@ namespace {
|
||||
prev = result;
|
||||
}
|
||||
|
||||
// Invalid case -- direct call of a metatype. Has one less argument
|
||||
// application because there's no ".init".
|
||||
if (isa<ApplyExpr>(ExprStack.back()))
|
||||
argCount--;
|
||||
|
||||
return argCount;
|
||||
}
|
||||
|
||||
@@ -737,6 +733,11 @@ namespace {
|
||||
unsigned maxArgCount = getNaturalArgumentCount(member);
|
||||
unsigned depth = ExprStack.size() - getArgCount(maxArgCount);
|
||||
|
||||
// Invalid case -- direct call of a metatype. Has one less argument
|
||||
// application because there's no ".init".
|
||||
if (isa<ApplyExpr>(ExprStack.back()))
|
||||
depth++;
|
||||
|
||||
// Create the opaque opened value. If we started with a
|
||||
// metatype, it's a metatype.
|
||||
Type opaqueType = archetype;
|
||||
@@ -804,7 +805,7 @@ namespace {
|
||||
SelectedOverload overload, DeclNameLoc memberLoc,
|
||||
ConstraintLocatorBuilder locator,
|
||||
ConstraintLocatorBuilder memberLocator, bool Implicit,
|
||||
AccessSemantics semantics) {
|
||||
bool extraUncurryLevel, AccessSemantics semantics) {
|
||||
auto choice = overload.choice;
|
||||
auto openedType = overload.openedType;
|
||||
auto openedFullType = overload.openedFullType;
|
||||
@@ -830,7 +831,6 @@ namespace {
|
||||
|
||||
// Build a member reference.
|
||||
auto memberRef = resolveConcreteDeclRef(member, memberLocator);
|
||||
auto refTy = solution.simplifyType(openedFullType);
|
||||
|
||||
// If we're referring to the member of a module, it's just a simple
|
||||
// reference.
|
||||
@@ -838,7 +838,7 @@ namespace {
|
||||
assert(semantics == AccessSemantics::Ordinary &&
|
||||
"Direct property access doesn't make sense for this");
|
||||
auto ref = new (context) DeclRefExpr(memberRef, memberLoc, Implicit);
|
||||
cs.setType(ref, refTy);
|
||||
cs.setType(ref, simplifyType(openedFullType));
|
||||
ref->setFunctionRefKind(choice.getFunctionRefKind());
|
||||
auto *DSBI = cs.cacheType(new (context) DotSyntaxBaseIgnoredExpr(
|
||||
base, dotLoc, ref, cs.getType(ref)));
|
||||
@@ -857,6 +857,11 @@ namespace {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool isUnboundInstanceMember =
|
||||
(!baseIsInstance && member->isInstanceMember());
|
||||
|
||||
auto refTy = simplifyType(openedFullType);
|
||||
|
||||
// The formal type of the 'self' value for the member's declaration.
|
||||
Type containerTy = getBaseType(refTy->castTo<FunctionType>());
|
||||
|
||||
@@ -866,39 +871,21 @@ namespace {
|
||||
|
||||
// If we opened up an existential when referencing this member, update
|
||||
// the base accordingly.
|
||||
bool openedExistential = false;
|
||||
|
||||
// For a partial application, we have to open the existential inside
|
||||
// the thunk itself.
|
||||
auto knownOpened = solution.OpenedExistentialTypes.find(
|
||||
getConstraintSystem().getConstraintLocator(
|
||||
memberLocator));
|
||||
bool openedExistential = false;
|
||||
if (knownOpened != solution.OpenedExistentialTypes.end()) {
|
||||
// Open the existential before performing the member reference.
|
||||
base = openExistentialReference(base, knownOpened->second, member);
|
||||
baseTy = knownOpened->second;
|
||||
selfTy = baseTy;
|
||||
openedExistential = true;
|
||||
}
|
||||
|
||||
// If this is a method whose result type is dynamic Self, or a
|
||||
// construction, replace the result type with the actual object type.
|
||||
Type dynamicSelfFnType;
|
||||
if (!member->getDeclContext()->getSelfProtocolDecl()) {
|
||||
if (auto func = dyn_cast<AbstractFunctionDecl>(member)) {
|
||||
if (func->hasDynamicSelfResult() &&
|
||||
!baseTy->getOptionalObjectType()) {
|
||||
refTy = refTy->replaceCovariantResultType(containerTy, 2);
|
||||
if (!baseTy->isEqual(containerTy)) {
|
||||
dynamicSelfFnType = refTy->replaceCovariantResultType(baseTy, 2);
|
||||
}
|
||||
}
|
||||
} else if (auto *decl = dyn_cast<VarDecl>(member)) {
|
||||
if (decl->getValueInterfaceType()->hasDynamicSelfType()) {
|
||||
refTy = refTy->replaceCovariantResultType(containerTy, 1);
|
||||
if (!baseTy->isEqual(containerTy)) {
|
||||
dynamicSelfFnType = refTy->replaceCovariantResultType(baseTy, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// References to properties with accessors and storage usually go
|
||||
// through the accessors, but sometimes are direct.
|
||||
if (auto *VD = dyn_cast<VarDecl>(member)) {
|
||||
@@ -952,9 +939,9 @@ namespace {
|
||||
|
||||
// If the base was an opened existential, erase the opened
|
||||
// existential.
|
||||
if (openedExistential &&
|
||||
refType->hasOpenedExistential(knownOpened->second)) {
|
||||
refType = refType->eraseOpenedExistential(knownOpened->second);
|
||||
if (openedExistential) {
|
||||
refType = refType->eraseOpenedExistential(
|
||||
baseTy->castTo<OpenedArchetypeType>());
|
||||
}
|
||||
|
||||
cs.setType(ref, refType);
|
||||
@@ -1003,7 +990,7 @@ namespace {
|
||||
|
||||
// For properties, build member references.
|
||||
if (isa<VarDecl>(member)) {
|
||||
if (!baseIsInstance && member->isInstanceMember()) {
|
||||
if (isUnboundInstanceMember) {
|
||||
assert(memberLocator.getBaseLocator() &&
|
||||
cs.UnevaluatedRootExprs.count(
|
||||
memberLocator.getBaseLocator()->getAnchor()) &&
|
||||
@@ -1020,31 +1007,46 @@ namespace {
|
||||
memberLoc, Implicit, semantics);
|
||||
memberRefExpr->setIsSuper(isSuper);
|
||||
|
||||
// Skip the synthesized 'self' input type of the opened type.
|
||||
cs.setType(memberRefExpr, simplifyType(openedType));
|
||||
Expr *result = memberRefExpr;
|
||||
closeExistential(result, locator);
|
||||
if (dynamicSelfFnType) {
|
||||
result = new (context) CovariantReturnConversionExpr(result,
|
||||
dynamicSelfFnType);
|
||||
cs.cacheType(result);
|
||||
cs.setType(result, simplifyType(openedType));
|
||||
|
||||
if (cast<VarDecl>(member)->getValueInterfaceType()
|
||||
->hasDynamicSelfType()) {
|
||||
if (!baseTy->isEqual(containerTy)) {
|
||||
result = new (context) CovariantReturnConversionExpr(
|
||||
result, simplifyType(openedType));
|
||||
cs.cacheType(result);
|
||||
}
|
||||
}
|
||||
return forceUnwrapIfExpected(result, choice, memberLocator);
|
||||
}
|
||||
|
||||
if (member->getInterfaceType()->hasDynamicSelfType())
|
||||
refTy = refTy->replaceCovariantResultType(containerTy, 2);
|
||||
|
||||
// Handle all other references.
|
||||
auto declRefExpr = new (context) DeclRefExpr(memberRef, memberLoc,
|
||||
Implicit, semantics);
|
||||
declRefExpr->setFunctionRefKind(choice.getFunctionRefKind());
|
||||
declRefExpr->setType(refTy);
|
||||
cs.setType(declRefExpr, refTy);
|
||||
Expr *ref = declRefExpr;
|
||||
|
||||
// If the reference needs to be converted, do so now.
|
||||
if (dynamicSelfFnType) {
|
||||
ref = new (context) CovariantFunctionConversionExpr(ref,
|
||||
// If this is a method whose result type is dynamic Self, or a
|
||||
// construction, replace the result type with the actual object type.
|
||||
if (!member->getDeclContext()->getSelfProtocolDecl()) {
|
||||
if (auto func = dyn_cast<AbstractFunctionDecl>(member)) {
|
||||
if (func->hasDynamicSelfResult() &&
|
||||
!baseTy->getOptionalObjectType()) {
|
||||
if (!baseTy->isEqual(containerTy)) {
|
||||
auto dynamicSelfFnType = refTy->replaceCovariantResultType(baseTy, 2);
|
||||
ref = new (context) CovariantFunctionConversionExpr(ref,
|
||||
dynamicSelfFnType);
|
||||
cs.cacheType(ref);
|
||||
cs.cacheType(ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ApplyExpr *apply;
|
||||
@@ -1052,7 +1054,13 @@ namespace {
|
||||
// FIXME: Provide type annotation.
|
||||
ref = forceUnwrapIfExpected(ref, choice, memberLocator);
|
||||
apply = new (context) ConstructorRefCallExpr(ref, base);
|
||||
} else if (!baseIsInstance && member->isInstanceMember()) {
|
||||
} else if (isUnboundInstanceMember) {
|
||||
auto refType = cs.simplifyType(openedType);
|
||||
if (!cs.getType(ref)->isEqual(refType)) {
|
||||
ref = new (context) FunctionConversionExpr(ref, refType);
|
||||
cs.cacheType(ref);
|
||||
}
|
||||
|
||||
// Reference to an unbound instance method.
|
||||
Expr *result = new (context) DotSyntaxBaseIgnoredExpr(base, dotLoc,
|
||||
ref,
|
||||
@@ -2339,7 +2347,7 @@ namespace {
|
||||
return buildMemberRef(
|
||||
expr->getBase(), expr->getDotLoc(), selected, expr->getNameLoc(),
|
||||
cs.getConstraintLocator(expr), memberLocator, expr->isImplicit(),
|
||||
expr->getAccessSemantics());
|
||||
/*extraUncurryLevel=*/false, expr->getAccessSemantics());
|
||||
}
|
||||
|
||||
Expr *visitDynamicMemberRefExpr(DynamicMemberRefExpr *expr) {
|
||||
@@ -2382,7 +2390,8 @@ namespace {
|
||||
auto *exprLoc = cs.getConstraintLocator(expr);
|
||||
auto result = buildMemberRef(
|
||||
base, expr->getDotLoc(), selected, expr->getNameLoc(), exprLoc,
|
||||
memberLocator, expr->isImplicit(), AccessSemantics::Ordinary);
|
||||
memberLocator, expr->isImplicit(), /*extraUncurryLevel=*/true,
|
||||
AccessSemantics::Ordinary);
|
||||
if (!result)
|
||||
return nullptr;
|
||||
|
||||
@@ -2530,7 +2539,8 @@ namespace {
|
||||
if (cs.getType(base)->is<AnyMetatypeType>()) {
|
||||
return buildMemberRef(
|
||||
base, dotLoc, overload, nameLoc, cs.getConstraintLocator(expr),
|
||||
ctorLocator, implicit, AccessSemantics::Ordinary);
|
||||
ctorLocator, implicit, /*extraUncurryLevel=*/true,
|
||||
AccessSemantics::Ordinary);
|
||||
}
|
||||
|
||||
// The subexpression must be either 'self' or 'super'.
|
||||
@@ -2703,7 +2713,8 @@ namespace {
|
||||
case OverloadChoiceKind::DeclViaDynamic:
|
||||
return buildMemberRef(base, dotLoc, selected, nameLoc,
|
||||
cs.getConstraintLocator(expr), memberLocator,
|
||||
implicit, AccessSemantics::Ordinary);
|
||||
implicit, /*extraUncurryLevel=*/false,
|
||||
AccessSemantics::Ordinary);
|
||||
|
||||
case OverloadChoiceKind::TupleIndex: {
|
||||
Type toType = simplifyType(cs.getType(expr));
|
||||
@@ -6547,7 +6558,8 @@ static Expr *buildCallAsFunctionMethodRef(
|
||||
auto *fn = apply->getFn();
|
||||
auto *declRef = rewriter.buildMemberRef(
|
||||
fn, /*dotLoc*/ SourceLoc(), selected, DeclNameLoc(fn->getEndLoc()),
|
||||
calleeLoc, calleeLoc, /*implicit*/ true, AccessSemantics::Ordinary);
|
||||
calleeLoc, calleeLoc, /*implicit*/ true,
|
||||
/*extraUncurryLevel=*/true, AccessSemantics::Ordinary);
|
||||
if (!declRef)
|
||||
return nullptr;
|
||||
declRef->setImplicit(apply->isImplicit());
|
||||
@@ -6581,7 +6593,8 @@ ExprRewriter::finishApplyDynamicCallable(ApplyExpr *apply,
|
||||
// Construct expression referencing the `dynamicallyCall` method.
|
||||
auto member = buildMemberRef(fn, SourceLoc(), selected,
|
||||
DeclNameLoc(method->getNameLoc()), loc, loc,
|
||||
/*implicit*/ true, AccessSemantics::Ordinary);
|
||||
/*implicit=*/true, /*extraUncurryLevel=*/true,
|
||||
AccessSemantics::Ordinary);
|
||||
|
||||
// Construct argument to the method (either an array or dictionary
|
||||
// expression).
|
||||
@@ -6942,7 +6955,8 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
|
||||
// constructor call expr itself has the apply's 'implicitness'.
|
||||
Expr *declRef = buildMemberRef(fn, /*dotLoc=*/SourceLoc(), *selected,
|
||||
DeclNameLoc(fn->getEndLoc()), locator,
|
||||
ctorLocator, /*Implicit=*/true,
|
||||
ctorLocator, /*implicit=*/true,
|
||||
/*extraUncurryLevel=*/true,
|
||||
AccessSemantics::Ordinary);
|
||||
if (!declRef)
|
||||
return nullptr;
|
||||
|
||||
@@ -1454,28 +1454,8 @@ ConstraintSystem::getTypeOfMemberReference(
|
||||
|
||||
openedType = openedType->removeArgumentLabels(numRemovedArgumentLabels);
|
||||
|
||||
if (!outerDC->getSelfProtocolDecl()) {
|
||||
// Class methods returning Self as well as constructors get the
|
||||
// result replaced with the base object type.
|
||||
if (auto func = dyn_cast<AbstractFunctionDecl>(value)) {
|
||||
if (func->hasDynamicSelfResult() &&
|
||||
!baseObjTy->getOptionalObjectType()) {
|
||||
openedType = openedType->replaceCovariantResultType(baseObjTy, 2);
|
||||
}
|
||||
} else if (auto *decl = dyn_cast<SubscriptDecl>(value)) {
|
||||
if (decl->getElementInterfaceType()->hasDynamicSelfType()) {
|
||||
openedType = openedType->replaceCovariantResultType(baseObjTy, 2);
|
||||
}
|
||||
} else if (auto *decl = dyn_cast<VarDecl>(value)) {
|
||||
if (decl->getValueInterfaceType()->hasDynamicSelfType()) {
|
||||
openedType = openedType->replaceCovariantResultType(baseObjTy, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we are looking at a member of an existential, open the existential.
|
||||
Type baseOpenedTy = baseObjTy;
|
||||
|
||||
if (baseObjTy->isExistentialType()) {
|
||||
auto openedArchetype = OpenedArchetypeType::get(baseObjTy);
|
||||
OpenedExistentialTypes.push_back({ getConstraintLocator(locator),
|
||||
@@ -1484,8 +1464,7 @@ ConstraintSystem::getTypeOfMemberReference(
|
||||
}
|
||||
|
||||
// Constrain the 'self' object type.
|
||||
auto openedFnType = openedType->castTo<FunctionType>();
|
||||
auto openedParams = openedFnType->getParams();
|
||||
auto openedParams = openedType->castTo<FunctionType>()->getParams();
|
||||
assert(openedParams.size() == 1);
|
||||
|
||||
Type selfObjTy = openedParams.front().getPlainType()->getMetatypeInstanceType();
|
||||
@@ -1513,16 +1492,35 @@ ConstraintSystem::getTypeOfMemberReference(
|
||||
}
|
||||
|
||||
// Compute the type of the reference.
|
||||
Type type;
|
||||
Type type = openedType;
|
||||
|
||||
if (!outerDC->getSelfProtocolDecl()) {
|
||||
// Class methods returning Self as well as constructors get the
|
||||
// result replaced with the base object type.
|
||||
if (auto func = dyn_cast<AbstractFunctionDecl>(value)) {
|
||||
if (func->hasDynamicSelfResult() &&
|
||||
!baseObjTy->getOptionalObjectType()) {
|
||||
type = type->replaceCovariantResultType(baseObjTy, 2);
|
||||
}
|
||||
} else if (auto *decl = dyn_cast<SubscriptDecl>(value)) {
|
||||
if (decl->getElementInterfaceType()->hasDynamicSelfType()) {
|
||||
type = type->replaceCovariantResultType(baseObjTy, 2);
|
||||
}
|
||||
} else if (auto *decl = dyn_cast<VarDecl>(value)) {
|
||||
if (decl->getValueInterfaceType()->hasDynamicSelfType()) {
|
||||
type = type->replaceCovariantResultType(baseObjTy, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasAppliedSelf) {
|
||||
// For a static member referenced through a metatype or an instance
|
||||
// member referenced through an instance, strip off the 'self'.
|
||||
type = openedFnType->getResult();
|
||||
type = type->castTo<FunctionType>()->getResult();
|
||||
} else {
|
||||
// For an unbound instance method reference, replace the 'Self'
|
||||
// parameter with the base type.
|
||||
openedType = openedFnType->replaceSelfParameterType(baseObjTy);
|
||||
type = openedType;
|
||||
type = type->replaceSelfParameterType(baseObjTy);
|
||||
}
|
||||
|
||||
// When accessing protocol members with an existential base, replace
|
||||
|
||||
Reference in New Issue
Block a user