Skip to content

[Variadic Generics] Change pack expansion types and expressions to use the repeat syntax. #62766

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 12 commits into from
Jan 7, 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 @@ -239,7 +239,7 @@ void *ImplicitlyUnwrappedOptionalTypeRepr_create(void *ctx, void *base,
void *exclamationLoc);
void *MetatypeTypeRepr_create(void *ctx, void *baseType, void *typeLoc);
void *ProtocolTypeRepr_create(void *ctx, void *baseType, void *protoLoc);
void *PackExpansionTypeRepr_create(void *ctx, void *base, void *ellipsisLoc);
void *PackExpansionTypeRepr_create(void *ctx, void *base, void *repeatLoc);
void *TupleTypeRepr_create(void *ctx, BridgedArrayRef elements, void *lParenLoc,
void *rParenLoc);
void *DeclRefTypeRepr_create(void *ctx, BridgedArrayRef bridgedComponents);
Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -5163,6 +5163,9 @@ 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(vararg_not_allowed,none,
"variadic parameter cannot appear outside of a function parameter list",
())
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))
Expand Down
51 changes: 13 additions & 38 deletions include/swift/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -350,11 +350,6 @@ class alignas(8) Expr : public ASTAllocated<Expr> {
IsObjC : 1
);

SWIFT_INLINE_BITFIELD_FULL(PackExpansionExpr, Expr, 32,
: NumPadBits,
NumBindings : 32
);

