Skip to content

Parse an ellipsis T... for type parameter packs #61575

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 3 commits into from
Oct 15, 2022
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/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1357,7 +1357,7 @@ class ASTContext final {
/// Get a generic signature where the generic parameter τ_d_i represents
/// the element of the pack generic parameter τ_d_i… in \p baseGenericSig.
///
/// This drops the @_typeSequence attribute from each generic parameter,
/// This drops the parameter pack bit from each generic parameter,
/// and converts same-element requirements to same-type requirements.
CanGenericSignature getOpenedElementSignature(CanGenericSignature baseGenericSig);

Expand Down
14 changes: 0 additions & 14 deletions include/swift/AST/Attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -2190,20 +2190,6 @@ class NonSendableAttr : public DeclAttribute {
}
};

/// The @_typeSequence attribute, which treats a generic param decl as a variadic
/// sequence of value/type pairs.
class TypeSequenceAttr : public DeclAttribute {
TypeSequenceAttr(SourceLoc atLoc, SourceRange Range);

public:
static TypeSequenceAttr *create(ASTContext &Ctx, SourceLoc atLoc,
SourceRange Range);

static bool classof(const DeclAttribute *DA) {
return DA->getKind() == DAK_TypeSequence;
}
};

/// The @_unavailableFromAsync attribute, used to make function declarations
/// unavailable from async contexts.
class UnavailableFromAsyncAttr : public DeclAttribute {
Expand Down
124 changes: 110 additions & 14 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3166,15 +3166,20 @@ class AbstractTypeParamDecl : public TypeDecl {
/// \code
/// func min<T : Comparable>(x : T, y : T) -> T { ... }
/// \endcode
class GenericTypeParamDecl final :
public AbstractTypeParamDecl,
private llvm::TrailingObjects<GenericTypeParamDecl, TypeRepr *>{
class GenericTypeParamDecl final
: public AbstractTypeParamDecl,
private llvm::TrailingObjects<GenericTypeParamDecl, TypeRepr *,
SourceLoc> {
friend TrailingObjects;

size_t numTrailingObjects(OverloadToken<OpaqueReturnTypeRepr *>) const {
size_t numTrailingObjects(OverloadToken<TypeRepr *>) const {
return isOpaqueType() ? 1 : 0;
}

size_t numTrailingObjects(OverloadToken<SourceLoc>) const {
return isParameterPack() ? 1 : 0;
}

/// Construct a new generic type parameter.
///
/// \param dc The DeclContext in which the generic type parameter's owner
Expand All @@ -3183,11 +3188,20 @@ 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 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...>.
/// \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,
bool isParameterPack, unsigned depth, unsigned index,
bool isOpaqueType, TypeRepr *typeRepr);
SourceLoc ellipsisLoc, unsigned depth, unsigned index,
bool isParameterPack, bool isOpaqueType,
TypeRepr *opaqueTypeRepr);

public:
/// Construct a new generic type parameter.
///
/// \param dc The DeclContext in which the generic type parameter's owner
Expand All @@ -3196,17 +3210,91 @@ class GenericTypeParamDecl final :
///
/// \param name The name of the generic parameter.
/// \param nameLoc The location of the name.
GenericTypeParamDecl(DeclContext *dc, Identifier name, SourceLoc nameLoc,
bool isParameterPack, unsigned depth, unsigned index)
: GenericTypeParamDecl(dc, name, nameLoc, isParameterPack, depth, index,
false, nullptr) { }
/// \param ellipsisLoc The location of the ellipsis 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...>.
/// \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,
unsigned depth, unsigned index,
bool isParameterPack, bool isOpaqueType,
TypeRepr *opaqueTypeRepr);

public:
static const unsigned InvalidDepth = 0xFFFF;

/// 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,
bool isParameterPack)
: GenericTypeParamDecl(dc, name, nameLoc, ellipsisLoc, depth, index,
isParameterPack, /*isOpaqueType*/ false, nullptr) {
}

/// Construct a deserialized generic type parameter.
///
/// \param dc The DeclContext in which the generic type parameter's owner
/// occurs. This should later be overwritten with the actual declaration
/// context that owns the type parameter.
///
/// \param name The name of the generic parameter.
/// \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...>.
/// \param isOpaqueType Whether the generic parameter is written as an opaque
/// parameter e.g 'some Collection'.
///
static GenericTypeParamDecl *
createDeserialized(DeclContext *dc, Identifier name, unsigned depth,
unsigned index, bool isParameterPack, bool isOpaqueType);

/// Construct a new parsed generic type parameter.
///
/// \param dc The DeclContext in which the generic type parameter's owner
/// occurs. This should later be overwritten with the actual declaration
/// context that owns the type parameter.
///
/// \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 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...>.
///
static GenericTypeParamDecl *
createParsed(DeclContext *dc, Identifier name, SourceLoc nameLoc,
SourceLoc ellipsisLoc, unsigned index, bool isParameterPack);

/// Construct a new implicit generic type parameter.
///
/// \param dc The DeclContext in which the generic type parameter's owner
/// occurs. This should later be overwritten with the actual declaration
/// context that owns the type parameter.
///
/// \param name The name of the generic parameter.
/// \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...>.
/// \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.
///
static GenericTypeParamDecl *
create(DeclContext *dc, Identifier name, SourceLoc nameLoc,
bool isParameterPack, unsigned depth, unsigned index,
bool isOpaqueType, TypeRepr *typeRepr);
createImplicit(DeclContext *dc, Identifier name, unsigned depth,
unsigned index, bool isParameterPack = false,
bool isOpaqueType = false, TypeRepr *opaqueTypeRepr = nullptr,
SourceLoc nameLoc = SourceLoc(),
SourceLoc ellipsisLoc = SourceLoc());

/// The depth of this generic type parameter, i.e., the number of outer
/// levels of generic parameter lists that enclose this type parameter.
Expand Down Expand Up @@ -3273,6 +3361,14 @@ 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 {
if (!isParameterPack())
return SourceLoc();

return *getTrailingObjects<SourceLoc>();
}

SourceLoc getStartLoc() const { return getNameLoc(); }
SourceRange getSourceRange() const;

Expand Down
7 changes: 7 additions & 0 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -1964,6 +1964,13 @@ ERROR(attr_requires_concurrency, none,
"concurrency is enabled",
(StringRef, bool))

//------------------------------------------------------------------------------
// MARK: Variadics
//------------------------------------------------------------------------------

ERROR(associatedtype_cannot_be_variadic,none,
"associated types cannot be variadic", ())

//------------------------------------------------------------------------------
// MARK: Consistency diagnostics
//------------------------------------------------------------------------------
Expand Down
8 changes: 0 additions & 8 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -6482,14 +6482,6 @@ ERROR(noimplicitcopy_attr_valid_only_on_local_let_params,
ERROR(noimplicitcopy_attr_invalid_in_generic_context,
none, "'@_noImplicitCopy' attribute cannot be applied to entities in generic contexts", ())

//------------------------------------------------------------------------------
// MARK: variadics
//------------------------------------------------------------------------------

ERROR(type_sequence_on_non_generic_param, none,
"'@_typeSequence' must appear on a generic parameter",
())

//------------------------------------------------------------------------------
// MARK: Type inference from default expressions
//------------------------------------------------------------------------------
Expand Down
8 changes: 8 additions & 0 deletions include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,9 @@ class Parser {
/// Check whether the current token starts with '>'.
bool startsWithGreater(Token Tok) { return startsWithSymbol(Tok, '>'); }

/// Check whether the current token starts with '...'.
bool startsWithEllipsis(Token Tok);

/// Returns true if token is an identifier with the given value.
bool isIdentifier(Token Tok, StringRef value) {
return Tok.is(tok::identifier) && Tok.getText() == value;
Expand All @@ -822,6 +825,11 @@ class Parser {
/// e.g., '>>'.
SourceLoc consumeStartingGreater();

/// Consume the starting '...' of the current token, which may either be a
/// complete '...' token or some kind of operator token starting with '...',
/// e.g '...>'.
SourceLoc consumeStartingEllipsis();

/// Consume the starting character of the current token, and split the
/// remainder of the token into a new token (or tokens).
SourceLoc
Expand Down
8 changes: 3 additions & 5 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ struct ASTContext::Implementation {
ExistentialSignatures;

/// The element signature for a generic signature, constructed by dropping
/// @_typeSequence attributes from generic parameters.
/// the parameter pack bit from generic parameters.
llvm::DenseMap<const GenericSignatureImpl *,
CanGenericSignature> ElementSignatures;

Expand Down Expand Up @@ -5459,10 +5459,8 @@ GenericParamList *ASTContext::getSelfGenericParamList(DeclContext *dc) const {
// Note: we always return a GenericParamList rooted at the first
// DeclContext this was called with. Since this is just a giant
// hack for SIL mode, that should be OK.
auto *selfParam = GenericTypeParamDecl::create(
dc, Id_Self, SourceLoc(),
/*isParameterPack=*/false, /*depth=*/0, /*index=*/0,
/*isOpaqueType=*/false, /*opaqueTypeRepr=*/nullptr);
auto *selfParam = GenericTypeParamDecl::createImplicit(
dc, Id_Self, /*depth*/ 0, /*index*/ 0);

theParamList = GenericParamList::create(
const_cast<ASTContext &>(*this), SourceLoc(), {selfParam}, SourceLoc());
Expand Down
9 changes: 4 additions & 5 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1684,9 +1684,6 @@ void PrintAST::printSingleDepthOfGenericSignature(
llvm::interleave(
genericParams,
[&](GenericTypeParamType *param) {
if (param->isParameterPack())
Printer.printAttrName("@_typeSequence ");

if (!subMap.empty()) {
printType(substParam(param));
} else if (auto *GP = param->getDecl()) {
Expand All @@ -1699,6 +1696,8 @@ void PrintAST::printSingleDepthOfGenericSignature(
} else {
printType(param);
}
if (param->isParameterPack())
Printer << "...";
},
[&] { Printer << ", "; });
}
Expand Down Expand Up @@ -3502,9 +3501,9 @@ void PrintAST::visitTypeAliasDecl(TypeAliasDecl *decl) {

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

printInherited(decl);
Expand Down
16 changes: 0 additions & 16 deletions lib/AST/Attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1264,11 +1264,6 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
break;
}

case DAK_TypeSequence: {
Printer.printAttrName("@_typeSequence");
break;
}

case DAK_UnavailableFromAsync: {
Printer.printAttrName("@_unavailableFromAsync");
const UnavailableFromAsyncAttr *attr = cast<UnavailableFromAsyncAttr>(this);
Expand Down Expand Up @@ -1454,8 +1449,6 @@ StringRef DeclAttribute::getAttrName() const {
return "derivative";
case DAK_Transpose:
return "transpose";
case DAK_TypeSequence:
return "_typeSequence";
case DAK_UnavailableFromAsync:
return "_unavailableFromAsync";
case DAK_BackDeploy:
Expand Down Expand Up @@ -2289,15 +2282,6 @@ bool CustomAttr::isArgUnsafe() const {
return isArgUnsafeBit;
}

TypeSequenceAttr::TypeSequenceAttr(SourceLoc atLoc, SourceRange range)
: DeclAttribute(DAK_TypeSequence, atLoc, range, /*Implicit=*/false) {}

TypeSequenceAttr *TypeSequenceAttr::create(ASTContext &Ctx, SourceLoc atLoc,
SourceRange range) {
void *mem = Ctx.Allocate(sizeof(TypeSequenceAttr), alignof(TypeSequenceAttr));
return new (mem) TypeSequenceAttr(atLoc, range);
}

const DeclAttribute *
DeclAttributes::getEffectiveSendableAttr() const {
const NonSendableAttr *assumedAttr = nullptr;
Expand Down
6 changes: 2 additions & 4 deletions lib/AST/Builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,8 @@ static GenericTypeParamDecl*
createGenericParam(ASTContext &ctx, const char *name, unsigned index) {
ModuleDecl *M = ctx.TheBuiltinModule;
Identifier ident = ctx.getIdentifier(name);
auto genericParam = GenericTypeParamDecl::create(
&M->getMainFile(FileUnitKind::Builtin), ident, SourceLoc(),
/*isParameterPack*/ false, 0, index, /*opaque type=*/false, nullptr);
return genericParam;
return GenericTypeParamDecl::createImplicit(
&M->getMainFile(FileUnitKind::Builtin), ident, /*depth*/ 0, index);
}

/// Create a generic parameter list with multiple generic parameters.
Expand Down
Loading