Skip to content

Commit 76c6254

Browse files
committed
[AST] Refactor KeyPathExpr constructors
Now that the CSApply just uses components, we can better split up the key path constructors to either accept a set of resolved components, or a parsed root or path.
1 parent d6ac93e commit 76c6254

File tree

5 files changed

+109
-49
lines changed

5 files changed

+109
-49
lines changed

include/swift/AST/Expr.h

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5562,24 +5562,43 @@ class KeyPathExpr : public Expr {
55625562
private:
55635563
llvm::MutableArrayRef<Component> Components;
55645564

5565-
public:
5566-
/// Create a new #keyPath expression.
5567-
KeyPathExpr(ASTContext &C,
5568-
SourceLoc keywordLoc, SourceLoc lParenLoc,
5569-
ArrayRef<Component> components,
5570-
SourceLoc rParenLoc,
5571-
bool isImplicit = false);
5565+
KeyPathExpr(SourceLoc startLoc, Expr *parsedRoot, Expr *parsedPath,
5566+
SourceLoc endLoc, bool hasLeadingDot, bool isObjC,
5567+
bool isImplicit);
55725568

5569+
/// Create a key path with unresolved root and path expressions.
55735570
KeyPathExpr(SourceLoc backslashLoc, Expr *parsedRoot, Expr *parsedPath,
5574-
bool hasLeadingDot, bool isImplicit = false)
5575-
: Expr(ExprKind::KeyPath, isImplicit), StartLoc(backslashLoc),
5576-
EndLoc(parsedPath ? parsedPath->getEndLoc() : parsedRoot->getEndLoc()),
5577-
ParsedRoot(parsedRoot), ParsedPath(parsedPath),
5578-
HasLeadingDot(hasLeadingDot) {
5579-
assert((parsedRoot || parsedPath) &&
5580-
"keypath must have either root or path");
5581-
Bits.KeyPathExpr.IsObjC = false;
5582-
}
5571+
bool hasLeadingDot, bool isImplicit);
5572+
5573+
/// Create a key path with components.
5574+
KeyPathExpr(ASTContext &ctx, SourceLoc startLoc,
5575+
ArrayRef<Component> components, SourceLoc endLoc, bool isObjC,
5576+
bool isImplicit);
5577+
5578+
public:
5579+
/// Create a new parsed Swift key path expression.
5580+
static KeyPathExpr *createParsed(ASTContext &ctx, SourceLoc backslashLoc,
5581+
Expr *parsedRoot, Expr *parsedPath,
5582+
bool hasLeadingDot);
5583+
5584+
/// Create a new parsed #keyPath expression.
5585+
static KeyPathExpr *createParsedPoundKeyPath(ASTContext &ctx,
5586+
SourceLoc keywordLoc,
5587+
SourceLoc lParenLoc,
5588+
ArrayRef<Component> components,
5589+
SourceLoc rParenLoc);
5590+
5591+
/// Create an implicit Swift key path expression with a set of resolved
5592+
/// components.
5593+
static KeyPathExpr *createImplicit(ASTContext &ctx, SourceLoc backslashLoc,
5594+
ArrayRef<Component> components,
5595+
SourceLoc endLoc);
5596+
5597+
/// Create an implicit Swift key path expression with a root and path
5598+
/// expression to be resolved.
5599+
static KeyPathExpr *createImplicit(ASTContext &ctx, SourceLoc backslashLoc,
5600+
Expr *parsedRoot, Expr *parsedPath,
5601+
bool hasLeadingDot);
55835602

55845603
SourceLoc getLoc() const { return StartLoc; }
55855604
SourceRange getSourceRange() const { return SourceRange(StartLoc, EndLoc); }

lib/AST/Expr.cpp

Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1987,17 +1987,64 @@ OpenedArchetypeType *OpenExistentialExpr::getOpenedArchetype() const {
19871987
return type->castTo<OpenedArchetypeType>();
19881988
}
19891989

