Skip to content

Commit 7a335d6

Browse files
committed
AST: Introduce @tuple (T) syntax for one-element tuples in SIL mode
1 parent 7a16b02 commit 7a335d6

File tree

7 files changed

+53
-0
lines changed

7 files changed

+53
-0
lines changed

include/swift/AST/Attr.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ TYPE_ATTR(Sendable)
5858
TYPE_ATTR(unchecked)
5959
TYPE_ATTR(_typeSequence)
6060
TYPE_ATTR(_local)
61+
TYPE_ATTR(tuple)
6162

6263
// SIL-specific attributes
6364
TYPE_ATTR(block_storage)

include/swift/AST/Attr.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2504,6 +2504,9 @@ class TypeAttributes {
25042504
};
25052505
Optional<OpaqueReturnTypeRef> OpaqueReturnTypeOf;
25062506

2507+
// Force construction of a one-element tuple type.
2508+
bool IsTuple = false;
2509+
25072510
TypeAttributes() {}
25082511

25092512
bool isValid() const { return AtLoc.isValid(); }

lib/AST/ASTPrinter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5549,6 +5549,12 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
55495549
Printer.callPrintStructurePre(PrintStructureKind::TupleType);
55505550
SWIFT_DEFER { Printer.printStructurePost(PrintStructureKind::TupleType); };
55515551

5552+
// Single-element tuples can only appear in SIL mode.
5553+
if (T->getNumElements() == 1 &&
5554+
!T->getElement(0).hasName()) {
5555+
Printer << "@tuple ";
5556+
}
5557+
55525558
Printer << "(";
55535559

55545560
auto Fields = T->getElements();

lib/AST/TypeRepr.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,9 @@ void AttributedTypeRepr::printAttrs(ASTPrinter &Printer,
257257
Printer.printSimpleAttr("@async") << " ";
258258
if (hasAttr(TAK_opened))
259259
Printer.printSimpleAttr("@opened") << " ";
260+
261+
if (hasAttr(TAK_tuple))
262+
Printer.printSimpleAttr("@tuple") << " ";
260263
}
261264

262265
IdentTypeRepr *IdentTypeRepr::create(ASTContext &C,

lib/Parse/ParseDecl.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3798,6 +3798,15 @@ ParserStatus Parser::parseTypeAttribute(TypeAttributes &Attributes,
37983798
Attributes.setOpaqueReturnTypeOf(mangling, index);
37993799
break;
38003800
}
3801+
3802+
case TAK_tuple: {
3803+
if (!isInSILMode()) {
3804+
diagnose(AtLoc, diag::only_allowed_in_sil, "tuple");
3805+
return makeParserSuccess();
3806+
}
3807+
3808+
Attributes.IsTuple = true;
3809+
}
38013810
}
38023811

38033812
Attributes.setAttr(attr, AtLoc);

lib/Sema/TypeCheckType.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2860,6 +2860,18 @@ TypeResolver::resolveAttributedType(TypeAttributes &attrs, TypeRepr *repr,
28602860
if (!ty) ty = resolveType(repr, instanceOptions);
28612861
if (!ty || ty->hasError()) return ty;
28622862

2863+
// In SIL mode only, build one-element tuples.
2864+
if (attrs.has(TAK_tuple)) {
2865+
SmallVector<TupleTypeElt, 1> elements;
2866+
if (auto *parenTy = dyn_cast<ParenType>(ty.getPointer()))
2867+
ty = parenTy->getUnderlyingType();
2868+
2869+
elements.emplace_back(ty);
2870+
ty = TupleType::get(elements, getASTContext());
2871+
2872+
attrs.clearAttribute(TAK_tuple);
2873+
}
2874+
28632875
// Type aliases inside protocols are not yet resolved in the structural
28642876
// stage of type resolution
28652877
if (ty->is<DependentMemberType>() &&

test/SIL/Parser/one_element_tuple.sil

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %target-sil-opt %s | %target-sil-opt | %FileCheck %s
2+
3+
sil_stage canonical
4+
5+
import Swift
6+
7+
// CHECK-LABEL: sil [ossa] @tuple_test : $@convention(thin) (@tuple (Int)) -> @tuple (Int) {
8+
// CHECK: bb0(%0 : $@tuple (Int)):
9+
// CHECK-NEXT: %1 = tuple_extract %0 : $@tuple (Int), 0
10+
// CHECK-NEXT: %2 = tuple (%1 : $Int)
11+
// CHECK-NEXT: return %2 : $@tuple (Int)
12+
// CHECK-NEXT: }
13+
14+
sil [ossa] @tuple_test : $@convention(thin) (@tuple (Int)) -> @tuple (Int) {
15+
bb0(%0 : $@tuple (Int)):
16+
%1 = tuple_extract %0 : $@tuple (Int), 0
17+
%2 = tuple $@tuple (Int) (%1)
18+
return %2 : $@tuple (Int)
19+
}

0 commit comments

Comments
 (0)