Skip to content

Commit 3dad575

Browse files
committed
[ASTGen] Handle variadic parameters in functions and function types
There is a modeling difference between the swift-syntax tree and the C++ type representation (TypeRepr) that is a little odd here, so we end up parsing the ellipsis on the C++ side rather than looking "up" the syntax tree to find it.
1 parent 3c1867f commit 3dad575

File tree

6 files changed

+40
-3
lines changed

6 files changed

+40
-3
lines changed

include/swift/AST/CASTBridging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ void *MetatypeTypeRepr_create(void *ctx, void *baseType, void *typeLoc);
274274
void *ProtocolTypeRepr_create(void *ctx, void *baseType, void *protoLoc);
275275
void *AttributedTypeSpecifierRepr_create(
276276
void *ctx, void *base, BridgedAttributedTypeSpecifier specifier, void *specifierLoc);
277+
void *VarargTypeRepr_create(void *ctx, void *base, void *ellipsisLocPtr);
277278
void *PackExpansionTypeRepr_create(void *ctx, void *base, void *repeatLoc);
278279
void *TupleTypeRepr_create(void *ctx, BridgedArrayRef elements, void *lParenLoc,
279280
void *rParenLoc);

lib/AST/CASTBridging.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,13 @@ void *AttributedTypeSpecifierRepr_create(
514514
}
515515
}
516516

517+
void *VarargTypeRepr_create(void *ctx, void *base, void *ellipsisLocPtr) {
518+
ASTContext &Context = *static_cast<ASTContext *>(ctx);
519+
SourceLoc ellipsisLoc = getSourceLocFromPointer(ellipsisLocPtr);
520+
TypeRepr *baseType = (TypeRepr *)base;
521+
return new (Context) VarargTypeRepr(baseType, ellipsisLoc);
522+
}
523+
517524
void *TupleTypeRepr_create(void *ctx, BridgedArrayRef elements, void *lParenLoc,
518525
void *rParenLoc) {
519526
ASTContext &Context = *static_cast<ASTContext *>(ctx);

lib/ASTGen/Sources/ASTGen/Macros.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ func findSyntaxNodeInSourceFile<Node: SyntaxProtocol>(
637637
while let parentSyntax = resultSyntax.parent {
638638
guard let typedParent = parentSyntax.as(type),
639639
typedParent.position == resultSyntax.position else {
640-
break;
640+
break
641641
}
642642

643643
resultSyntax = typedParent

lib/ASTGen/Sources/ASTGen/Types.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,13 @@ extension ASTGenVisitor {
213213
self.base.advanced(by: $0.position.utf8Offset).raw
214214
}
215215
let colonLoc = element.colon.map { self.base.advanced(by: $0.position.utf8Offset).raw }
216-
let type = visit(element.type).rawValue
216+
217+
var type = visit(element.type).rawValue
218+
if let ellipsis = element.ellipsis {
219+
let ellipsisLoc = self.base.advanced(by: ellipsis.positionAfterSkippingLeadingTrivia.utf8Offset).raw
220+
type = VarargTypeRepr_create(self.ctx, type, ellipsisLoc)
221+
}
222+
217223
let trailingCommaLoc = element.trailingComma.map {
218224
self.base.advanced(by: $0.position.utf8Offset).raw
219225
}

lib/Parse/ParseType.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,8 +599,21 @@ ParserResult<TypeRepr> Parser::parseType(
599599
CurDeclContext, &Context, &endLocPtr);
600600
return std::make_pair(typeRepr, endLocPtr);
601601
});
602-
if (astGenResult.isNonNull())
602+
if (astGenResult.isNonNull()) {
603+
// Note: there is a representational difference between the swift-syntax
604+
// tree and the C++ parser tree regarding variadic parameters. In the
605+
// swift-syntax tree, the ellipsis is part of the parameter declaration.
606+
// In the C++ parser tree, the ellipsis is part of the type. Account for
607+
// this difference by consuming the ellipsis here.
608+
if (Tok.isEllipsis()) {
609+
Tok.setKind(tok::ellipsis);
610+
SourceLoc ellipsisLoc = consumeToken();
611+
return makeParserResult(astGenResult,
612+
new (Context) VarargTypeRepr(astGenResult.get(), ellipsisLoc));
613+
}
614+
603615
return astGenResult;
616+
}
604617
#endif
605618

606619
// Parse pack expansion 'repeat T'

test/ASTGen/types.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,13 @@ func test7(_ b: inout Bool) {
1111
struct X { struct `Protocol` { } }
1212

1313
func test10(_: X.`Protocol`) { }
14+
15+
func test11(_: Int...) { }
16+
func test11a() {
17+
test11(1, 2, 3, 4, 5)
18+
}
19+
20+
typealias VAFunc = (Int, Int...) -> Int
21+
func testVAFunc(a: Int, f: VAFunc) {
22+
_ = f(a, a, a, a, a)
23+
}

0 commit comments

Comments
 (0)