Skip to content

Commit 0031873

Browse files
authored
Merge pull request #30084 from slavapestov/sr-75-prep
More Sema cleanups to prepare for curry thunks
2 parents 910af40 + 9452c60 commit 0031873

File tree

6 files changed

+185
-128
lines changed

6 files changed

+185
-128
lines changed

include/swift/AST/Expr.h

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,10 @@ class alignas(8) Expr {
284284
Discriminator : 16
285285
);
286286

287-
SWIFT_INLINE_BITFIELD(AutoClosureExpr, AbstractClosureExpr, 1,
288-
/// True if this autoclosure was built for a function conversion, and
289-
/// not an actual @autoclosure parameter.
290-
IsThunk : 1
287+
SWIFT_INLINE_BITFIELD(AutoClosureExpr, AbstractClosureExpr, 2,
288+
/// If the autoclosure was built for a curry thunk, the thunk kind is
289+
/// stored here.
290+
Kind : 2
291291
);
292292

293293
SWIFT_INLINE_BITFIELD(ClosureExpr, AbstractClosureExpr, 1,
@@ -3790,22 +3790,36 @@ class AutoClosureExpr : public AbstractClosureExpr {
37903790
BraceStmt *Body;
37913791

37923792
public:
3793+
enum class Kind : uint8_t {
3794+
// An autoclosure with type () -> Result. Formed from type checking an
3795+
// @autoclosure argument in a function call.
3796+
None = 0,
3797+
3798+
// An autoclosure with type (Args...) -> Result. Formed from type checking a
3799+
// partial application.
3800+
SingleCurryThunk = 1,
3801+
3802+
// An autoclosure with type (Self) -> (Args...) -> Result. Formed from type
3803+
// checking a partial application.
3804+
DoubleCurryThunk = 2
3805+
};
3806+
37933807
AutoClosureExpr(Expr *Body, Type ResultTy, unsigned Discriminator,
37943808
DeclContext *Parent)
37953809
: AbstractClosureExpr(ExprKind::AutoClosure, ResultTy, /*Implicit=*/true,
37963810
Discriminator, Parent) {
37973811
if (Body != nullptr)
37983812
setBody(Body);
37993813

3800-
Bits.AutoClosureExpr.IsThunk = false;
3814+
Bits.AutoClosureExpr.Kind = 0;
38013815
}
38023816

3803-
bool isThunk() const {
3804-
return Bits.AutoClosureExpr.IsThunk;
3817+
Kind getThunkKind() const {
3818+
return Kind(Bits.AutoClosureExpr.Kind);
38053819
}
38063820

3807-
void setIsThunk(bool isThunk) {
3808-
Bits.AutoClosureExpr.IsThunk = isThunk;
3821+
void setThunkKind(Kind K) {
3822+
Bits.AutoClosureExpr.Kind = uint8_t(K);
38093823
}
38103824

38113825
SourceRange getSourceRange() const;
@@ -3824,6 +3838,16 @@ class AutoClosureExpr : public AbstractClosureExpr {
38243838
/// The body of an autoclosure always consists of a single expression.
38253839
Expr *getSingleExpressionBody() const;
38263840

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.
3844+
///
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.
3849+
Expr *getUnwrappedCurryThunkExpr() const;
3850+
38273851
// Implement isa/cast/dyncast/etc.
38283852
static bool classof(const Expr *E) {
38293853
return E->getKind() == ExprKind::AutoClosure;

lib/AST/Expr.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1843,6 +1843,46 @@ Expr *AutoClosureExpr::getSingleExpressionBody() const {
18431843
return cast<ReturnStmt>(Body->getFirstElement().get<Stmt *>())->getResult();
18441844
}
18451845

1846+
Expr *AutoClosureExpr::getUnwrappedCurryThunkExpr() const {
1847+
switch (getThunkKind()) {
1848+
case AutoClosureExpr::Kind::None:
1849+
break;
1850+
1851+
case AutoClosureExpr::Kind::SingleCurryThunk: {
1852+
auto *body = getSingleExpressionBody();
1853+
body = body->getSemanticsProvidingExpr();
1854+
if (auto *outerCall = dyn_cast<ApplyExpr>(body)) {
1855+
return outerCall->getFn();
1856+
}
1857+
1858+
assert(false && "Malformed curry thunk?");
1859+
break;
1860+
}
1861+
1862+
case AutoClosureExpr::Kind::DoubleCurryThunk: {
1863+
auto *body = getSingleExpressionBody();
1864+
if (auto *innerClosure = dyn_cast<AutoClosureExpr>(body)) {
1865+
assert(innerClosure->getThunkKind() ==
1866+
AutoClosureExpr::Kind::SingleCurryThunk);
1867+
auto *innerBody = innerClosure->getSingleExpressionBody();
1868+
innerBody = innerBody->getSemanticsProvidingExpr();
1869+
if (auto *outerCall = dyn_cast<ApplyExpr>(innerBody)) {
1870+
if (auto *innerCall = dyn_cast<ApplyExpr>(outerCall->getFn())) {
1871+
if (auto *declRef = dyn_cast<DeclRefExpr>(innerCall->getFn())) {
1872+
return declRef;
1873+
}
1874+
}
1875+
}
1876+
}
1877+
1878+
assert(false && "Malformed curry thunk?");
1879+
break;
1880+
}
1881+
}
1882+
1883+
return nullptr;
1884+
}
1885+
18461886
FORWARD_SOURCE_LOCS_TO(UnresolvedPatternExpr, subPattern)
18471887

18481888
TypeExpr::TypeExpr(TypeLoc TyLoc)

lib/IDE/SourceEntityWalker.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,21 @@ std::pair<bool, Expr *> SemaAnnotator::walkToExprPre(Expr *E) {
256256
if (auto *CtorRefE = dyn_cast<ConstructorRefCallExpr>(E))
257257
CtorRefs.push_back(CtorRefE);
258258

259+
if (auto *ACE = dyn_cast<AutoClosureExpr>(E)) {
260+
if (auto *SubExpr = ACE->getUnwrappedCurryThunkExpr()) {
261+
if (auto *DRE = dyn_cast<DeclRefExpr>(SubExpr)) {
262+
if (!passReference(DRE->getDecl(), DRE->getType(),
263+
DRE->getNameLoc(),
264+
ReferenceMetaData(getReferenceKind(Parent.getAsExpr(), DRE),
265+
OpAccess))) {
266+
return { false, nullptr };
267+
}
268+
269+
return { true, E };
270+
}
271+
}
272+
}
273+
259274
if (!isa<InOutExpr>(E) &&
260275
!isa<LoadExpr>(E) &&
261276
!isa<OpenExistentialExpr>(E) &&

lib/IDE/Utils.cpp

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -989,28 +989,9 @@ std::pair<Type, ConcreteDeclRef> swift::ide::getReferencedDecl(Expr *expr) {
989989
expr = selfApplyExpr->getFn();
990990

991991
// Look through curry thunks.
992-
if (auto *closure = dyn_cast<AutoClosureExpr>(expr)) {
993-
if (closure->isThunk()) {
994-
auto *body = closure->getSingleExpressionBody();
995-
if (isa<AutoClosureExpr>(body) &&
996-
closure->getParameters()->size() == 1)
997-
expr = closure->getSingleExpressionBody();
998-
}
999-
}
1000-
1001-
if (auto *closure = dyn_cast<AutoClosureExpr>(expr)) {
1002-
if (closure->isThunk()) {
1003-
auto *body = closure->getSingleExpressionBody();
1004-
body = body->getSemanticsProvidingExpr();
1005-
if (auto *outerCall = dyn_cast<ApplyExpr>(body)) {
1006-
if (auto *innerCall = dyn_cast<ApplyExpr>(outerCall->getFn())) {
1007-
if (auto *declRef = dyn_cast<DeclRefExpr>(innerCall->getFn())) {
1008-
expr = declRef;
1009-
}
1010-
}
1011-
}
1012-
}
1013-
}
992+
if (auto *closure = dyn_cast<AutoClosureExpr>(expr))
993+
if (auto *unwrappedThunk = closure->getUnwrappedCurryThunkExpr())
994+
expr = unwrappedThunk;
1014995

1015996
// If this is an IUO result, unwrap the optional type.
1016997
auto refDecl = expr->getReferencedDecl();

0 commit comments

Comments
 (0)