Skip to content

[Variadic Generics] type parameter pack syntax change: T... -> each T #64039

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/swift/AST/CASTBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ void *GenericParamList_create(void *ctx, void *lAngleLoc,
BridgedArrayRef reqs, void *rAngleLoc);
void *GenericTypeParamDecl_create(void *ctx, void *declContext,
BridgedIdentifier name, void *nameLoc,
void *_Nullable ellipsisLoc, long index,
void *_Nullable eachLoc, long index,
_Bool isParameterPack);
void GenericTypeParamDecl_setInheritedType(void *ctx, void *Param, void *ty);

Expand Down
48 changes: 26 additions & 22 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3331,17 +3331,18 @@ class GenericTypeParamDecl final
///
/// \param name The name of the generic parameter.
/// \param nameLoc The location of the name.
/// \param ellipsisLoc The location of the ellipsis for a type parameter pack.
/// \param eachLoc The location of the 'each' keyword for a type parameter
/// pack.
/// \param depth The generic signature depth.
/// \param index The index of the parameter in the generic signature.
/// \param isParameterPack Whether the generic parameter is for a type
/// parameter pack, denoted by \c <T...>.
/// parameter pack, denoted by \c <each T>.
/// \param isOpaqueType Whether the generic parameter is written as an opaque
/// parameter e.g 'some Collection'.
/// \param opaqueTypeRepr The TypeRepr of an opaque generic parameter.
///
GenericTypeParamDecl(DeclContext *dc, Identifier name, SourceLoc nameLoc,
SourceLoc ellipsisLoc, unsigned depth, unsigned index,
SourceLoc eachLoc, unsigned depth, unsigned index,
bool isParameterPack, bool isOpaqueType,
TypeRepr *opaqueTypeRepr);

Expand All @@ -3353,17 +3354,18 @@ class GenericTypeParamDecl final
///
/// \param name The name of the generic parameter.
/// \param nameLoc The location of the name.
/// \param ellipsisLoc The location of the ellipsis for a type parameter pack.
/// \param eachLoc The location of the 'each' keyword for a type parameter
/// pack.
/// \param depth The generic signature depth.
/// \param index The index of the parameter in the generic signature.
/// \param isParameterPack Whether the generic parameter is for a type
/// parameter pack, denoted by \c <T...>.
/// parameter pack, denoted by \c <each T>.
/// \param isOpaqueType Whether the generic parameter is written as an opaque
/// parameter e.g 'some Collection'.
/// \param opaqueTypeRepr The TypeRepr of an opaque generic parameter.
///
static GenericTypeParamDecl *create(DeclContext *dc, Identifier name,
SourceLoc nameLoc, SourceLoc ellipsisLoc,
SourceLoc nameLoc, SourceLoc eachLoc,
unsigned depth, unsigned index,
bool isParameterPack, bool isOpaqueType,
TypeRepr *opaqueTypeRepr);
Expand All @@ -3374,9 +3376,9 @@ class GenericTypeParamDecl final
/// Construct a new generic type parameter. This should only be used by the
/// ClangImporter, use \c GenericTypeParamDecl::create[...] instead.
GenericTypeParamDecl(DeclContext *dc, Identifier name, SourceLoc nameLoc,
SourceLoc ellipsisLoc, unsigned depth, unsigned index,
SourceLoc eachLoc, unsigned depth, unsigned index,
bool isParameterPack)
: GenericTypeParamDecl(dc, name, nameLoc, ellipsisLoc, depth, index,
: GenericTypeParamDecl(dc, name, nameLoc, eachLoc, depth, index,
isParameterPack, /*isOpaqueType*/ false, nullptr) {
}

Expand All @@ -3390,7 +3392,7 @@ class GenericTypeParamDecl final
/// \param depth The generic signature depth.
/// \param index The index of the parameter in the generic signature.
/// \param isParameterPack Whether the generic parameter is for a type
/// parameter pack, denoted by \c <T...>.
/// parameter pack, denoted by \c <each T>.
/// \param isOpaqueType Whether the generic parameter is written as an opaque
/// parameter e.g 'some Collection'.
///
Expand All @@ -3406,14 +3408,16 @@ class GenericTypeParamDecl final
///
/// \param name The name of the generic parameter.
/// \param nameLoc The location of the name.
/// \param ellipsisLoc The location of the ellipsis for a type parameter pack.
/// \param eachLoc The location of the 'each' keyword for a type parameter
/// pack.
/// \param index The index of the parameter in the generic signature.
/// \param isParameterPack Whether the generic parameter is for a type
/// parameter pack, denoted by \c <T...>.
/// parameter pack, denoted by \c <each T>.
///
static GenericTypeParamDecl *
createParsed(DeclContext *dc, Identifier name, SourceLoc nameLoc,
SourceLoc ellipsisLoc, unsigned index, bool isParameterPack);
static GenericTypeParamDecl *createParsed(DeclContext *dc, Identifier name,
SourceLoc nameLoc,
SourceLoc eachLoc, unsigned index,
bool isParameterPack);

/// Construct a new implicit generic type parameter.
///
Expand All @@ -3425,19 +3429,19 @@ class GenericTypeParamDecl final
/// \param depth The generic signature depth.
/// \param index The index of the parameter in the generic signature.
/// \param isParameterPack Whether the generic parameter is for a type
/// parameter pack, denoted by \c <T...>.
/// parameter pack, denoted by \c <each T>.
/// \param isOpaqueType Whether the generic parameter is written as an opaque
/// parameter e.g 'some Collection'.
/// \param opaqueTypeRepr The TypeRepr of an opaque generic parameter.
/// \param nameLoc The location of the name.
/// \param ellipsisLoc The location of the ellipsis for a type parameter pack.
/// \param eachLoc The location of the 'each' keyword for a type parameter
/// pack.
///
static GenericTypeParamDecl *
createImplicit(DeclContext *dc, Identifier name, unsigned depth,
unsigned index, bool isParameterPack = false,
bool isOpaqueType = false, TypeRepr *opaqueTypeRepr = nullptr,
SourceLoc nameLoc = SourceLoc(),
SourceLoc ellipsisLoc = SourceLoc());
SourceLoc nameLoc = {}, SourceLoc eachLoc = {});

