Skip to content

Commit 7693167

Browse files
authored
Merge pull request #60438 from hamishknight/factor-in-factor-out
2 parents b45dfa1 + 6b9bcf3 commit 7693167

13 files changed

+183
-169
lines changed

include/swift/AST/ArgumentList.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ class Argument final {
5151
return Argument(SourceLoc(), Identifier(), expr);
5252
}
5353

54+
/// Make an implicit unlabeled 'inout' argument.
55+
static Argument implicitInOut(ASTContext &ctx, Expr *expr);
56+
5457
SourceLoc getStartLoc() const { return getSourceRange().Start; }
5558
SourceLoc getEndLoc() const { return getSourceRange().End; }
5659
SourceRange getSourceRange() const;
@@ -65,6 +68,11 @@ class Argument final {
6568
/// The argument label written in the call.
6669
Identifier getLabel() const { return Label; }
6770

71+
/// Whether the argument has a non-empty label. Note that this returns `false`
72+
/// for an explicitly specified empty label e.g `_: {}` for a trailing
73+
/// closure.
74+
bool hasLabel() const { return !Label.empty(); }
75+
6876
/// Set a new argument label.
6977
///
7078
/// Note this is marked \c & to prevent its use on an rvalue Argument vended

include/swift/AST/Expr.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4763,8 +4763,13 @@ class DotSyntaxCallExpr : public SelfApplyExpr {
47634763
}
47644764

47654765
public:
4766+
/// Create a new method reference to \p fnExpr on the base value \p baseArg.
4767+
///
4768+
/// If this is for a 'mutating' method, \p baseArg should be created using
4769+
/// \c Argument::implicitInOut. Otherwise, \p Argument::unlabeled should be
4770+
/// used. \p baseArg must not be labeled.
47664771
static DotSyntaxCallExpr *create(ASTContext &ctx, Expr *fnExpr,
4767-
SourceLoc dotLoc, Expr *baseExpr,
4772+
SourceLoc dotLoc, Argument baseArg,
47684773
Type ty = Type());
47694774

47704775
SourceLoc getDotLoc() const { return DotLoc; }

lib/AST/ArgumentList.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,19 @@ SourceRange Argument::getSourceRange() const {
3535
return SourceRange(labelLoc, exprEndLoc);
3636
}
3737

38+
Argument Argument::implicitInOut(ASTContext &ctx, Expr *expr) {
39+
assert(!isa<InOutExpr>(expr) && "Cannot nest InOutExpr");
40+
41+
// Eventually this will set an 'inout' bit on Argument, but for now,
42+
// synthesize in the InOutExpr.
43+
Type objectTy;
44+
if (auto subTy = expr->getType())
45+
objectTy = subTy->castTo<LValueType>()->getObjectType();
46+
47+
return Argument::unlabeled(
48+
new (ctx) InOutExpr(SourceLoc(), expr, objectTy, /*isImplicit*/ true));
49+
}
50+
3851
bool Argument::isInOut() const {
3952
return ArgExpr->isSemanticallyInOutExpr();
4053
}

lib/AST/Expr.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,9 +1574,10 @@ BinaryExpr *BinaryExpr::create(ASTContext &ctx, Expr *lhs, Expr *fn, Expr *rhs,
15741574
}
15751575

15761576
DotSyntaxCallExpr *DotSyntaxCallExpr::create(ASTContext &ctx, Expr *fnExpr,
1577-
SourceLoc dotLoc, Expr *baseExpr,
1577+
SourceLoc dotLoc, Argument baseArg,
15781578
Type ty) {
1579-
auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {baseExpr});
1579+
assert(!baseArg.hasLabel());
1580+
auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {baseArg.getExpr()});
15801581
return new (ctx) DotSyntaxCallExpr(fnExpr, dotLoc, argList, ty);
15811582
}
15821583

lib/ClangImporter/ClangImporter.cpp