1990-
KeyPathExpr::KeyPathExpr(ASTContext &C, SourceLoc keywordLoc,
1991-
SourceLoc lParenLoc, ArrayRef<Component> components,
1992-
SourceLoc rParenLoc, bool isImplicit)
1993-
: Expr(ExprKind::KeyPath, isImplicit), StartLoc(keywordLoc),
1994-
LParenLoc(lParenLoc), EndLoc(rParenLoc),
1995-
Components(C.AllocateUninitialized<Component>(components.size())) {
1996-
// Copy components into the AST context.
1997-
std::uninitialized_copy(components.begin(), components.end(),
1998-
Components.begin());
1999-
2000-
Bits.KeyPathExpr.IsObjC = true;
1990+
KeyPathExpr::KeyPathExpr(SourceLoc startLoc, Expr *parsedRoot,
1991+
Expr *parsedPath, SourceLoc endLoc, bool hasLeadingDot,
1992+
bool isObjC, bool isImplicit)
1993+
: Expr(ExprKind::KeyPath, isImplicit), StartLoc(startLoc), EndLoc(endLoc),
1994+
ParsedRoot(parsedRoot), ParsedPath(parsedPath),
1995+
HasLeadingDot(hasLeadingDot) {
1996+
assert(!(isObjC && (parsedRoot || parsedPath)) &&
1997+
"Obj-C key paths should only have components");
1998+
Bits.KeyPathExpr.IsObjC = isObjC;
1999+
}
2000+
2001+
KeyPathExpr::KeyPathExpr(SourceLoc backslashLoc, Expr *parsedRoot,
2002+
Expr *parsedPath, bool hasLeadingDot, bool isImplicit)
2003+
: KeyPathExpr(backslashLoc, parsedRoot, parsedPath,
2004+
parsedPath ? parsedPath->getEndLoc()
2005+
: parsedRoot->getEndLoc(),
2006+
hasLeadingDot, /*isObjC*/ false, isImplicit) {
2007+
assert((parsedRoot || parsedPath) &&
2008+
"Key path must have either root or path");
2009+
}
2010+
2011+
KeyPathExpr::KeyPathExpr(ASTContext &ctx, SourceLoc startLoc,
2012+
ArrayRef<Component> components, SourceLoc endLoc,
2013+
bool isObjC, bool isImplicit)
2014+
: KeyPathExpr(startLoc, /*parsedRoot*/ nullptr, /*parsedPath*/ nullptr,
2015+
endLoc, /*hasLeadingDot*/ false, isObjC, isImplicit) {
2016+
assert(!components.empty());
2017+
Components = ctx.AllocateCopy(components);
2018+
}
2019+
2020+
KeyPathExpr *KeyPathExpr::createParsedPoundKeyPath(
2021+
ASTContext &ctx, SourceLoc keywordLoc, SourceLoc lParenLoc,
2022+
ArrayRef<Component> components, SourceLoc rParenLoc) {
2023+
return new (ctx) KeyPathExpr(ctx, keywordLoc, components, rParenLoc,
2024+
/*isObjC*/ true, /*isImplicit*/ false);
2025+
}
2026+
2027+
KeyPathExpr *KeyPathExpr::createParsed(ASTContext &ctx, SourceLoc backslashLoc,
2028+
Expr *parsedRoot, Expr *parsedPath,
2029+
bool hasLeadingDot) {
2030+
return new (ctx) KeyPathExpr(backslashLoc, parsedRoot, parsedPath,
2031+
hasLeadingDot, /*isImplicit*/ false);
2032+
}
2033+
2034+
KeyPathExpr *KeyPathExpr::createImplicit(ASTContext &ctx,
2035+
SourceLoc backslashLoc,
2036+
ArrayRef<Component> components,
2037+
SourceLoc endLoc) {
2038+
return new (ctx) KeyPathExpr(ctx, backslashLoc, components, endLoc,
2039+
/*isObjC*/ false, /*isImplicit*/ true);
2040+
}
2041+
2042+
KeyPathExpr *KeyPathExpr::createImplicit(ASTContext &ctx,
2043+
SourceLoc backslashLoc,
2044+
Expr *parsedRoot, Expr *parsedPath,
2045+
bool hasLeadingDot) {
2046+
return new (ctx) KeyPathExpr(backslashLoc, parsedRoot, parsedPath,
2047+
hasLeadingDot, /*isImplicit*/ true);
20012048
}
20022049

20032050
void

lib/Parse/ParseExpr.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -656,17 +656,17 @@ ParserResult<Expr> Parser::parseExprKeyPath() {
656656
// Add the code completion expression to the path result.
657657
CodeCompletionExpr *CC = new (Context)
658658
CodeCompletionExpr(pathResult.getPtrOrNull(), Tok.getLoc());
659-
auto keypath = new (Context)
660-
KeyPathExpr(backslashLoc, rootResult.getPtrOrNull(), CC, hasLeadingDot);
659+
auto *keypath = KeyPathExpr::createParsed(
660+
Context, backslashLoc, rootResult.getPtrOrNull(), CC, hasLeadingDot);
661661
if (CodeCompletion)
662662
CodeCompletion->completeExprKeyPath(keypath, DotLoc);
663663
consumeToken(tok::code_complete);
664664
return makeParserCodeCompletionResult(keypath);
665665
}
666666

667-
auto keypath =
668-
new (Context) KeyPathExpr(backslashLoc, rootResult.getPtrOrNull(),
669-
pathResult.getPtrOrNull(), hasLeadingDot);
667+
auto *keypath = KeyPathExpr::createParsed(
668+
Context, backslashLoc, rootResult.getPtrOrNull(),
669+
pathResult.getPtrOrNull(), hasLeadingDot);
670670
return makeParserResult(parseStatus, keypath);
671671
}
672672

