Skip to content

Introduce PackExpansionTypeRepr #60923

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 5 commits into from
Sep 7, 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
6 changes: 2 additions & 4 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -5904,10 +5904,8 @@ class ParamDecl : public VarDecl {

void setDefaultValueStringRepresentation(StringRef stringRepresentation);

/// Whether or not this parameter is varargs.
bool isVariadic() const {
return DefaultValueAndFlags.getInt().contains(Flags::IsVariadic);
}
/// Whether or not this parameter is old-style variadic.
bool isVariadic() const;
void setVariadic(bool value = true) {
auto flags = DefaultValueAndFlags.getInt();
DefaultValueAndFlags.setInt(value ? flags | Flags::IsVariadic
Expand Down
9 changes: 0 additions & 9 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -852,8 +852,6 @@ NOTE(subscript_array_element_fix_it_remove_space, none,
// Tuple Types
ERROR(expected_rparen_tuple_type_list,none,
"expected ')' at end of tuple list", ())
ERROR(multiple_ellipsis_in_tuple,none,
"only a single element can be variadic", ())
ERROR(tuple_type_init,none,
"default argument not permitted in a tuple type", ())
ERROR(protocol_method_argument_init,none,
Expand Down Expand Up @@ -959,8 +957,6 @@ ERROR(expected_parameter_colon,PointsToFirstBadToken,
"expected ':' following argument label and parameter name", ())
ERROR(expected_assignment_instead_of_comparison_operator,none,
"expected '=' instead of '==' to assign default value for parameter", ())
ERROR(parameter_vararg_default,none,
"variadic parameter cannot have a default value", ())
ERROR(parameter_specifier_as_attr_disallowed,none,
"'%0' before a parameter name is not allowed, place it before the parameter type instead",
(StringRef))
Expand Down Expand Up @@ -995,11 +991,6 @@ ERROR(false_available_is_called_unavailable,none,
ERROR(initializer_as_typed_pattern,none,
"unexpected initializer in pattern; did you mean to use '='?", ())

ERROR(unlabeled_parameter_following_variadic_parameter,none,
"a parameter following a variadic parameter requires a label", ())
ERROR(closure_unlabeled_parameter_following_variadic_parameter,none,
"no parameters may follow a variadic parameter in a closure", ())

ERROR(enum_element_empty_arglist,none,
"enum element with associated values must have at least one "
"associated value", ())
Expand Down
19 changes: 14 additions & 5 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -5014,14 +5014,25 @@ ERROR(dot_protocol_on_non_existential,none,
"cannot use 'Protocol' with non-protocol type %0", (Type))
ERROR(tuple_single_element,none,
"cannot create a single-element tuple with an element label", ())
ERROR(tuple_ellipsis,none,
"cannot create a variadic tuple", ())
ERROR(expansion_not_allowed,none,
"variadic expansion %0 cannot appear outside of a function parameter list, "
"function result, tuple element or generic argument list", (Type))
ERROR(expansion_not_variadic,none,
"cannot create expansion with non-variadic type %0", (Type))
"variadic expansion %0 must contain at least one variadic generic parameter", (Type))
ERROR(tuple_duplicate_label,none,
"cannot create a tuple with a duplicate element label", ())
ERROR(multiple_ellipsis_in_tuple,none,
"only a single element can be variadic", ())

ERROR(enum_element_ellipsis,none,
"variadic enum cases are not supported", ())
ERROR(unlabeled_parameter_following_variadic_parameter,none,
"a parameter following a variadic parameter requires a label", ())
ERROR(closure_unlabeled_parameter_following_variadic_parameter,none,
"no parameters may follow a variadic parameter in a closure", ())

ERROR(parameter_vararg_default,none,
"variadic parameter cannot have a default value", ())

WARNING(implicitly_unwrapped_optional_in_illegal_position_interpreted_as_optional,none,
"using '!' is not allowed here; treating this as '?' instead", ())
Expand Down Expand Up @@ -5142,8 +5153,6 @@ ERROR(opened_bad_constraint_type,none,
"@opened constraint type %0 is not a protocol or protocol composition", (Type))
ERROR(opened_bad_interface_type,none,
"@opened interface type %0 is not a type parameter", (Type))
ERROR(sil_function_ellipsis,PointsToFirstBadToken,
"SIL function types cannot be variadic", ())
ERROR(sil_function_input_label,PointsToFirstBadToken,
"SIL function types cannot have labeled inputs", ())
ERROR(sil_function_output_label,PointsToFirstBadToken,
Expand Down
88 changes: 45 additions & 43 deletions include/swift/AST/TypeRepr.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,7 @@ class alignas(1 << TypeReprAlignInBits) TypeRepr
Warned : 1
);

SWIFT_INLINE_BITFIELD_FULL(TupleTypeRepr, TypeRepr, 1+32,
/// Whether this tuple has '...' and its position.
HasEllipsis : 1,
: NumPadBits,
SWIFT_INLINE_BITFIELD_FULL(TupleTypeRepr, TypeRepr, 32,
/// The number of elements contained.
NumElements : 32
);
Expand Down Expand Up @@ -708,26 +705,62 @@ struct TupleTypeReprElement {
TupleTypeReprElement(TypeRepr *Type): Type(Type) {}
};

/// A pack expansion 'T...' with a pattern 'T'.
///
/// Can appear in the following positions:
/// - The type of a parameter declaration in a function declaration
/// - The type of a parameter in a function type
/// - The element of a tuple
///
/// In the first two cases, it also spells an old-style variadic parameter
/// desugaring to an array type. The two meanings are distinguished by the
/// presence of at least one pack type parameter in the pack expansion
/// pattern.
///
/// In the third case, tuples cannot contain an old-style variadic element,
/// so the pack expansion must be a real variadic pack expansion.
class PackExpansionTypeRepr final : public TypeRepr {
TypeRepr *Pattern;
SourceLoc EllipsisLoc;

public:
PackExpansionTypeRepr(TypeRepr *Pattern, SourceLoc EllipsisLoc)
: TypeRepr(TypeReprKind::PackExpansion), Pattern(Pattern),
EllipsisLoc(EllipsisLoc) {}

TypeRepr *getPatternType() const { return Pattern; }
SourceLoc getEllipsisLoc() const { return EllipsisLoc; }

static bool classof(const TypeRepr *T) {
return T->getKind() == TypeReprKind::PackExpansion;
}
static bool classof(const PackExpansionTypeRepr *T) { return true; }

private:
SourceLoc getStartLocImpl() const { return Pattern->getStartLoc(); }
SourceLoc getEndLocImpl() const { return EllipsisLoc; }
SourceLoc getLocImpl() const { return EllipsisLoc; }
void printImpl(ASTPrinter &Printer, const PrintOptions &Opts) const;
friend class TypeRepr;
};

/// A tuple type.
/// \code
/// (Foo, Bar)
/// (x: Foo)
/// (_ x: Foo)
/// \endcode
class TupleTypeRepr final : public TypeRepr,
private llvm::TrailingObjects<TupleTypeRepr, TupleTypeReprElement,
Located<unsigned>> {
private llvm::TrailingObjects<TupleTypeRepr, TupleTypeReprElement> {
friend TrailingObjects;
typedef Located<unsigned> SourceLocAndIdx;

SourceRange Parens;

size_t numTrailingObjects(OverloadToken<TupleTypeReprElement>) const {
return Bits.TupleTypeRepr.NumElements;
}

TupleTypeRepr(ArrayRef<TupleTypeReprElement> Elements,
SourceRange Parens, SourceLoc Ellipsis, unsigned EllipsisIdx);
TupleTypeRepr(ArrayRef<TupleTypeReprElement> Elements, SourceRange Parens);

public:
unsigned getNumElements() const { return Bits.TupleTypeRepr.NumElements; }
Expand Down Expand Up @@ -783,47 +816,15 @@ class TupleTypeRepr final : public TypeRepr,

SourceRange getParens() const { return Parens; }

bool hasEllipsis() const {
return Bits.TupleTypeRepr.HasEllipsis;
}

SourceLoc getEllipsisLoc() const {
return hasEllipsis() ?
getTrailingObjects<SourceLocAndIdx>()[0].Loc : SourceLoc();
}

unsigned getEllipsisIndex() const {
return hasEllipsis() ?
getTrailingObjects<SourceLocAndIdx>()[0].Item :
Bits.TupleTypeRepr.NumElements;
}

void removeEllipsis() {
if (hasEllipsis()) {
Bits.TupleTypeRepr.HasEllipsis = false;
getTrailingObjects<SourceLocAndIdx>()[0] = {
getNumElements(),
SourceLoc()
};
}
}

bool isParenType() const {
return Bits.TupleTypeRepr.NumElements == 1 &&
getElementNameLoc(0).isInvalid() &&
!hasEllipsis();
!isa<PackExpansionTypeRepr>(getElementType(0));
}

static TupleTypeRepr *create(const ASTContext &C,
ArrayRef<TupleTypeReprElement> Elements,
SourceRange Parens,
SourceLoc Ellipsis, unsigned EllipsisIdx);
static TupleTypeRepr *create(const ASTContext &C,
ArrayRef<TupleTypeReprElement> Elements,
SourceRange Parens) {
return create(C, Elements, Parens,
SourceLoc(), Elements.size());
}
SourceRange Parens);
static TupleTypeRepr *createEmpty(const ASTContext &C, SourceRange Parens);

static bool classof(const TypeRepr *T) {
Expand Down Expand Up @@ -1339,6 +1340,7 @@ inline bool TypeRepr::isSimple() const {
case TypeReprKind::Dictionary:
case TypeReprKind::Optional:
case TypeReprKind::ImplicitlyUnwrappedOptional:
case TypeReprKind::PackExpansion:
case TypeReprKind::Tuple:
case TypeReprKind::Fixed:
case TypeReprKind::Array:
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/TypeReprNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ TYPEREPR(ImplicitlyUnwrappedOptional, TypeRepr)
TYPEREPR(Tuple, TypeRepr)
TYPEREPR(Composition, TypeRepr)
TYPEREPR(Metatype, TypeRepr)
TYPEREPR(PackExpansion, TypeRepr)
TYPEREPR(Protocol, TypeRepr)
TYPEREPR(OpaqueReturn, TypeRepr)
TYPEREPR(NamedOpaqueReturn, TypeRepr)
Expand Down
7 changes: 4 additions & 3 deletions include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1316,6 +1316,10 @@ class Parser {
CustomAttribute,
};

ParserResult<TypeRepr> parseTypeScalar(
Diag<> MessageID,
ParseTypeReason reason);

ParserResult<TypeRepr> parseType();
ParserResult<TypeRepr> parseType(
Diag<> MessageID,
Expand Down Expand Up @@ -1433,9 +1437,6 @@ class Parser {
/// \p SecondName is the name.
SourceLoc SecondNameLoc;

/// The location of the '...', if present.
SourceLoc EllipsisLoc;

/// The first name.
Identifier FirstName;

Expand Down
11 changes: 9 additions & 2 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -960,8 +960,9 @@ namespace {
}
}

if (P->isVariadic())
OS << " variadic";
if (P->hasInterfaceType())
if (P->isVariadic())
OS << " variadic";

if (P->isAutoClosure())
OS << " autoclosure";
Expand Down Expand Up @@ -3088,6 +3089,12 @@ class PrintTypeRepr : public TypeReprVisitor<PrintTypeRepr> {
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}

void visitPackExpansionTypeRepr(PackExpansionTypeRepr *T) {
printCommon("pack_expansion") << '\n';
printRec(T->getPatternType());
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}

void visitTupleTypeRepr(TupleTypeRepr *T) {
printCommon("type_tuple");

Expand Down
10 changes: 0 additions & 10 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3832,13 +3832,6 @@ void PrintAST::printOneParameter(const ParamDecl *param,
TheTypeLoc = TypeLoc::withoutLoc(param->getInterfaceType());
}

// If the parameter is variadic, we will print the "..." after it, but we have
// to strip off the added array type.
if (param->isVariadic() && TheTypeLoc.getType()) {
if (auto *BGT = TheTypeLoc.getType()->getAs<BoundGenericType>())
TheTypeLoc.setType(BGT->getGenericArgs()[0]);
}

{
Printer.printStructurePre(PrintStructureKind::FunctionParameterType);
SWIFT_DEFER {
Expand All @@ -3853,9 +3846,6 @@ void PrintAST::printOneParameter(const ParamDecl *param,

printTypeLocForImplicitlyUnwrappedOptional(
TheTypeLoc, param->isImplicitlyUnwrappedOptional());

if (param->isVariadic())
Printer << "...";
}

if (param->isDefaultArgument() && Options.PrintDefaultArgumentValue) {
Expand Down
3 changes: 3 additions & 0 deletions lib/AST/ASTWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1879,6 +1879,9 @@ bool Traversal::visitOptionalTypeRepr(OptionalTypeRepr *T) {
bool Traversal::visitImplicitlyUnwrappedOptionalTypeRepr(ImplicitlyUnwrappedOptionalTypeRepr *T) {
return doIt(T->getBase());
}
bool Traversal::visitPackExpansionTypeRepr(PackExpansionTypeRepr *T) {
return doIt(T->getPatternType());
}

bool Traversal::visitTupleTypeRepr(TupleTypeRepr *T) {
for (auto &elem : T->getElements()) {
Expand Down
10 changes: 6 additions & 4 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1873,10 +1873,6 @@ static bool isDefaultInitializable(const TypeRepr *typeRepr, ASTContext &ctx) {
// Tuple types are default-initializable if all of their element
// types are.
if (const auto tuple = dyn_cast<TupleTypeRepr>(typeRepr)) {
// ... but not variadic ones.
if (tuple->hasEllipsis())
return false;

for (const auto &elt : tuple->getElements()) {
if (!isDefaultInitializable(elt.Type, ctx))
return false;
Expand Down Expand Up @@ -6530,6 +6526,12 @@ bool ParamDecl::isAnonClosureParam() const {
return nameStr[0] == '$';
}

bool ParamDecl::isVariadic() const {
(void) getInterfaceType();

return DefaultValueAndFlags.getInt().contains(Flags::IsVariadic);
}

ParamDecl::Specifier ParamDecl::getSpecifier() const {
auto &ctx = getASTContext();

Expand Down
11 changes: 7 additions & 4 deletions lib/AST/NameLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2532,6 +2532,13 @@ directReferencesForTypeRepr(Evaluator &evaluator,
return { };
}

case TypeReprKind::PackExpansion: {
auto packExpansionRepr = cast<PackExpansionTypeRepr>(typeRepr);
return directReferencesForTypeRepr(evaluator, ctx,
packExpansionRepr->getPatternType(), dc,
allowUsableFromInline);
}

case TypeReprKind::Error:
case TypeReprKind::Function:
case TypeReprKind::InOut:
Expand Down Expand Up @@ -2804,10 +2811,6 @@ createOpaqueParameterGenericParams(
SmallVector<GenericTypeParamDecl *, 2> implicitGenericParams;
auto dc = value->getInnermostDeclContext();
for (auto param : *params) {
// Don't permit variadic parameters.
if (param->isVariadic())
continue;

auto typeRepr = param->getTypeRepr();
if (!typeRepr)
continue;
Expand Down
3 changes: 1 addition & 2 deletions lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1315,8 +1315,7 @@ ParameterListInfo::ParameterListInfo(
inheritActorContext.set(i);
}

if (param->isVariadic() &&
param->getVarargBaseTy()->hasTypeSequence()) {
if (param->getInterfaceType()->is<PackExpansionType>()) {
variadicGenerics.set(i);
}
}
Expand Down
Loading