Lines changed: 68 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -4444,29 +4444,23 @@ DeclRefExpr *getInteropStaticCastDeclRefExpr(ASTContext &ctx,
44444444
// %2 = __swift_interopStaticCast<UnsafeMutablePointer<Base>?>(%1)
44454445
// %3 = %2!
44464446
// return %3.pointee
4447-
MemberRefExpr *getInOutSelfInteropStaticCast(FuncDecl *funcDecl,
4448-
NominalTypeDecl *baseStruct,
4449-
NominalTypeDecl *derivedStruct) {
4447+
MemberRefExpr *getSelfInteropStaticCast(FuncDecl *funcDecl,
4448+
NominalTypeDecl *baseStruct,
4449+
NominalTypeDecl *derivedStruct) {
44504450
auto &ctx = funcDecl->getASTContext();
44514451

4452-
auto inoutSelf = [&ctx](FuncDecl *funcDecl) {
4453-
auto inoutSelfDecl = funcDecl->getImplicitSelfDecl();
4452+
auto mutableSelf = [&ctx](FuncDecl *funcDecl) {
4453+
auto selfDecl = funcDecl->getImplicitSelfDecl();
44544454

4455-
auto inoutSelfRef =
4456-
new (ctx) DeclRefExpr(inoutSelfDecl, DeclNameLoc(), /*implicit*/ true);
4457-
inoutSelfRef->setType(LValueType::get(inoutSelfDecl->getInterfaceType()));
4455+
auto selfRef =
4456+
new (ctx) DeclRefExpr(selfDecl, DeclNameLoc(), /*implicit*/ true);
4457+
selfRef->setType(LValueType::get(selfDecl->getInterfaceType()));
44584458

4459-
auto inoutSelf = new (ctx) InOutExpr(
4460-
SourceLoc(), inoutSelfRef,
4461-
funcDecl->mapTypeIntoContext(inoutSelfDecl->getValueInterfaceType()),
4462-
/*implicit*/ true);
4463-
inoutSelf->setType(InOutType::get(inoutSelfDecl->getInterfaceType()));
4464-
4465-
return inoutSelf;
4459+
return selfRef;
44664460
}(funcDecl);
44674461

44684462
auto createCallToBuiltin = [&](Identifier name, ArrayRef<Type> substTypes,
4469-
Expr *arg) {
4463+
Argument arg) {
44704464
auto builtinFn = cast<FuncDecl>(getBuiltinValueDecl(ctx, name));
44714465
auto substMap =
44724466
SubstitutionMap::get(builtinFn->getGenericSignature(), substTypes,
@@ -4479,22 +4473,23 @@ MemberRefExpr *getInOutSelfInteropStaticCast(FuncDecl *funcDecl,
44794473
if (auto genericFnType = dyn_cast<GenericFunctionType>(fnType.getPointer()))
44804474
fnType = genericFnType->substGenericArgs(substMap);
44814475
builtinFnRefExpr->setType(fnType);
4482-
auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {arg});
4476+
auto *argList = ArgumentList::createImplicit(ctx, {arg});
44834477
auto callExpr = CallExpr::create(ctx, builtinFnRefExpr, argList, /*implicit*/ true);
44844478
callExpr->setThrows(false);
44854479
return callExpr;
44864480
};
44874481

4488-
auto rawSelfPointer =
4489-
createCallToBuiltin(ctx.getIdentifier("addressof"),
4490-
{derivedStruct->getSelfInterfaceType()}, inoutSelf);
4482+
auto rawSelfPointer = createCallToBuiltin(
4483+
ctx.getIdentifier("addressof"), {derivedStruct->getSelfInterfaceType()},
4484+
Argument::implicitInOut(ctx, mutableSelf));
44914485
rawSelfPointer->setType(ctx.TheRawPointerType);
44924486

44934487
auto derivedPtrType = derivedStruct->getSelfInterfaceType()->wrapInPointer(
44944488
PTK_UnsafeMutablePointer);
4495-
auto selfPointer = createCallToBuiltin(
4496-
ctx.getIdentifier("reinterpretCast"),
4497-
{ctx.TheRawPointerType, derivedPtrType}, rawSelfPointer);
4489+
auto selfPointer =
4490+
createCallToBuiltin(ctx.getIdentifier("reinterpretCast"),
4491+
{ctx.TheRawPointerType, derivedPtrType},
4492+
Argument::unlabeled(rawSelfPointer));
44984493
selfPointer->setType(derivedPtrType);
44994494

45004495
auto staticCastRefExpr = getInteropStaticCastDeclRefExpr(
@@ -4554,14 +4549,11 @@ synthesizeBaseClassMethodBody(AbstractFunctionDecl *afd, void *context) {
45544549
forwardingParams.push_back(paramRefExpr);
45554550
}
45564551

4557-
Expr *casted = nullptr;
4558-
if (funcDecl->isMutating()) {
4559-
auto pointeeMemberRefExpr =
4560-
getInOutSelfInteropStaticCast(funcDecl, baseStruct, derivedStruct);
4561-
casted = new (ctx) InOutExpr(SourceLoc(), pointeeMemberRefExpr, baseType,
4562-
/*implicit*/ true);
4563-
casted->setType(InOutType::get(baseType));
4564-
} else {
4552+
Argument casted = [&]() {
4553+
if (funcDecl->isMutating()) {
4554+
return Argument::implicitInOut(
4555+
ctx, getSelfInteropStaticCast(funcDecl, baseStruct, derivedStruct));
4556+
}
45654557
auto *selfDecl = funcDecl->getImplicitSelfDecl();
45664558
auto selfExpr = new (ctx) DeclRefExpr(selfDecl, DeclNameLoc(),
45674559
/*implicit*/ true);
@@ -4575,8 +4567,8 @@ synthesizeBaseClassMethodBody(AbstractFunctionDecl *afd, void *context) {
45754567
auto castedCall = CallExpr::createImplicit(ctx, staticCastRefExpr, argList);
45764568
castedCall->setType(baseType);
45774569
castedCall->setThrows(false);
4578-
casted = castedCall;
4579-
}
4570+
return Argument::unlabeled(castedCall);
4571+
}();
45804572

45814573
auto *baseMemberExpr =
45824574
new (ctx) DeclRefExpr(ConcreteDeclRef(baseMember), DeclNameLoc(),
@@ -4680,7 +4672,7 @@ synthesizeBaseClassFieldSetterBody(AbstractFunctionDecl *afd, void *context) {
46804672
cast<NominalTypeDecl>(setterDecl->getDeclContext()->getAsDecl());
46814673

46824674
auto *pointeePropertyRefExpr =
4683-
getInOutSelfInteropStaticCast(setterDecl, baseStruct, derivedStruct);
4675+
getSelfInteropStaticCast(setterDecl, baseStruct, derivedStruct);
46844676

46854677
Expr *storedRef = nullptr;
46864678
if (auto subscript = dyn_cast<SubscriptDecl>(baseClassVar)) {
@@ -5395,7 +5387,7 @@ static ValueDecl *rewriteIntegerTypes(SubstitutionMap subst, ValueDecl *oldDecl,
53955387
return newDecl;
53965388
}
53975389

5398-
static Expr *createSelfExpr(FuncDecl *fnDecl) {
5390+
static Argument createSelfArg(FuncDecl *fnDecl) {
53995391
ASTContext &ctx = fnDecl->getASTContext();
54005392

54015393
auto selfDecl = fnDecl->getImplicitSelfDecl();
@@ -5404,16 +5396,10 @@ static Expr *createSelfExpr(FuncDecl *fnDecl) {
54045396

54055397
if (!fnDecl->isMutating()) {
54065398
selfRefExpr->setType(selfDecl->getInterfaceType());
5407-
return selfRefExpr;
5399+
return Argument::unlabeled(selfRefExpr);
54085400
}
54095401
selfRefExpr->setType(LValueType::get(selfDecl->getInterfaceType()));
5410-
5411-
auto inoutSelfExpr = new (ctx) InOutExpr(
5412-
SourceLoc(), selfRefExpr,
5413-
fnDecl->mapTypeIntoContext(selfDecl->getValueInterfaceType()),
5414-
/*isImplicit*/ true);
5415-
inoutSelfExpr->setType(InOutType::get(selfDecl->getInterfaceType()));
5416-
return inoutSelfExpr;
5402+
return Argument::implicitInOut(ctx, selfRefExpr);
54175403
}
54185404

54195405
// Synthesize a thunk body for the function created in
@@ -5434,30 +5420,30 @@ synthesizeDependentTypeThunkParamForwarding(AbstractFunctionDecl *afd, void *con
54345420
paramIndex++;
54355421
continue;
54365422
}
5423+
auto paramTy = param->getType();
5424+
auto isInOut = param->isInOut();
5425+
auto specParamTy =
5426+
specializedFuncDecl->getParameters()->get(paramIndex)->getType();
54375427

54385428
Expr *paramRefExpr = new (ctx) DeclRefExpr(param, DeclNameLoc(),
54395429
/*Implicit=*/true);
5440-
paramRefExpr->setType(param->getType());
5441-
5442-
if (param->isInOut()) {
5443-
paramRefExpr->setType(LValueType::get(param->getType()));
5444-
5445-
paramRefExpr = new (ctx) InOutExpr(
5446-
SourceLoc(), paramRefExpr, param->getType(), /*isImplicit*/ true);
5447-
paramRefExpr->setType(InOutType::get(param->getType()));
5448-
}
5449-
5450-
auto specParamTy = specializedFuncDecl->getParameters()->get(paramIndex)->getType();
5430+
paramRefExpr->setType(isInOut ? LValueType::get(paramTy) : paramTy);
54515431

5452-
Expr *argExpr = nullptr;
5453-
if (specParamTy->isEqual(param->getType())) {
5454-
argExpr = paramRefExpr;
5455-
} else {
5456-
argExpr = ForcedCheckedCastExpr::createImplicit(ctx, paramRefExpr,
5457-
specParamTy);
5458-
}
5459-
5460-
forwardingParams.push_back(Argument(SourceLoc(), Identifier(), argExpr));
5432+
Argument arg = [&]() {
5433+
if (isInOut) {
5434+
assert(specParamTy->isEqual(paramTy));
5435+
return Argument::implicitInOut(ctx, paramRefExpr);
5436+
}
5437+
Expr *argExpr = nullptr;
5438+
if (specParamTy->isEqual(paramTy)) {
5439+
argExpr = paramRefExpr;
5440+
} else {
5441+
argExpr = ForcedCheckedCastExpr::createImplicit(ctx, paramRefExpr,
5442+
specParamTy);
5443+
}
5444+
return Argument::unlabeled(argExpr);
5445+
}();
5446+
forwardingParams.push_back(arg);
54615447
paramIndex++;
54625448
}
54635449

@@ -5466,8 +5452,9 @@ synthesizeDependentTypeThunkParamForwarding(AbstractFunctionDecl *afd, void *con
54665452
specializedFuncDeclRef->setType(specializedFuncDecl->getInterfaceType());
54675453

54685454
if (specializedFuncDecl->isInstanceMember()) {
5469-
auto selfExpr = createSelfExpr(thunkDecl);
5470-
auto *memberCall = DotSyntaxCallExpr::create(ctx, specializedFuncDeclRef, SourceLoc(), selfExpr);
5455+
auto selfArg = createSelfArg(thunkDecl);
5456+
auto *memberCall = DotSyntaxCallExpr::create(ctx, specializedFuncDeclRef,
5457+
SourceLoc(), selfArg);
54715458
memberCall->setThrows(false);
54725459
auto resultType = specializedFuncDecl->getInterfaceType()->getAs<FunctionType>()->getResult();
54735460
specializedFuncDeclRef = memberCall;
@@ -5476,7 +5463,9 @@ synthesizeDependentTypeThunkParamForwarding(AbstractFunctionDecl *afd, void *con
54765463
auto resultType = specializedFuncDecl->getInterfaceType()->getAs<FunctionType>()->getResult();
54775464
auto selfType = cast<NominalTypeDecl>(thunkDecl->getDeclContext()->getAsDecl())->getDeclaredInterfaceType();
54785465
auto selfTypeExpr = TypeExpr::createImplicit(selfType, ctx);
5479-
auto *memberCall = DotSyntaxCallExpr::create(ctx, specializedFuncDeclRef, SourceLoc(), selfTypeExpr);
5466+
auto *memberCall =
5467+
DotSyntaxCallExpr::create(ctx, specializedFuncDeclRef, SourceLoc(),
5468+
Argument::unlabeled(selfTypeExpr));
54805469
memberCall->setThrows(false);
54815470
specializedFuncDeclRef = memberCall;
54825471
specializedFuncDeclRef->setType(resultType);
@@ -5576,28 +5565,26 @@ synthesizeForwardingThunkBody(AbstractFunctionDecl *afd, void *context) {
55765565
if (isa<MetatypeType>(param->getType().getPointer())) {
55775566
continue;
55785567
}
5568+
auto paramTy = param->getType();
5569+
auto isInOut = param->isInOut();
5570+
55795571
Expr *paramRefExpr = new (ctx) DeclRefExpr(param, DeclNameLoc(),
55805572
/*Implicit=*/true);
5581-
paramRefExpr->setType(param->getType());
5582-
5583-
if (param->isInOut()) {
5584-
paramRefExpr->setType(LValueType::get(param->getType()));
5585-
5586-
paramRefExpr = new (ctx) InOutExpr(
5587-
SourceLoc(), paramRefExpr, param->getType(), /*isImplicit*/ true);
5588-
paramRefExpr->setType(InOutType::get(param->getType()));
5589-
}
5573+
paramRefExpr->setType(isInOut ? LValueType::get(paramTy) : paramTy);
55905574

5591-
forwardingParams.push_back(Argument(SourceLoc(), Identifier(), paramRefExpr));
5575+
auto arg = isInOut ? Argument::implicitInOut(ctx, paramRefExpr)
5576+
: Argument::unlabeled(paramRefExpr);
5577+
forwardingParams.push_back(arg);
55925578
}
55935579

55945580
Expr *specializedFuncDeclRef = new (ctx) DeclRefExpr(ConcreteDeclRef(specializedFuncDecl),
55955581
DeclNameLoc(), true);
55965582
specializedFuncDeclRef->setType(specializedFuncDecl->getInterfaceType());
55975583

55985584
if (specializedFuncDecl->isInstanceMember()) {
5599-
auto selfExpr = createSelfExpr(thunkDecl);
5600-
auto *memberCall = DotSyntaxCallExpr::create(ctx, specializedFuncDeclRef, SourceLoc(), selfExpr);
5585+
auto selfArg = createSelfArg(thunkDecl);
5586+
auto *memberCall = DotSyntaxCallExpr::create(ctx, specializedFuncDeclRef,
5587+
SourceLoc(), selfArg);
56015588
memberCall->setThrows(false);
56025589
auto resultType = specializedFuncDecl->getInterfaceType()->getAs<FunctionType>()->getResult();
56035590
specializedFuncDeclRef = memberCall;
@@ -5606,7 +5593,9 @@ synthesizeForwardingThunkBody(AbstractFunctionDecl *afd, void *context) {
56065593
auto resultType = specializedFuncDecl->getInterfaceType()->getAs<FunctionType>()->getResult();
56075594
auto selfType = cast<NominalTypeDecl>(thunkDecl->getDeclContext()->getAsDecl())->getDeclaredInterfaceType();
56085595
auto selfTypeExpr = TypeExpr::createImplicit(selfType, ctx);
5609-
auto *memberCall = DotSyntaxCallExpr::create(ctx, specializedFuncDeclRef, SourceLoc(), selfTypeExpr);
5596+
auto *memberCall =
5597+
DotSyntaxCallExpr::create(ctx, specializedFuncDeclRef, SourceLoc(),
5598+
Argument::unlabeled(selfTypeExpr));
56105599
memberCall->setThrows(false);
56115600
specializedFuncDeclRef = memberCall;
56125601
specializedFuncDeclRef->setType(resultType);

lib/ClangImporter/ImportDecl.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5457,8 +5457,9 @@ Decl *SwiftDeclConverter::importEnumCaseAlias(
54575457
/*implicit*/ true);
54585458
constantRef->setType(enumElt->getInterfaceType());
54595459

5460-
auto instantiate = DotSyntaxCallExpr::create(Impl.SwiftContext, constantRef,
5461-
SourceLoc(), typeRef);
5460+
auto instantiate =
5461+
DotSyntaxCallExpr::create(Impl.SwiftContext, constantRef, SourceLoc(),
5462+
Argument::unlabeled(typeRef));
54625463
instantiate->setType(importedEnumTy);
54635464
instantiate->setThrows(false);
54645465

0 commit comments

Comments
 (0)