@@ -690,8 +690,8 @@ ParserResult<Expr> Parser::parseExprKeyPathObjC() {
690690
auto handleCodeCompletion = [&](SourceLoc DotLoc) -> ParserResult<Expr> {
691691
KeyPathExpr *expr = nullptr;
692692
if (!components.empty()) {
693-
expr = new (Context)
694-
KeyPathExpr(Context, keywordLoc, lParenLoc, components, Tok.getLoc());
693+
expr = KeyPathExpr::createParsedPoundKeyPath(
694+
Context, keywordLoc, lParenLoc, components, Tok.getLoc());
695695
}
696696

697697
if (CodeCompletion)
@@ -764,7 +764,7 @@ ParserResult<Expr> Parser::parseExprKeyPathObjC() {
764764
}
765765

766766
// We're done: create the key-path expression.
767-
return makeParserResult<Expr>(new (Context) KeyPathExpr(
767+
return makeParserResult<Expr>(KeyPathExpr::createParsedPoundKeyPath(
768768
Context, keywordLoc, lParenLoc, components, rParenLoc));
769769
}
770770

lib/Sema/CSApply.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2223,16 +2223,8 @@ namespace {
22232223
auto *anchor = getAsExpr(memberLoc->getAnchor());
22242224

22252225
auto makeKeyPath = [&](ArrayRef<Component> components) -> Expr * {
2226-
// Create a new implicit key path. We pass in anchor as the parsed path
2227-
// to set the end loc, but don't want to keep it as the parsed path,
2228-
// so clear it out after.
2229-
auto *kp = new (ctx) KeyPathExpr(/*backslashLoc*/ dotLoc,
2230-
/*parsedRoot*/ nullptr,
2231-
/*parsedPath*/ anchor,
2232-
/*hasLeadingDot*/ false,
2233-
/*isImplicit*/ true);
2234-
kp->setParsedPath(nullptr);
2235-
kp->setComponents(ctx, components);
2226+
auto *kp = KeyPathExpr::createImplicit(ctx, /*backslashLoc*/ dotLoc,
2227+
components, anchor->getEndLoc());
22362228
kp->setType(keyPathTy);
22372229
cs.cacheExprTypes(kp);
22382230

lib/Sema/TypeCheckStorage.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -918,15 +918,17 @@ static Expr *buildStorageReference(AccessorDecl *accessor,
918918
Expr *propertyKeyPath = new (ctx) KeyPathDotExpr(SourceLoc());
919919
propertyKeyPath = UnresolvedDotExpr::createImplicit(ctx, propertyKeyPath,
920920
enclosingSelfAccess->accessedProperty->getName());
921-
propertyKeyPath = new (ctx) KeyPathExpr(
922-
SourceLoc(), nullptr, propertyKeyPath, /*hasLeadingDot=*/true);
921+
propertyKeyPath = KeyPathExpr::createImplicit(
922+
ctx, /*backslashLoc*/ SourceLoc(), /*parsedRoot*/ nullptr,
923+
propertyKeyPath, /*hasLeadingDot*/ true);
923924

924925
// Key path referring to the backing storage property.
925926
Expr *storageKeyPath = new (ctx) KeyPathDotExpr(SourceLoc());
926927
storageKeyPath = UnresolvedDotExpr::createImplicit(ctx, storageKeyPath,
927928
storage->getName());
928-
storageKeyPath = new (ctx) KeyPathExpr(SourceLoc(), nullptr, storageKeyPath,
929-
/*hasLeadingDot=*/true);
929+
storageKeyPath = KeyPathExpr::createImplicit(
930+
ctx, /*backslashLoc*/ SourceLoc(), /*parsedRoot*/ nullptr,
931+
storageKeyPath, /*hasLeadingDot*/ true);
930932
Expr *args[3] = {selfDRE, propertyKeyPath, storageKeyPath};
931933

932934
auto *subscriptDecl = enclosingSelfAccess->subscript;

0 commit comments

Comments
 (0)