Skip to content

Commit f8ab391

Browse files
authored
Introduce type sugar for InlineArray (#80087)
* [CS] Decline to handle InlineArray in shrink Previously we would try the contextual type `(<int>, <element>)`, which is wrong. Given we want to eliminate shrink, let's just bail. * [Sema] Sink `ValueMatchVisitor` into `applyUnboundGenericArguments` Make sure it's called for sugar code paths too. Also let's just always run it since it should be a pretty cheap check. * [Sema] Diagnose passing integer to non-integer type parameter This was previously missed, though would have been diagnosed later as a requirement failure. * [Parse] Split up `canParseType` While here, address the FIXME in `canParseTypeSimpleOrComposition` and only check to see if we can parse a type-simple, including `each`, `some`, and `any` for better recovery. * 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 564191e commit f8ab391

Some content is hidden

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

55 files changed

+855
-74
lines changed

docs/ABI/Mangling.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,7 @@ productions:
954954
type ::= base-type "XSq" // sugared Optional type
955955
type ::= base-type "XSa" // sugared Array type
956956
type ::= key-type value-type "XSD" // sugared Dictionary type
957+
type ::= count-type element-type "XSA" // sugared InlineArray type
957958

958959
Generics
959960
~~~~~~~~

include/swift/AST/ASTBridging.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2702,6 +2702,11 @@ BridgedImplicitlyUnwrappedOptionalTypeRepr_createParsed(
27022702
BridgedASTContext cContext, BridgedTypeRepr base,
27032703
BridgedSourceLoc cExclamationLoc);
27042704

2705+
SWIFT_NAME("BridgedInlineArrayTypeRepr.createParsed(_:count:element:brackets:)")
2706+
BridgedInlineArrayTypeRepr BridgedInlineArrayTypeRepr_createParsed(
2707+
BridgedASTContext cContext, BridgedTypeRepr cCountType,
2708+
BridgedTypeRepr cElementType, BridgedSourceRange cBracketsRange);
2709+
27052710
SWIFT_NAME("BridgedInverseTypeRepr.createParsed(_:tildeLoc:constraint:)")
27062711
BridgedInverseTypeRepr
27072712
BridgedInverseTypeRepr_createParsed(BridgedASTContext cContext,

include/swift/AST/ASTDemangler.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,8 @@ class ASTBuilder {
248248

249249
Type createArrayType(Type base);
250250

251+
Type createInlineArrayType(Type count, Type element);
252+
251253
Type createDictionaryType(Type key, Type value);
252254

253255
Type createIntegerType(intptr_t value);

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
@@ -6069,7 +6069,7 @@ NOTE(note_recursive_enum_case_here,none,
60696069

60706070
ERROR(sugar_type_not_found,none,
60716071
"broken standard library: cannot find "
6072-
"%select{Array|Optional|ImplicitlyUnwrappedOptional|Dictionary|"
6072+
"%select{Array|Optional|InlineArray|Dictionary|"
60736073
"Error}0 type", (unsigned))
60746074
ERROR(optional_intrinsics_not_found,none,
60756075
"broken standard library: cannot find intrinsic operations on "
@@ -8334,6 +8334,9 @@ ERROR(invalid_value_for_type_same_type,none,
83348334
ERROR(inlinearray_literal_incorrect_count,none,
83358335
"expected %0 elements in inline array literal, but got %1", (Type, Type))
83368336

8337+
ERROR(inline_array_type_backwards,none,
8338+
"element count must precede inline array element type", ())
8339+
83378340
//===----------------------------------------------------------------------===//
83388341
// MARK: @abi Attribute
83398342
//===----------------------------------------------------------------------===//

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: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,35 @@ class ArrayTypeRepr : public TypeRepr {
641641
friend class TypeRepr;
642642
};
643643

644+
/// An InlineArray type e.g `[2 x Foo]`, sugar for `InlineArray<2, Foo>`.
645+
class InlineArrayTypeRepr : public TypeRepr {
646+
TypeRepr *Count;
647+
TypeRepr *Element;
648+
SourceRange Brackets;
649+
650+
InlineArrayTypeRepr(TypeRepr *count, TypeRepr *element, SourceRange brackets)
651+
: TypeRepr(TypeReprKind::InlineArray), Count(count), Element(element),
652+
Brackets(brackets) {}
653+
654+
public:
655+
static InlineArrayTypeRepr *create(ASTContext &ctx, TypeRepr *count,
656+
TypeRepr *element, SourceRange brackets);
657+
658+
TypeRepr *getCount() const { return Count; }
659+
TypeRepr *getElement() const { return Element; }
660+
SourceRange getBrackets() const { return Brackets; }
661+
662+
static bool classof(const TypeRepr *T) {
663+
return T->getKind() == TypeReprKind::InlineArray;
664+
}
665+
666+
private:
667+
SourceLoc getStartLocImpl() const { return Brackets.Start; }
668+
SourceLoc getEndLocImpl() const { return Brackets.End; }
669+
void printImpl(ASTPrinter &Printer, const PrintOptions &Opts) const;
670+
friend class TypeRepr;
671+
};
672+
644673
/// A dictionary type.
645674
/// \code
646675
/// [K : V]
@@ -1626,6 +1655,7 @@ inline bool TypeRepr::isSimple() const {
16261655
case TypeReprKind::Fixed:
16271656
case TypeReprKind::Self:
16281657
case TypeReprKind::Array:
1658+
case TypeReprKind::InlineArray:
16291659
case TypeReprKind::SILBox:
16301660
case TypeReprKind::Isolated:
16311661
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: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6197,6 +6197,27 @@ class ArraySliceType : public UnarySyntaxSugarType {
61976197
}
61986198
};
61996199

6200+
/// An InlineArray type e.g `[2 x Foo]`, sugar for `InlineArray<2, Foo>`.
6201+
class InlineArrayType : public SyntaxSugarType {
6202+
Type Count;
6203+
Type Elt;
6204+
6205+
InlineArrayType(const ASTContext &ctx, Type count, Type elt,
6206+
RecursiveTypeProperties properties)
6207+
: SyntaxSugarType(TypeKind::InlineArray, ctx, properties), Count(count),
6208+
Elt(elt) {}
6209+
6210+
public:
6211+
static InlineArrayType *get(Type count, Type elt);
6212+
6213+
Type getCountType() const { return Count; }
6214+
Type getElementType() const { return Elt; }
6215+
6216+
static bool classof(const TypeBase *T) {
6217+
return T->getKind() == TypeKind::InlineArray;
6218+
}
6219+
};
6220+
62006221
/// The type T?, which is always sugar for a library type.
62016222
class OptionalType : public UnarySyntaxSugarType {
62026223
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
@@ -511,6 +511,9 @@ EXPERIMENTAL_FEATURE(SwiftSettings, false)
511511
/// Syntax sugar features for concurrency.
512512
EXPERIMENTAL_FEATURE(ConcurrencySyntaxSugar, true)
513513

514+
/// Enable syntax sugar type '[3 x Int]' for Inline Array
515+
EXPERIMENTAL_FEATURE(InlineArrayTypeSugar, false)
516+
514517
/// Allow declaration of compile-time values
515518
EXPERIMENTAL_FEATURE(CompileTimeValues, true)
516519

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ NODE(AssociatedTypeGenericParamRef)
330330
NODE(SugaredOptional)
331331
NODE(SugaredArray)
332332
NODE(SugaredDictionary)
333+
NODE(SugaredInlineArray)
333334
NODE(SugaredParen) // Removed in Swift 6.TBD
334335

335336
// Added in Swift 5.1

include/swift/Demangling/TypeDecoder.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,6 +1466,22 @@ class TypeDecoder {
14661466

14671467
return Builder.createArrayType(base.getType());
14681468
}
1469+
case NodeKind::SugaredInlineArray: {
1470+
if (Node->getNumChildren() < 2) {
1471+
return MAKE_NODE_TYPE_ERROR(Node,
1472+
"fewer children (%zu) than required (2)",
1473+
Node->getNumChildren());
1474+
}
1475+
auto count = decodeMangledType(Node->getChild(0), depth + 1);
1476+
if (count.isError())
1477+
return count;
1478+
1479+
auto element = decodeMangledType(Node->getChild(1), depth + 1);
1480+
if (element.isError())
1481+
return element;
1482+
1483+
return Builder.createInlineArrayType(count.getType(), element.getType());
1484+
}
14691485
case NodeKind::SugaredDictionary: {
14701486
if (Node->getNumChildren() < 2)
14711487
return MAKE_NODE_TYPE_ERROR(Node,

include/swift/Parse/Parser.h

Lines changed: 14 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 ']'
@@ -1691,8 +1699,14 @@ class Parser {
16911699
/// and the expression will parse with the '<' as an operator.
16921700
bool canParseAsGenericArgumentList();
16931701

1702+
bool canParseTypeSimple();
1703+
bool canParseTypeSimpleOrComposition();
1704+
bool canParseTypeScalar();
16941705
bool canParseType();
16951706

1707+
bool canParseStartOfInlineArrayType();
1708+
bool canParseCollectionType();
1709+
16961710
/// Returns true if a simple type identifier can be parsed.
16971711
///
16981712
/// \verbatim

include/swift/RemoteInspection/TypeRefBuilder.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,12 @@ class TypeRefBuilder {
917917
return nullptr;
918918
}
919919

920+
const TypeRef *createInlineArrayType(const TypeRef *count,
921+
const TypeRef *element) {
922+
// TypeRefs don't contain sugared types
923+
return nullptr;
924+
}
925+
920926
const TypeRef *createDictionaryType(const TypeRef *key,
921927
const TypeRef *value) {
922928
// TypeRefs don't contain sugared types

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/ASTDemangler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,10 @@ Type ASTBuilder::createArrayType(Type base) {
10541054
return ArraySliceType::get(base);
10551055
}
10561056

1057+
Type ASTBuilder::createInlineArrayType(Type count, Type element) {
1058+
return InlineArrayType::get(count, element);
1059+
}
1060+
10571061
Type ASTBuilder::createDictionaryType(Type key, Type value) {
10581062
return DictionaryType::get(key, value);
10591063
}

lib/AST/ASTDumper.cpp

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

4547+
void visitInlineArrayTypeRepr(InlineArrayTypeRepr *T, Label label) {
4548+
printCommon("type_inline_array", label);
4549+
printRec(T->getCount(), Label::always("count"));
4550+
printRec(T->getElement(), Label::always("element"));
4551+
printFoot();
4552+
}
4553+
45474554
void visitDictionaryTypeRepr(DictionaryTypeRepr *T, Label label) {
45484555
printCommon("type_dictionary", label);
45494556
printRec(T->getKey(), Label::optional("key"));
@@ -6388,6 +6395,13 @@ namespace {
63886395
printFoot();
63896396
}
63906397

6398+
void visitInlineArrayType(InlineArrayType *T, Label label) {
6399+
printCommon("inline_array_type", label);
6400+
printRec(T->getCountType(), Label::always("count"));
6401+
printRec(T->getElementType(), Label::always("element"));
6402+
printFoot();
6403+
}
6404+
63916405
void visitOptionalType(OptionalType *T, Label label) {
63926406
printCommon("optional_type", label);
63936407
printRec(T->getBaseType(), Label::optional("base_type"));

lib/AST/ASTMangler.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,6 +1574,18 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
15741574
appendOperator("XSa");
15751575
return;
15761576

1577+
case TypeKind::InlineArray: {
1578+
assert(DWARFMangling && "sugared types are only legal for the debugger");
1579+
auto *T = cast<InlineArrayType>(tybase);
1580+
appendType(T->getCountType(), sig, forDecl);
1581+
appendType(T->getElementType(), sig, forDecl);
1582+
// Note we don't have a known-type mangling for InlineArray, we can
1583+
// use 'A' since it's incredibly unlikely
1584+
// AutoreleasingUnsafeMutablePointer will ever receive type sugar.
1585+
appendOperator("XSA");
1586+
return;
1587+
}
1588+
15771589
case TypeKind::VariadicSequence:
15781590
assert(DWARFMangling && "sugared types are only legal for the debugger");
15791591
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
@@ -7066,6 +7066,18 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
70667066
}
70677067
}
70687068

7069+
void visitInlineArrayType(InlineArrayType *T) {
7070+
if (Options.AlwaysDesugarInlineArrayTypes) {
7071+
visit(T->getDesugaredType());
7072+
} else {
7073+
Printer << "[";
7074+
visit(T->getCountType());
7075+
Printer << " x ";
7076+
visit(T->getElementType());
7077+
Printer << "]";
7078+
}
7079+
}
7080+
70697081
void visitDictionaryType(DictionaryType *T) {
70707082
if (Options.AlwaysDesugarDictionaryTypes) {
70717083
visit(T->getDesugaredType());

lib/AST/ASTWalker.cpp

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

2251+
bool Traversal::visitInlineArrayTypeRepr(InlineArrayTypeRepr *T) {
2252+
return doIt(T->getCount()) || doIt(T->getElement());
2253+
}
2254+
22512255
bool Traversal::visitDictionaryTypeRepr(DictionaryTypeRepr *T) {
22522256
return doIt(T->getKey()) || doIt(T->getValue());
22532257
}

0 commit comments

Comments
 (0)