SWIFT_INLINE_BITFIELD_FULL(SequenceExpr, Expr, 32,
: NumPadBits,
NumElements : 32
Expand Down Expand Up @@ -3599,39 +3594,23 @@ class PackElementExpr final : public Expr {
/// that naturally accept a comma-separated list of values, including
/// call argument lists, the elements of a tuple value, and the source
/// of a for-in loop.
class PackExpansionExpr final : public Expr,
private llvm::TrailingObjects<PackExpansionExpr, PackElementExpr *> {
friend TrailingObjects;

class PackExpansionExpr final : public Expr {
SourceLoc RepeatLoc;
Expr *PatternExpr;
SourceLoc DotsLoc;
GenericEnvironment *Environment;

PackExpansionExpr(Expr *patternExpr,
ArrayRef<PackElementExpr *> packElements,
SourceLoc dotsLoc,
PackExpansionExpr(SourceLoc repeatLoc,
Expr *patternExpr,
GenericEnvironment *environment,
bool implicit, Type type)
: Expr(ExprKind::PackExpansion, implicit, type),
PatternExpr(patternExpr), DotsLoc(dotsLoc), Environment(environment) {
Bits.PackExpansionExpr.NumBindings = packElements.size();
std::uninitialized_copy(packElements.begin(), packElements.end(),
getTrailingObjects<PackElementExpr *>());
}

size_t numTrailingObjects(OverloadToken<PackElementExpr *>) const {
return getNumBindings();
}

MutableArrayRef<PackElementExpr *> getMutableBindings() {
return {getTrailingObjects<PackElementExpr *>(), getNumBindings()};
}
RepeatLoc(repeatLoc), PatternExpr(patternExpr),
Environment(environment) {}

public:
static PackExpansionExpr *create(ASTContext &ctx,
SourceLoc repeatLoc,
Expr *patternExpr,
ArrayRef<PackElementExpr *> packElements,
SourceLoc dotsLoc,
GenericEnvironment *environment,
bool implicit = false,
Type type = Type());
Expand All @@ -3642,26 +3621,22 @@ class PackExpansionExpr final : public Expr,
PatternExpr = patternExpr;
}

unsigned getNumBindings() const {
return Bits.PackExpansionExpr.NumBindings;
}

ArrayRef<PackElementExpr *> getPackElements() {
return {getTrailingObjects<PackElementExpr *>(), getNumBindings()};
}

void getExpandedPacks(SmallVectorImpl<ASTNode> &packs);

GenericEnvironment *getGenericEnvironment() {
return Environment;
}

void setGenericEnvironment(GenericEnvironment *env) {
Environment = env;
}

SourceLoc getStartLoc() const {
return PatternExpr->getStartLoc();
return RepeatLoc;
}

SourceLoc getEndLoc() const {
return DotsLoc;
return PatternExpr->getEndLoc();
}

static bool classof(const Expr *E) {
Expand Down
43 changes: 35 additions & 8 deletions include/swift/AST/TypeRepr.h
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,32 @@ struct TupleTypeReprElement {
TupleTypeReprElement(TypeRepr *Type): Type(Type) {}
};

/// A vararg type 'T...' with element type 'T'.
class VarargTypeRepr final : public TypeRepr {
TypeRepr *Element;
SourceLoc EllipsisLoc;

public:
VarargTypeRepr(TypeRepr *Element, SourceLoc EllipsisLoc)
: TypeRepr(TypeReprKind::Vararg), Element(Element),
EllipsisLoc(EllipsisLoc) {}

TypeRepr *getElementType() const { return Element; }
SourceLoc getEllipsisLoc() const { return EllipsisLoc; }

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

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

/// A pack expansion 'T...' with a pattern 'T'.
///
/// Can appear in the following positions:
Expand All @@ -708,26 +734,26 @@ struct TupleTypeReprElement {
/// 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 {
SourceLoc RepeatLoc;
TypeRepr *Pattern;
SourceLoc EllipsisLoc;

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

SourceLoc getRepeatLoc() const { return RepeatLoc; }
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; }
SourceLoc getStartLocImpl() const { return RepeatLoc; }
SourceLoc getEndLocImpl() const { return Pattern->getEndLoc(); }
SourceLoc getLocImpl() const { return RepeatLoc; }
void printImpl(ASTPrinter &Printer, const PrintOptions &Opts) const;
friend class TypeRepr;
};
Expand Down Expand Up @@ -1370,6 +1396,7 @@ inline bool TypeRepr::isSimple() const {
case TypeReprKind::Dictionary:
case TypeReprKind::Optional:
case TypeReprKind::ImplicitlyUnwrappedOptional:
case TypeReprKind::Vararg:
case TypeReprKind::PackExpansion:
case TypeReprKind::Tuple:
case TypeReprKind::Fixed:
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(Vararg, TypeRepr)
TYPEREPR(PackExpansion, TypeRepr)
TYPEREPR(Protocol, TypeRepr)
TYPEREPR(OpaqueReturn, TypeRepr)
Expand Down
15 changes: 0 additions & 15 deletions include/swift/Sema/ConstraintLocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -690,21 +690,6 @@ class LocatorPathElt::PackElement final : public StoredIntegerElement<1> {
}
};

class LocatorPathElt::OpenedPackElement final
: public StoredPointerElement<GenericEnvironment> {
public:
OpenedPackElement(GenericEnvironment *env)
: StoredPointerElement(PathElementKind::OpenedPackElement, env) {}

GenericEnvironment *getGenericEnvironment() const {
return getStoredPointer();
}

static bool classof(const LocatorPathElt *elt) {
return elt->getKind() == PathElementKind::OpenedPackElement;
}
};

class LocatorPathElt::KeyPathComponent final : public StoredIntegerElement<1> {
public:
KeyPathComponent(unsigned index)
Expand Down
3 changes: 0 additions & 3 deletions include/swift/Sema/ConstraintLocatorPathElts.def
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,6 @@ CUSTOM_LOCATOR_PATH_ELT(PackType)
/// An element of a pack type - the T in <T, U, V, ...>
CUSTOM_LOCATOR_PATH_ELT(PackElement)

/// Stores the generic environment for an opened pack element.
CUSTOM_LOCATOR_PATH_ELT(OpenedPackElement)

/// The shape of a parameter pack.
SIMPLE_LOCATOR_PATH_ELT(PackShape)

Expand Down
27 changes: 21 additions & 6 deletions include/swift/Sema/ConstraintSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -1494,6 +1494,10 @@ class Solution {
llvm::DenseMap<ConstraintLocator *, OpenedArchetypeType *>
OpenedExistentialTypes;

/// The pack expansion environment that can open pack elements for
/// a given locator.
llvm::DenseMap<ConstraintLocator *, UUID> PackExpansionEnvironments;

/// The locators of \c Defaultable constraints whose defaults were used.
llvm::SmallPtrSet<ConstraintLocator *, 2> DefaultedConstraints;

Expand Down Expand Up @@ -3021,6 +3025,8 @@ class ConstraintSystem {
llvm::SmallMapVector<ConstraintLocator *, OpenedArchetypeType *, 4>
OpenedExistentialTypes;

llvm::SmallMapVector<ConstraintLocator *, UUID, 4> PackExpansionEnvironments;

/// The set of functions that have been transformed by a result builder.
llvm::MapVector<AnyFunctionRef, AppliedBuilderTransform>
resultBuilderTransformed;
Expand Down Expand Up @@ -3496,6 +3502,9 @@ class ConstraintSystem {
/// The length of \c OpenedExistentialTypes.
unsigned numOpenedExistentialTypes;

/// The length of \c PackExpansionEnvironments.
unsigned numPackExpansionEnvironments;

/// The length of \c DefaultedConstraints.
unsigned numDefaultedConstraints;

Expand Down Expand Up @@ -3974,6 +3983,12 @@ class ConstraintSystem {
std::pair<Type, OpenedArchetypeType *> openExistentialType(
Type type, ConstraintLocator *locator);

/// Add the given pack expansion as an opened pack element environment.
void addPackElementEnvironment(PackExpansionExpr *expr);

/// Get the opened element generic environment for the given locator.
GenericEnvironment *getPackElementEnvironment(ConstraintLocator *locator);

/// Retrieve the constraint locator for the given anchor and
/// path, uniqued and automatically infer the summary flags
ConstraintLocator *
Expand Down Expand Up @@ -6124,12 +6139,12 @@ class HandlePlaceholderType {
class OpenPackElementType {
ConstraintSystem &cs;
ConstraintLocator *locator;
GenericEnvironment *elementEnv;
PackExpansionExpr *elementEnv;

public:
explicit OpenPackElementType(ConstraintSystem &cs,
const ConstraintLocatorBuilder &locator,
GenericEnvironment *elementEnv)
PackExpansionExpr *elementEnv)
: cs(cs), elementEnv(elementEnv) {
this->locator = cs.getConstraintLocator(locator);
}
Expand All @@ -6141,9 +6156,9 @@ class OpenPackElementType {
// element.
assert(elementEnv);

auto *elementType = cs.createTypeVariable(locator, TVO_CanBindToHole);
auto elementLoc = cs.getConstraintLocator(locator,
LocatorPathElt::OpenedPackElement(elementEnv));
auto *elementType = cs.createTypeVariable(locator,
TVO_CanBindToHole |
TVO_CanBindToNoEscape);

// If we're opening a pack element from an explicit type repr,
// set the type repr types in the constraint system for generating
Expand All @@ -6154,7 +6169,7 @@ class OpenPackElementType {
}

cs.addConstraint(ConstraintKind::PackElementOf, elementType,
packType, elementLoc);
packType, cs.getConstraintLocator(elementEnv));
return elementType;
}
};
Expand Down
6 changes: 6 additions & 0 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3168,6 +3168,12 @@ class PrintTypeRepr : public TypeReprVisitor<PrintTypeRepr> {
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}

void visitVarargTypeRepr(VarargTypeRepr *T) {
printCommon("vararg") << '\n';
printRec(T->getElementType());
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}

void visitPackExpansionTypeRepr(PackExpansionTypeRepr *T) {
printCommon("pack_expansion") << '\n';
printRec(T->getPatternType());
Expand Down
5 changes: 1 addition & 4 deletions lib/AST/ASTVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -839,13 +839,10 @@ class Verifier : public ASTWalker {
return true;
}

void verifyCheckedAlways(PackExpansionExpr *E) {
// Remove the element generic environment before verifying
// the pack expansion type, which contains pack archetypes.
void cleanup(PackExpansionExpr *E) {
assert(Generics.back().get<GenericEnvironment *>() ==
E->getGenericEnvironment());
Generics.pop_back();
verifyCheckedAlwaysBase(E);
}

bool shouldVerify(MakeTemporarilyEscapableExpr *expr) {
Expand Down
5 changes: 5 additions & 0 deletions lib/AST/ASTWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2002,6 +2002,11 @@ bool Traversal::visitOptionalTypeRepr(OptionalTypeRepr *T) {
bool Traversal::visitImplicitlyUnwrappedOptionalTypeRepr(ImplicitlyUnwrappedOptionalTypeRepr *T) {
return doIt(T->getBase());
}

bool Traversal::visitVarargTypeRepr(VarargTypeRepr *T) {
return doIt(T->getElementType());
}

bool Traversal::visitPackExpansionTypeRepr(PackExpansionTypeRepr *T) {
return doIt(T->getPatternType());
}
Expand Down
4 changes: 2 additions & 2 deletions lib/AST/CASTBridging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -466,10 +466,10 @@ void *ProtocolTypeRepr_create(void *ctx, void *baseType, void *protoLoc) {
return new (Context) ProtocolTypeRepr((TypeRepr *)baseType, protocolLoc);
}

void *PackExpansionTypeRepr_create(void *ctx, void *base, void *ellipsisLoc) {
void *PackExpansionTypeRepr_create(void *ctx, void *base, void *repeatLoc) {
ASTContext &Context = *static_cast<ASTContext *>(ctx);
return new (Context) PackExpansionTypeRepr(
(TypeRepr *)base, getSourceLocFromPointer(ellipsisLoc));
getSourceLocFromPointer(repeatLoc), (TypeRepr *)base);
}

void *TupleTypeRepr_create(void *ctx, BridgedArrayRef elements, void *lParenLoc,
Expand Down
13 changes: 4 additions & 9 deletions lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1250,16 +1250,11 @@ VarargExpansionExpr *VarargExpansionExpr::createArrayExpansion(ASTContext &ctx,
}

PackExpansionExpr *
PackExpansionExpr::create(ASTContext &ctx, Expr *patternExpr,
ArrayRef<PackElementExpr *> packElements,
SourceLoc dotsLoc, GenericEnvironment *environment,
PackExpansionExpr::create(ASTContext &ctx, SourceLoc repeatLoc,
Expr *patternExpr, GenericEnvironment *environment,
bool implicit, Type type) {
size_t size =
totalSizeToAlloc<PackElementExpr *>(packElements.size());
void *mem = ctx.Allocate(size, alignof(PackExpansionExpr));
return ::new (mem) PackExpansionExpr(patternExpr, packElements,
dotsLoc, environment,
implicit, type);
return new (ctx) PackExpansionExpr(repeatLoc, patternExpr, environment,
implicit, type);
}

void PackExpansionExpr::getExpandedPacks(SmallVectorImpl<ASTNode> &packs) {
Expand Down
Loading