Skip to content

Commit 68c461d

Browse files
committed
Introduce type sugar for InlineArray
Parse e.g `[3 x Int]` as type sugar for InlineArray. Gated behind an experimental feature flag for now.
1 parent 57fefb9 commit 68c461d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+662
-6
lines changed

include/swift/AST/ASTBridging.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2681,6 +2681,11 @@ BridgedImplicitlyUnwrappedOptionalTypeRepr_createParsed(
26812681
BridgedASTContext cContext, BridgedTypeRepr base,
26822682
BridgedSourceLoc cExclamationLoc);
26832683

2684+
SWIFT_NAME("BridgedInlineArrayTypeRepr.createParsed(_:count:element:brackets:)")
2685+
BridgedInlineArrayTypeRepr BridgedInlineArrayTypeRepr_createParsed(
2686+
BridgedASTContext cContext, BridgedTypeRepr cCountType,
2687+
BridgedTypeRepr cElementType, BridgedSourceRange cBracketsRange);
2688+
26842689
SWIFT_NAME("BridgedInverseTypeRepr.createParsed(_:tildeLoc:constraint:)")
26852690
BridgedInverseTypeRepr
26862691
BridgedInverseTypeRepr_createParsed(BridgedASTContext cContext,

include/swift/AST/DiagnosticsParse.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,10 @@ NOTE(subscript_array_element_fix_it_add_comma, none, "add a separator between "
878878
NOTE(subscript_array_element_fix_it_remove_space, none,
879879
"remove the space between the elements to silence this warning", ())
880880

881+
// Inline Array
882+
ERROR(expected_rsquare_inline_array,none,
883+
"expected ']' in inline array type", ())
884+
881885
// Tuple Types
882886
ERROR(expected_rparen_tuple_type_list,none,
883887
"expected ')' at end of tuple list", ())

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6059,7 +6059,7 @@ NOTE(note_recursive_enum_case_here,none,
60596059

60606060
ERROR(sugar_type_not_found,none,
60616061
"broken standard library: cannot find "
6062-
"%select{Array|Optional|ImplicitlyUnwrappedOptional|Dictionary|"
6062+
"%select{Array|Optional|InlineArray|Dictionary|"
60636063
"Error}0 type", (unsigned))
60646064
ERROR(optional_intrinsics_not_found,none,
60656065
"broken standard library: cannot find intrinsic operations on "
@@ -8281,6 +8281,9 @@ ERROR(invalid_value_for_type_same_type,none,
82818281
ERROR(inlinearray_literal_incorrect_count,none,
82828282
"expected %0 elements in inline array literal, but got %1", (Type, Type))
82838283

8284+
ERROR(inline_array_type_backwards,none,
8285+
"element count must precede inline array element type", ())
8286+
82848287
//===----------------------------------------------------------------------===//
82858288
// MARK: @abi Attribute
82868289
//===----------------------------------------------------------------------===//

include/swift/AST/PrintOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,10 @@ struct PrintOptions {
590590
/// Whether to always desugar array types from `[base_type]` to `Array<base_type>`
591591
bool AlwaysDesugarArraySliceTypes = false;
592592

593+
/// Whether to always desugar inline array types from
594+
/// `[<count> x <element>]` to `InlineArray<count, element>`
595+
bool AlwaysDesugarInlineArrayTypes = false;
596+
593597
/// Whether to always desugar dictionary types
594598
/// from `[key_type:value_type]` to `Dictionary<key_type,value_type>`
595599
bool AlwaysDesugarDictionaryTypes = false;

include/swift/AST/TypeNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ ABSTRACT_SUGARED_TYPE(Sugar, Type)
217217
SUGARED_TYPE(Optional, UnarySyntaxSugarType)
218218
SUGARED_TYPE(VariadicSequence, UnarySyntaxSugarType)
219219
TYPE_RANGE(UnarySyntaxSugar, ArraySlice, VariadicSequence)
220+
SUGARED_TYPE(InlineArray, SyntaxSugarType)
220221
SUGARED_TYPE(Dictionary, SyntaxSugarType)
221222
TYPE_RANGE(SyntaxSugar, ArraySlice, Dictionary)
222223
TYPE_RANGE(Sugar, TypeAlias, Dictionary)

include/swift/AST/TypeRepr.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,38 @@ class ArrayTypeRepr : public TypeRepr {
641641
friend class TypeRepr;
642642
};
643643

644+
/// An InlineArray type.
645+
/// \code
646+
/// [2 x Foo]
647+
/// \endcode
648+
class InlineArrayTypeRepr : public TypeRepr {
649+
TypeRepr *Count;
650+
TypeRepr *Element;
651+
SourceRange Brackets;
652+
653+
InlineArrayTypeRepr(TypeRepr *count, TypeRepr *element, SourceRange brackets)
654+
: TypeRepr(TypeReprKind::InlineArray), Count(count), Element(element),
655+
Brackets(brackets) {}
656+
657+
public:
658+
static InlineArrayTypeRepr *create(ASTContext &ctx, TypeRepr *count,
659+
TypeRepr *element, SourceRange brackets);
660+
661+
TypeRepr *getCount() const { return Count; }
662+
TypeRepr *getElement() const { return Element; }
663+
SourceRange getBrackets() const { return Brackets; }
664+
665+
static bool classof(const TypeRepr *T) {
666+
return T->getKind() == TypeReprKind::InlineArray;
667+
}
668+
669+
private:
670+
SourceLoc getStartLocImpl() const { return Brackets.Start; }
671+
SourceLoc getEndLocImpl() const { return Brackets.End; }
672+
void printImpl(ASTPrinter &Printer, const PrintOptions &Opts) const;
673+
friend class TypeRepr;
674+
};
675+
644676
/// A dictionary type.
645677
/// \code
646678
/// [K : V]
@@ -1626,6 +1658,7 @@ inline bool TypeRepr::isSimple() const {
16261658
case TypeReprKind::Fixed:
16271659
case TypeReprKind::Self:
16281660
case TypeReprKind::Array:
1661+
case TypeReprKind::InlineArray:
16291662
case TypeReprKind::SILBox:
16301663
case TypeReprKind::Isolated:
16311664
case TypeReprKind::Sending:

include/swift/AST/TypeReprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ ABSTRACT_TYPEREPR(DeclRef, TypeRepr)
4949
TYPEREPR(UnqualifiedIdent, DeclRefTypeRepr)
5050
TYPEREPR(QualifiedIdent, DeclRefTypeRepr)
5151
TYPEREPR(Function, TypeRepr)
52+
TYPEREPR(InlineArray, TypeRepr)
5253
TYPEREPR(Array, TypeRepr)
5354
TYPEREPR(Dictionary, TypeRepr)
5455
TYPEREPR(Optional, TypeRepr)

include/swift/AST/TypeTransform.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,25 @@ case TypeKind::Id:
894894
return ArraySliceType::get(baseTy);
895895
}
896896

897+
case TypeKind::InlineArray: {
898+
auto ty = cast<InlineArrayType>(base);
899+
auto countTy = doIt(ty->getCountType(), TypePosition::Invariant);
900+
if (!countTy)
901+
return Type();
902+
903+
// Currently the element type is invariant for InlineArray.
904+
// FIXME: Should we allow covariance?
905+
auto eltTy = doIt(ty->getElementType(), TypePosition::Invariant);
906+
if (!eltTy)
907+
return Type();
908+
909+
if (countTy.getPointer() == ty->getCountType().getPointer() &&
910+
eltTy.getPointer() == ty->getElementType().getPointer())
911+
return t;
912+
913+
return InlineArrayType::get(countTy, eltTy);
914+
}
915+
897916
case TypeKind::Optional: {
898917
auto optional = cast<OptionalType>(base);
899918
auto baseTy = doIt(optional->getBaseType(), pos);

include/swift/AST/Types.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6191,6 +6191,28 @@ class ArraySliceType : public UnarySyntaxSugarType {
61916191
}
61926192
};
61936193

6194+
/// The type [<count> x <element>], which is syntax sugar for
6195+
/// InlineArray<count, element>.
6196+
class InlineArrayType : public SyntaxSugarType {
6197+
Type Count;
6198+
Type Elt;
6199+
6200+
InlineArrayType(const ASTContext &ctx, Type count, Type elt,
6201+
RecursiveTypeProperties properties)
6202+
: SyntaxSugarType(TypeKind::InlineArray, ctx, properties), Count(count),
6203+
Elt(elt) {}
6204+
6205+
public:
6206+
static InlineArrayType *get(Type count, Type elt);
6207+
6208+
Type getCountType() const { return Count; }
6209+
Type getElementType() const { return Elt; }
6210+
6211+
static bool classof(const TypeBase *T) {
6212+
return T->getKind() == TypeKind::InlineArray;
6213+
}
6214+
};
6215+
61946216
/// The type T?, which is always sugar for a library type.
61956217
class OptionalType : public UnarySyntaxSugarType {
61966218
OptionalType(const ASTContext &ctx,Type base,

include/swift/Basic/Features.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,9 @@ EXPERIMENTAL_FEATURE(SwiftSettings, false)
508508
/// Syntax sugar features for concurrency.
509509
EXPERIMENTAL_FEATURE(ConcurrencySyntaxSugar, true)
510510

511+
/// Enable syntax sugar type '[3 x Int]' for Inline Array
512+
EXPERIMENTAL_FEATURE(InlineArrayTypeSugar, false)
513+
511514
/// Allow declaration of compile-time values
512515
EXPERIMENTAL_FEATURE(CompileTimeValues, true)
513516

include/swift/Parse/Parser.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1458,6 +1458,14 @@ class Parser {
14581458
ParserResult<TypeRepr> parseTypeTupleBody();
14591459
ParserResult<TypeRepr> parseTypeArray(ParserResult<TypeRepr> Base);
14601460

1461+
/// Whether the parser is at the start of an InlineArray type body.
1462+
bool isStartOfInlineArrayTypeBody();
1463+
1464+
/// Parse an InlineArray type '[' integer 'x' type ']'.
1465+
///
1466+
/// NOTE: 'isStartOfInlineArrayTypeBody' must be true.
1467+
ParserResult<TypeRepr> parseTypeInlineArray(SourceLoc lSquare);
1468+
14611469
/// Parse a collection type.
14621470
/// type-simple:
14631471
/// '[' type ']'
@@ -1696,6 +1704,7 @@ class Parser {
16961704
bool canParseTypeScalar();
16971705
bool canParseType();
16981706

1707+
bool canParseStartOfInlineArrayType();
16991708
bool canParseCollectionType();
17001709

17011710
/// Returns true if a simple type identifier can be parsed.

lib/AST/ASTContext.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ struct ASTContext::Implementation {
547547
llvm::DenseMap<llvm::PointerIntPair<TypeBase*, 3, unsigned>,
548548
ExistentialMetatypeType*> ExistentialMetatypeTypes;
549549
llvm::DenseMap<Type, ArraySliceType*> ArraySliceTypes;
550+
llvm::DenseMap<std::pair<Type, Type>, InlineArrayType *> InlineArrayTypes;
550551
llvm::DenseMap<Type, VariadicSequenceType*> VariadicSequenceTypes;
551552
llvm::DenseMap<std::pair<Type, Type>, DictionaryType *> DictionaryTypes;
552553
llvm::DenseMap<Type, OptionalType*> OptionalTypes;
@@ -5426,6 +5427,21 @@ ArraySliceType *ArraySliceType::get(Type base) {
54265427
return entry = new (C, arena) ArraySliceType(C, base, properties);
54275428
}
54285429

5430+
InlineArrayType *InlineArrayType::get(Type count, Type elt) {
5431+
auto properties =
5432+
count->getRecursiveProperties() | elt->getRecursiveProperties();
5433+
auto arena = getArena(properties);
5434+
5435+
const ASTContext &C = count->getASTContext();
5436+
5437+
auto *&entry = C.getImpl().getArena(arena).InlineArrayTypes[{count, elt}];
5438+
if (entry)
5439+
return entry;
5440+
5441+
entry = new (C, arena) InlineArrayType(C, count, elt, properties);
5442+
return entry;
5443+
}
5444+
54295445
VariadicSequenceType *VariadicSequenceType::get(Type base) {
54305446
auto properties = base->getRecursiveProperties();
54315447
auto arena = getArena(properties);

lib/AST/ASTDumper.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4538,6 +4538,13 @@ class PrintTypeRepr : public TypeReprVisitor<PrintTypeRepr, void, Label>,
45384538
printFoot();
45394539
}
45404540

4541+
void visitInlineArrayTypeRepr(InlineArrayTypeRepr *T, Label label) {
4542+
printCommon("type_inline_array", label);
4543+
printRec(T->getCount(), Label::always("count"));
4544+
printRec(T->getElement(), Label::always("element"));
4545+
printFoot();
4546+
}
4547+
45414548
void visitDictionaryTypeRepr(DictionaryTypeRepr *T, Label label) {
45424549
printCommon("type_dictionary", label);
45434550
printRec(T->getKey(), Label::optional("key"));
@@ -6382,6 +6389,13 @@ namespace {
63826389
printFoot();
63836390
}
63846391

6392+
void visitInlineArrayType(InlineArrayType *T, Label label) {
6393+
printCommon("inline_array_type", label);
6394+
printRec(T->getCountType(), Label::always("count"));
6395+
printRec(T->getElementType(), Label::always("element"));
6396+
printFoot();
6397+
}
6398+
63856399
void visitOptionalType(OptionalType *T, Label label) {
63866400
printCommon("optional_type", label);
63876401
printRec(T->getBaseType(), Label::optional("base_type"));

lib/AST/ASTMangler.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,6 +1509,14 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
15091509
appendOperator("XSa");
15101510
return;
15111511

1512+
case TypeKind::InlineArray: {
1513+
assert(DWARFMangling && "sugared types are only legal for the debugger");
1514+
// FIXME: Once we have a known mangling substitution for InlineArray,
1515+
// use that. For now just desugar.
1516+
appendType(tybase->getDesugaredType(), sig, forDecl);
1517+
return;
1518+
}
1519+
15121520
case TypeKind::VariadicSequence:
15131521
assert(DWARFMangling && "sugared types are only legal for the debugger");
15141522
appendType(cast<VariadicSequenceType>(tybase)->getBaseType(), sig, forDecl);

lib/AST/ASTPrinter.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7060,6 +7060,18 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
70607060
}
70617061
}
70627062

7063+
void visitInlineArrayType(InlineArrayType *T) {
7064+
if (Options.AlwaysDesugarInlineArrayTypes) {
7065+
visit(T->getDesugaredType());
7066+
} else {
7067+
Printer << "[";
7068+
visit(T->getCountType());
7069+
Printer << " x ";
7070+
visit(T->getElementType());
7071+
Printer << "]";
7072+
}
7073+
}
7074+
70637075
void visitDictionaryType(DictionaryType *T) {
70647076
if (Options.AlwaysDesugarDictionaryTypes) {
70657077
visit(T->getDesugaredType());

lib/AST/ASTWalker.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2246,6 +2246,10 @@ bool Traversal::visitArrayTypeRepr(ArrayTypeRepr *T) {
22462246
return doIt(T->getBase());
22472247
}
22482248

2249+
bool Traversal::visitInlineArrayTypeRepr(InlineArrayTypeRepr *T) {
2250+
return doIt(T->getCount()) || doIt(T->getElement());
2251+
}
2252+
22492253
bool Traversal::visitDictionaryTypeRepr(DictionaryTypeRepr *T) {
22502254
return doIt(T->getKey()) || doIt(T->getValue());
22512255
}

lib/AST/Bridging/TypeReprBridging.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,14 @@ BridgedErrorTypeRepr BridgedErrorTypeRepr_create(BridgedASTContext cContext,
100100
return ErrorTypeRepr::create(cContext.unbridged(), cRange.unbridged());
101101
}
102102

103+
BridgedInlineArrayTypeRepr BridgedInlineArrayTypeRepr_createParsed(
104+
BridgedASTContext cContext, BridgedTypeRepr cCountType,
105+
BridgedTypeRepr cElementType, BridgedSourceRange cBracketsRange) {
106+
return InlineArrayTypeRepr::create(
107+
cContext.unbridged(), cCountType.unbridged(), cElementType.unbridged(),
108+
cBracketsRange.unbridged());
109+
}
110+
103111
BridgedInverseTypeRepr
104112
BridgedInverseTypeRepr_createParsed(BridgedASTContext cContext,
105113
BridgedSourceLoc cTildeLoc,

lib/AST/FeatureSet.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,12 @@ static bool usesFeatureNonescapableTypes(Decl *decl) {
194194
return false;
195195
}
196196

197+
static bool usesFeatureInlineArrayTypeSugar(Decl *D) {
198+
return usesTypeMatching(D, [&](Type ty) {
199+
return isa<InlineArrayType>(ty.getPointer());
200+
});
201+
}
202+
197203
UNINTERESTING_FEATURE(StaticExclusiveOnly)
198204
UNINTERESTING_FEATURE(ExtractConstantsFromMembers)
199205
UNINTERESTING_FEATURE(GroupActorErrors)

lib/AST/NameLookup.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3167,6 +3167,10 @@ directReferencesForTypeRepr(Evaluator &evaluator, ASTContext &ctx,
31673167
result.first.push_back(ctx.getArrayDecl());
31683168
return result;
31693169

3170+
case TypeReprKind::InlineArray:
3171+
result.first.push_back(ctx.getInlineArrayDecl());
3172+
return result;
3173+
31703174
case TypeReprKind::Attributed: {
31713175
auto attributed = cast<AttributedTypeRepr>(typeRepr);
31723176
return directReferencesForTypeRepr(evaluator, ctx,

lib/AST/Type.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,6 +1974,9 @@ Type SugarType::getSinglyDesugaredTypeSlow() {
19741974
case TypeKind::VariadicSequence:
19751975
implDecl = Context->getArrayDecl();
19761976
break;
1977+
case TypeKind::InlineArray:
1978+
implDecl = Context->getInlineArrayDecl();
1979+
break;
19771980
case TypeKind::Optional:
19781981
implDecl = Context->getOptionalDecl();
19791982
break;
@@ -1989,8 +1992,11 @@ Type SugarType::getSinglyDesugaredTypeSlow() {
19891992
if (auto Ty = dyn_cast<UnarySyntaxSugarType>(this)) {
19901993
UnderlyingType = BoundGenericType::get(implDecl, Type(), Ty->getBaseType());
19911994
} else if (auto Ty = dyn_cast<DictionaryType>(this)) {
1992-
UnderlyingType = BoundGenericType::get(implDecl, Type(),
1993-
{ Ty->getKeyType(), Ty->getValueType() });
1995+
UnderlyingType = BoundGenericType::get(
1996+
implDecl, Type(), {Ty->getKeyType(), Ty->getValueType()});
1997+
} else if (auto Ty = dyn_cast<InlineArrayType>(this)) {
1998+
UnderlyingType = BoundGenericType::get(
1999+
implDecl, Type(), {Ty->getCountType(), Ty->getElementType()});
19942000
} else {
19952001
llvm_unreachable("Not UnarySyntaxSugarType or DictionaryType?");
19962002
}

lib/AST/TypeRepr.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,13 @@ SourceLoc DeclRefTypeRepr::getEndLocImpl() const {
311311
return getNameLoc().getEndLoc();
312312
}
313313

314+
InlineArrayTypeRepr *InlineArrayTypeRepr::create(ASTContext &ctx,
315+
TypeRepr *count,
316+
TypeRepr *element,
317+
SourceRange brackets) {
318+
return new (ctx) InlineArrayTypeRepr(count, element, brackets);
319+
}
320+
314321
static void printTypeRepr(const TypeRepr *TyR, ASTPrinter &Printer,
315322
const PrintOptions &Opts) {
316323
if (TyR == nullptr)
@@ -473,6 +480,15 @@ void FunctionTypeRepr::printImpl(ASTPrinter &Printer,
473480
Printer.printStructurePost(PrintStructureKind::FunctionType);
474481
}
475482

483+
void InlineArrayTypeRepr::printImpl(ASTPrinter &Printer,
484+
const PrintOptions &Opts) const {
485+
Printer << "[";
486+
printTypeRepr(getCount(), Printer, Opts);
487+
Printer << " x ";
488+
printTypeRepr(getElement(), Printer, Opts);
489+
Printer << "]";
490+
}
491+
476492
void ArrayTypeRepr::printImpl(ASTPrinter &Printer,
477493
const PrintOptions &Opts) const {
478494
Printer << "[";

0 commit comments

Comments
 (0)