Skip to content

Commit 41298c2

Browse files
committed
[AST] Introduce PackReferenceTypeRepr for pack references spelled with
a contextual 'each' keyword.
1 parent 1f3397a commit 41298c2

File tree

10 files changed

+105
-0
lines changed

10 files changed

+105
-0
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5150,6 +5150,12 @@ ERROR(expansion_not_allowed,none,
51505150
"function result, tuple element or generic argument list", (Type))
51515151
ERROR(expansion_not_variadic,none,
51525152
"variadic expansion %0 must contain at least one variadic generic parameter", (Type))
5153+
ERROR(pack_reference_outside_expansion,none,
5154+
"pack reference %0 can only appear in pack expansion or generic requirement",
5155+
(Type))
5156+
ERROR(each_non_pack,none,
5157+
"'each' cannot be applied to non-pack type %0",
5158+
(Type))
51535159
ERROR(tuple_duplicate_label,none,
51545160
"cannot create a tuple with a duplicate element label", ())
51555161
ERROR(multiple_ellipsis_in_tuple,none,

include/swift/AST/TypeRepr.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,41 @@ class PackExpansionTypeRepr final : public TypeRepr {
743743
friend class TypeRepr;
744744
};
745745

746+
/// A pack reference spelled with the \c each keyword.
747+
///
748+
/// Pack references can only appear inside pack expansions and in
749+
/// generic requirements.
750+
///
751+
/// \code
752+
/// struct Generic<T...> {
753+
/// func f(value: (each T)...) where each T: P {}
754+
/// }
755+
/// \endcode
756+
class PackReferenceTypeRepr: public TypeRepr {
757+
TypeRepr *PackType;
758+
SourceLoc EachLoc;
759+
760+
public:
761+
PackReferenceTypeRepr(SourceLoc eachLoc, TypeRepr *packType)
762+
: TypeRepr(TypeReprKind::PackReference), PackType(packType),
763+
EachLoc(eachLoc) {}
764+
765+
TypeRepr *getPackType() const { return PackType; }
766+
SourceLoc getEachLoc() const { return EachLoc; }
767+
768+
static bool classof(const TypeRepr *T) {
769+
return T->getKind() == TypeReprKind::PackReference;
770+
}
771+
static bool classof(const PackReferenceTypeRepr *T) { return true; }
772+
773+
private:
774+
SourceLoc getStartLocImpl() const { return EachLoc; }
775+
SourceLoc getEndLocImpl() const { return PackType->getEndLoc(); }
776+
SourceLoc getLocImpl() const { return EachLoc; }
777+
void printImpl(ASTPrinter &Printer, const PrintOptions &Opts) const;
778+
friend class TypeRepr;
779+
};
780+
746781
/// A tuple type.
747782
/// \code
748783
/// (Foo, Bar)
@@ -1336,6 +1371,7 @@ inline bool TypeRepr::isSimple() const {
13361371
case TypeReprKind::OpaqueReturn:
13371372
case TypeReprKind::NamedOpaqueReturn:
13381373
case TypeReprKind::Existential:
1374+
case TypeReprKind::PackReference:
13391375
return false;
13401376
case TypeReprKind::SimpleIdent:
13411377
case TypeReprKind::GenericIdent:

include/swift/AST/TypeReprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ TYPEREPR(Protocol, TypeRepr)
6464
TYPEREPR(OpaqueReturn, TypeRepr)
6565
TYPEREPR(NamedOpaqueReturn, TypeRepr)
6666
TYPEREPR(Existential, TypeRepr)
67+
TYPEREPR(PackReference, TypeRepr)
6768
TYPEREPR(Placeholder, TypeRepr)
6869
ABSTRACT_TYPEREPR(Specifier, TypeRepr)
6970
SPECIFIER_TYPEREPR(InOut, SpecifierTypeRepr)

lib/AST/ASTDumper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3141,6 +3141,12 @@ class PrintTypeRepr : public TypeReprVisitor<PrintTypeRepr> {
31413141
PrintWithColorRAII(OS, ParenthesisColor) << ')';
31423142
}
31433143

3144+
void visitPackReferenceTypeRepr(PackReferenceTypeRepr *T) {
3145+
printCommon("pack_reference");
3146+
printRec(T->getPackType());
3147+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
3148+
}
3149+
31443150
void visitTupleTypeRepr(TupleTypeRepr *T) {
31453151
printCommon("type_tuple");
31463152

lib/AST/ASTWalker.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1995,6 +1995,10 @@ bool Traversal::visitPackExpansionTypeRepr(PackExpansionTypeRepr *T) {
19951995
return doIt(T->getPatternType());
19961996
}
19971997

1998+
bool Traversal::visitPackReferenceTypeRepr(PackReferenceTypeRepr *T) {
1999+
return doIt(T->getPackType());
2000+
}
2001+
19982002
bool Traversal::visitTupleTypeRepr(TupleTypeRepr *T) {
19992003
for (auto &elem : T->getElements()) {
20002004
if (doIt(elem.Type))

lib/AST/NameLookup.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2516,6 +2516,13 @@ directReferencesForTypeRepr(Evaluator &evaluator,
25162516
allowUsableFromInline);
25172517
}
25182518

2519+
case TypeReprKind::PackReference: {
2520+
auto packReferenceRepr = cast<PackReferenceTypeRepr>(typeRepr);
2521+
return directReferencesForTypeRepr(evaluator, ctx,
2522+
packReferenceRepr->getPackType(), dc,
2523+
allowUsableFromInline);
2524+
}
2525+
25192526
case TypeReprKind::Error:
25202527
case TypeReprKind::Function:
25212528
case TypeReprKind::InOut:

lib/AST/TypeRepr.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,12 @@ void PackExpansionTypeRepr::printImpl(ASTPrinter &Printer,
413413
Printer << "...";
414414
}
415415

416+
void PackReferenceTypeRepr::printImpl(ASTPrinter &Printer,
417+
const PrintOptions &Opts) const {
418+
Printer.printKeyword("each", Opts, /*Suffix=*/" ");
419+
printTypeRepr(PackType, Printer, Opts);
420+
}
421+
416422
void TupleTypeRepr::printImpl(ASTPrinter &Printer,
417423
const PrintOptions &Opts) const {
418424
Printer.callPrintStructurePre(PrintStructureKind::TupleType);

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,7 @@ RequirementRequest::evaluate(Evaluator &evaluator,
966966
context = TypeResolverContext::GenericRequirement;
967967
}
968968
auto options = TypeResolutionOptions(context);
969+
options |= TypeResolutionFlags::AllowPackReferences;
969970
if (owner.dc->isInSpecializeExtensionContext())
970971
options |= TypeResolutionFlags::AllowUsableFromInline;
971972
Optional<TypeResolution> resolution;

lib/Sema/TypeCheckType.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2088,6 +2088,8 @@ namespace {
20882088
TypeResolutionOptions options);
20892089
NeverNullType resolvePackExpansionType(PackExpansionTypeRepr *repr,
20902090
TypeResolutionOptions options);
2091+
NeverNullType resolvePackReference(PackReferenceTypeRepr *repr,
2092+
TypeResolutionOptions options);
20912093
NeverNullType resolveTupleType(TupleTypeRepr *repr,
20922094
TypeResolutionOptions options);
20932095
NeverNullType resolveCompositionType(CompositionTypeRepr *repr,
@@ -2277,6 +2279,9 @@ NeverNullType TypeResolver::resolveType(TypeRepr *repr,
22772279
case TypeReprKind::PackExpansion:
22782280
return resolvePackExpansionType(cast<PackExpansionTypeRepr>(repr), options);
22792281

2282+
case TypeReprKind::PackReference:
2283+
return resolvePackReference(cast<PackReferenceTypeRepr>(repr), options);
2284+
22802285
case TypeReprKind::Tuple:
22812286
return resolveTupleType(cast<TupleTypeRepr>(repr), options);
22822287

@@ -4182,6 +4187,7 @@ std::pair<Type, Type>
41824187
TypeResolver::maybeResolvePackExpansionType(PackExpansionTypeRepr *repr,
41834188
TypeResolutionOptions options) {
41844189
auto elementOptions = options;
4190+
elementOptions |= TypeResolutionFlags::AllowPackReferences;
41854191
auto patternTy = resolveType(repr->getPatternType(), elementOptions);
41864192
if (patternTy->hasError())
41874193
return std::make_pair(ErrorType::get(getASTContext()), Type());
@@ -4243,6 +4249,31 @@ NeverNullType TypeResolver::resolvePackExpansionType(PackExpansionTypeRepr *repr
42434249
return PackExpansionType::get(pair.first, pair.second);
42444250
}
42454251

4252+
NeverNullType TypeResolver::resolvePackReference(PackReferenceTypeRepr *repr,
4253+
TypeResolutionOptions options) {
4254+
auto &ctx = getASTContext();
4255+
auto packReference = resolveType(repr->getPackType(), options);
4256+
4257+
// If we already failed, don't diagnose again.
4258+
if (packReference->hasError())
4259+
return ErrorType::get(ctx);
4260+
4261+
if (!packReference->isParameterPack()) {
4262+
ctx.Diags.diagnose(repr->getLoc(), diag::each_non_pack,
4263+
packReference);
4264+
return packReference;
4265+
}
4266+
4267+
if (!options.contains(TypeResolutionFlags::AllowPackReferences)) {
4268+
ctx.Diags.diagnose(repr->getLoc(),
4269+
diag::pack_reference_outside_expansion,
4270+
packReference);
4271+
return packReference;
4272+
}
4273+
4274+
return packReference;
4275+
}
4276+
42464277
NeverNullType TypeResolver::resolveTupleType(TupleTypeRepr *repr,
42474278
TypeResolutionOptions options) {
42484279
auto &ctx = getASTContext();
@@ -4739,6 +4770,7 @@ class ExistentialTypeVisitor
47394770
case TypeReprKind::Placeholder:
47404771
case TypeReprKind::CompileTimeConst:
47414772
case TypeReprKind::PackExpansion:
4773+
case TypeReprKind::PackReference:
47424774
return false;
47434775
}
47444776
}

lib/Sema/TypeCheckType.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ enum class TypeResolutionFlags : uint16_t {
7070

7171
/// We are in a `@preconcurrency` declaration.
7272
Preconcurrency = 1 << 10,
73+
74+
/// Whether references to type parameter packs are allowed.
75+
///
76+
/// Pack references are only allowed inside pack expansions
77+
/// and in generic requirements.
78+
AllowPackReferences = 1 << 11,
7379
};
7480

7581
/// Type resolution contexts that require special handling.

0 commit comments

Comments
 (0)