/// The depth of this generic type parameter, i.e., the number of outer
/// levels of generic parameter lists that enclose this type parameter.
Expand All @@ -3463,8 +3467,8 @@ class GenericTypeParamDecl final
/// parameter pack.
///
/// \code
/// func foo<T...>(_ : T...) { }
/// struct Foo<T...> { }
/// func foo<each T>(_ : for each T) { }
/// struct Foo<each T> { }
/// \endcode
bool isParameterPack() const { return Bits.GenericTypeParamDecl.ParameterPack; }

Expand Down Expand Up @@ -3504,8 +3508,8 @@ class GenericTypeParamDecl final
/// Here 'T' and 'U' have indexes 0 and 1, respectively. 'V' has index 0.
unsigned getIndex() const { return Bits.GenericTypeParamDecl.Index; }

/// Retrieve the ellipsis location for a type parameter pack \c T...
SourceLoc getEllipsisLoc() const {
/// Retrieve the 'each' keyword location for a type parameter pack \c each T
SourceLoc getEachLoc() const {
if (!isParameterPack())
return SourceLoc();

Expand Down
2 changes: 2 additions & 0 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -1989,6 +1989,8 @@ ERROR(attr_requires_concurrency, none,

ERROR(associatedtype_cannot_be_variadic,none,
"associated types cannot be variadic", ())
ERROR(type_parameter_pack_ellipsis,none,
"ellipsis operator cannot be used with a type parameter pack", ())

//------------------------------------------------------------------------------
// MARK: syntax parsing diagnostics
Expand Down
4 changes: 0 additions & 4 deletions include/swift/AST/Identifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,6 @@ class Identifier {
return is("??");
}

bool isExpansionOperator() const {
return is("...");
}

/// isOperatorStartCodePoint - Return true if the specified code point is a
/// valid start of an operator.
static bool isOperatorStartCodePoint(uint32_t C) {
Expand Down
2 changes: 1 addition & 1 deletion include/swift/IRGen/IRABIDetailsProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class LoweredFunctionSignature {
friend class LoweredFunctionSignature;
};

/// Represents a generic requirement paremeter that must be passed to the
/// Represents a generic requirement parameter that must be passed to the
/// function.
class GenericRequirementParameter {
public:
Expand Down
14 changes: 7 additions & 7 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1713,6 +1713,8 @@ void PrintAST::printSingleDepthOfGenericSignature(
llvm::interleave(
genericParams,
[&](GenericTypeParamType *param) {
if (param->isParameterPack())
Printer << "each ";
if (!subMap.empty()) {
printType(substParam(param));
} else if (auto *GP = param->getDecl()) {
Expand All @@ -1725,8 +1727,6 @@ void PrintAST::printSingleDepthOfGenericSignature(
} else {
printType(param);
}
if (param->isParameterPack())
Printer << "...";
},
[&] { Printer << ", "; });
}
Expand Down Expand Up @@ -1816,11 +1816,11 @@ void PrintAST::printSingleDepthOfGenericSignature(
void PrintAST::printRequirement(const Requirement &req) {
switch (req.getKind()) {
case RequirementKind::SameShape:
Printer << "((";
Printer << "(repeat (each ";
printTransformedType(req.getFirstType());
Printer << ", ";
Printer << ", each ";
printTransformedType(req.getSecondType());
Printer << ")...) : Any";
Printer << ")) : Any";
return;
case RequirementKind::Layout:
printTransformedType(req.getFirstType());
Expand Down Expand Up @@ -3599,9 +3599,9 @@ void PrintAST::visitTypeAliasDecl(TypeAliasDecl *decl) {

void PrintAST::visitGenericTypeParamDecl(GenericTypeParamDecl *decl) {
recordDeclLoc(decl, [&] {
Printer.printName(decl->getName(), PrintNameContext::GenericParameter);
if (decl->isParameterPack())
Printer << "...";
Printer << "each ";
Printer.printName(decl->getName(), PrintNameContext::GenericParameter);
});

printInherited(decl);
Expand Down
4 changes: 2 additions & 2 deletions lib/AST/CASTBridging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -579,12 +579,12 @@ void *GenericParamList_create(void *ctx, void *lAngleLoc,

void *GenericTypeParamDecl_create(void *ctx, void *declContext,
BridgedIdentifier name, void *nameLoc,
void *_Nullable ellipsisLoc, long index,
void *_Nullable eachLoc, long index,
bool isParameterPack) {
return GenericTypeParamDecl::createParsed(
static_cast<DeclContext *>(declContext),
Identifier::getFromOpaquePointer(name), getSourceLocFromPointer(nameLoc),
getSourceLocFromPointer(ellipsisLoc),
getSourceLocFromPointer(eachLoc),
/*index*/ index, isParameterPack);
}

Expand Down
41 changes: 22 additions & 19 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4865,13 +4865,15 @@ Type TypeAliasDecl::getStructuralType() const {
return ErrorType::get(ctx);
}

GenericTypeParamDecl::GenericTypeParamDecl(
DeclContext *dc, Identifier name, SourceLoc nameLoc, SourceLoc ellipsisLoc,
unsigned depth, unsigned index, bool isParameterPack, bool isOpaqueType,
TypeRepr *opaqueTypeRepr)
: TypeDecl(DeclKind::GenericTypeParam, dc, name, nameLoc, { }) {
assert(!(ellipsisLoc && !isParameterPack) &&
"Ellipsis always means type parameter pack");
GenericTypeParamDecl::GenericTypeParamDecl(DeclContext *dc, Identifier name,
SourceLoc nameLoc, SourceLoc eachLoc,
unsigned depth, unsigned index,
bool isParameterPack,
bool isOpaqueType,
TypeRepr *opaqueTypeRepr)
: TypeDecl(DeclKind::GenericTypeParam, dc, name, nameLoc, {}) {
assert(!(eachLoc && !isParameterPack) &&
"'each' keyword always means type parameter pack");

Bits.GenericTypeParamDecl.Depth = depth;
assert(Bits.GenericTypeParamDecl.Depth == depth && "Truncation");
Expand All @@ -4883,7 +4885,7 @@ GenericTypeParamDecl::GenericTypeParamDecl(
if (isOpaqueType)
*getTrailingObjects<TypeRepr *>() = opaqueTypeRepr;
if (isParameterPack)
*getTrailingObjects<SourceLoc>() = ellipsisLoc;
*getTrailingObjects<SourceLoc>() = eachLoc;

auto &ctx = dc->getASTContext();
RecursiveTypeProperties props = RecursiveTypeProperties::HasTypeParameter;
Expand All @@ -4894,15 +4896,15 @@ GenericTypeParamDecl::GenericTypeParamDecl(
}

GenericTypeParamDecl *GenericTypeParamDecl::create(
DeclContext *dc, Identifier name, SourceLoc nameLoc, SourceLoc ellipsisLoc,
DeclContext *dc, Identifier name, SourceLoc nameLoc, SourceLoc eachLoc,
unsigned depth, unsigned index, bool isParameterPack, bool isOpaqueType,
TypeRepr *opaqueTypeRepr) {
auto &ctx = dc->getASTContext();
auto allocSize = totalSizeToAlloc<TypeRepr *, SourceLoc>(
isOpaqueType ? 1 : 0, isParameterPack ? 1 : 0);
auto mem = ctx.Allocate(allocSize, alignof(GenericTypeParamDecl));
return new (mem)
GenericTypeParamDecl(dc, name, nameLoc, ellipsisLoc, depth, index,
GenericTypeParamDecl(dc, name, nameLoc, eachLoc, depth, index,
isParameterPack, isOpaqueType, opaqueTypeRepr);
}

Expand All @@ -4916,37 +4918,38 @@ GenericTypeParamDecl *GenericTypeParamDecl::createDeserialized(

GenericTypeParamDecl *
GenericTypeParamDecl::createParsed(DeclContext *dc, Identifier name,
SourceLoc nameLoc, SourceLoc ellipsisLoc,
SourceLoc nameLoc, SourceLoc eachLoc,
unsigned index, bool isParameterPack) {
// We always create generic type parameters with an invalid depth.
// Semantic analysis fills in the depth when it processes the generic
// parameter list.
return GenericTypeParamDecl::create(
dc, name, nameLoc, ellipsisLoc, GenericTypeParamDecl::InvalidDepth, index,
dc, name, nameLoc, eachLoc, GenericTypeParamDecl::InvalidDepth, index,
isParameterPack, /*isOpaqueType*/ false, /*opaqueTypeRepr*/ nullptr);
}

GenericTypeParamDecl *GenericTypeParamDecl::createImplicit(
DeclContext *dc, Identifier name, unsigned depth, unsigned index,
bool isParameterPack, bool isOpaqueType, TypeRepr *opaqueTypeRepr,
SourceLoc nameLoc, SourceLoc ellipsisLoc) {
auto *param = GenericTypeParamDecl::create(dc, name, nameLoc, ellipsisLoc,
depth, index, isParameterPack,
SourceLoc nameLoc, SourceLoc eachLoc) {
auto *param = GenericTypeParamDecl::create(dc, name, nameLoc, eachLoc, depth,
index, isParameterPack,
isOpaqueType, opaqueTypeRepr);
param->setImplicit();
return param;
}

SourceRange GenericTypeParamDecl::getSourceRange() const {
SourceLoc endLoc = getNameLoc();
auto startLoc = getNameLoc();
auto endLoc = getNameLoc();

if (auto ellipsisLoc = getEllipsisLoc())
endLoc = ellipsisLoc;
if (const auto eachLoc = getEachLoc())
startLoc = eachLoc;

if (!getInherited().empty())
endLoc = getInherited().back().getSourceRange().End;

return SourceRange(getNameLoc(), endLoc);
return {startLoc, endLoc};
}

AssociatedTypeDecl::AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc,
Expand Down
6 changes: 3 additions & 3 deletions lib/ASTGen/Sources/ASTGen/Generics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ extension ASTGenVisitor {
return SwiftASTContext_getIdentifier(ctx, buf.baseAddress, buf.count)
}
let nameLoc = self.base.advanced(by: node.name.position.utf8Offset).raw
let ellipsisLoc = node.ellipsis.map { self.base.advanced(by: $0.position.utf8Offset).raw }
let eachLoc = node.each.map { self.base.advanced(by: $0.position.utf8Offset).raw }

return .decl(
GenericTypeParamDecl_create(
self.ctx, self.declContext, name, nameLoc, ellipsisLoc, node.indexInParent / 2,
ellipsisLoc != nil))
self.ctx, self.declContext, name, nameLoc, eachLoc, node.indexInParent / 2,
eachLoc != nil))
}
}

Expand Down
Loading