Skip to content

Commit e5bfda7

Browse files
authored
Merge pull request #40587 from CodaFi/substitute-teacher
Initial Semantics for Variadic Generics
2 parents 669e3f3 + d44d8ec commit e5bfda7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1421
-104
lines changed

include/swift/AST/ASTContext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,7 @@ class ASTContext final {
848848
const CanType TheErrorType; /// This is the ErrorType singleton.
849849
const CanType TheUnresolvedType; /// This is the UnresolvedType singleton.
850850
const CanType TheEmptyTupleType; /// This is '()', aka Void
851+
const CanType TheEmptyPackType;
851852
const CanType TheAnyType; /// This is 'Any', the empty protocol composition
852853
#define SINGLETON_TYPE(SHORT_ID, ID) \
853854
const CanType The##SHORT_ID##Type;

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3700,8 +3700,8 @@ NOTE(specialize_explicit_type_instead,none,
37003700
"did you mean to explicitly reference %0 instead?", (Type))
37013701
ERROR(type_parameter_count_mismatch,none,
37023702
"generic type %0 specialized with %select{too many|too few}3 type "
3703-
"parameters (got %2, but expected %1)",
3704-
(Identifier, unsigned, unsigned, bool))
3703+
"parameters (got %2, but expected %select{%1|at least %1}4)",
3704+
(Identifier, unsigned, unsigned, bool, bool))
37053705
ERROR(generic_type_requires_arguments,none,
37063706
"reference to generic type %0 requires arguments in <...>", (Type))
37073707
NOTE(descriptive_generic_type_declared_here,none,
@@ -4832,6 +4832,8 @@ ERROR(tuple_single_element,none,
48324832
"cannot create a single-element tuple with an element label", ())
48334833
ERROR(tuple_ellipsis,none,
48344834
"cannot create a variadic tuple", ())
4835+
ERROR(expansion_not_variadic,none,
4836+
"cannot create expansion with non-variadic type %0", (Type))
48354837
ERROR(tuple_duplicate_label,none,
48364838
"cannot create a tuple with a duplicate element label", ())
48374839
ERROR(enum_element_ellipsis,none,

include/swift/AST/Expr.h

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,10 @@ class alignas(8) Expr : public ASTAllocated<Expr> {
348348
IsPlaceholder : 1
349349
);
350350

351+
SWIFT_INLINE_BITFIELD_FULL(PackExpr, Expr, 32,
352+
: NumPadBits,
353+
NumElements : 32
354+
);
351355
} Bits;
352356

353357
private:
@@ -3319,6 +3323,18 @@ class BridgeToObjCExpr : public ImplicitConversionExpr {
33193323
}
33203324
};
33213325

3326+
/// ReifyPackExpr - Drop the pack structure and reify it either as a tuple or
3327+
/// single value.
3328+
class ReifyPackExpr : public ImplicitConversionExpr {
3329+
public:
3330+
ReifyPackExpr(Expr *subExpr, Type type)
3331+
: ImplicitConversionExpr(ExprKind::ReifyPack, subExpr, type) {}
3332+
3333+
static bool classof(const Expr *E) {
3334+
return E->getKind() == ExprKind::ReifyPack;
3335+
}
3336+
};
3337+
33223338
/// UnresolvedSpecializeExpr - Represents an explicit specialization using
33233339
/// a type parameter list (e.g. "Vector<Int>") that has not been resolved.
33243340
class UnresolvedSpecializeExpr final : public Expr,
@@ -3418,10 +3434,13 @@ class InOutExpr : public Expr {
34183434
class VarargExpansionExpr : public Expr {
34193435
Expr *SubExpr;
34203436

3421-
public:
34223437
VarargExpansionExpr(Expr *subExpr, bool implicit, Type type = Type())
34233438
: Expr(ExprKind::VarargExpansion, implicit, type), SubExpr(subExpr) {}
34243439

3440+
public:
3441+
static VarargExpansionExpr *createParamExpansion(ASTContext &ctx, Expr *E);
3442+
static VarargExpansionExpr *createArrayExpansion(ASTContext &ctx, ArrayExpr *AE);
3443+
34253444
SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr)
34263445

34273446
Expr *getSubExpr() const { return SubExpr; }
@@ -5763,6 +5782,56 @@ class OneWayExpr : public Expr {
57635782
}
57645783
};
57655784

5785+
/// An expression node that aggregates a set of heterogeneous arguments into a
5786+
/// parameter pack suitable for passing off to a variadic generic function
5787+
/// argument.
5788+
///
5789+
/// There is no user-visible way to spell a pack expression, they are always
5790+
/// implicitly created at applies. As such, any appearance of pack types outside
5791+
/// of applies are illegal. In general, packs appearing in such positions should
5792+
/// have a \c ReifyPackExpr to convert them to a user-available AST type.
5793+
class PackExpr final : public Expr,
5794+
private llvm::TrailingObjects<PackExpr, Expr *> {
5795+
friend TrailingObjects;
5796+
5797+
size_t numTrailingObjects() const {
5798+
return getNumElements();
5799+
}
5800+
5801+
PackExpr(ArrayRef<Expr *> SubExprs, Type Ty);
5802+
5803+
public:
5804+
/// Create a pack.
5805+
static PackExpr *create(ASTContext &ctx, ArrayRef<Expr *> SubExprs, Type Ty);
5806+
5807+
/// Create an empty pack.
5808+
static PackExpr *createEmpty(ASTContext &ctx);
5809+
5810+
SourceLoc getLoc() const { return SourceLoc(); }
5811+
SourceRange getSourceRange() const { return SourceRange(); }
5812+
5813+
/// Retrieve the elements of this pack.
5814+
MutableArrayRef<Expr *> getElements() {
5815+
return { getTrailingObjects<Expr *>(), getNumElements() };
5816+
}
5817+
5818+
/// Retrieve the elements of this pack.
5819+
ArrayRef<Expr *> getElements() const {
5820+
return { getTrailingObjects<Expr *>(), getNumElements() };
5821+
}
5822+
5823+
unsigned getNumElements() const { return Bits.PackExpr.NumElements; }
5824+
5825+
Expr *getElement(unsigned i) const {
5826+
return getElements()[i];
5827+
}
5828+
void setElement(unsigned i, Expr *e) {
5829+
getElements()[i] = e;
5830+
}
5831+
5832+
static bool classof(const Expr *E) { return E->getKind() == ExprKind::Pack; }
5833+
};
5834+
57665835
inline bool Expr::isInfixOperator() const {
57675836
return isa<BinaryExpr>(this) || isa<IfExpr>(this) ||
57685837
isa<AssignExpr>(this) || isa<ExplicitCastExpr>(this);

include/swift/AST/ExprNodes.def

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,8 @@ ABSTRACT_EXPR(ImplicitConversion, Expr)
181181
EXPR(DifferentiableFunctionExtractOriginal, ImplicitConversionExpr)
182182
EXPR(LinearFunctionExtractOriginal, ImplicitConversionExpr)
183183
EXPR(LinearToDifferentiableFunction, ImplicitConversionExpr)
184-
EXPR_RANGE(ImplicitConversion, Load, LinearToDifferentiableFunction)
184+
EXPR(ReifyPack, ImplicitConversionExpr)
185+
EXPR_RANGE(ImplicitConversion, Load, ReifyPack)
185186
ABSTRACT_EXPR(ExplicitCast, Expr)
186187
ABSTRACT_EXPR(CheckedCast, ExplicitCastExpr)
187188
EXPR(ForcedCheckedCast, CheckedCastExpr)
@@ -203,7 +204,8 @@ EXPR(KeyPath, Expr)
203204
UNCHECKED_EXPR(KeyPathDot, Expr)
204205
UNCHECKED_EXPR(OneWay, Expr)
205206
EXPR(Tap, Expr)
206-
LAST_EXPR(Tap)
207+
EXPR(Pack, Expr)
208+
LAST_EXPR(Pack)
207209

208210
#undef EXPR_RANGE
209211
#undef LITERAL_EXPR

include/swift/AST/TypeDifferenceVisitor.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,17 @@ class CanTypeDifferenceVisitor : public CanTypePairVisitor<Impl, bool> {
130130
return asImpl().visit(type1.getElementType(), type2.getElementType());
131131
}
132132

133+
bool visitPackType(CanPackType type1, CanPackType type2) {
134+
return visitComponentArray(type1, type2,
135+
type1->getElementTypes(),
136+
type2->getElementTypes());
137+
}
138+
139+
bool visitPackExpansionType(CanPackExpansionType type1,
140+
CanPackExpansionType type2) {
141+
return asImpl().visit(type1.getPatternType(), type2.getPatternType());
142+
}
143+
133144
bool visitTupleType(CanTupleType type1, CanTupleType type2) {
134145
return visitComponentArray(type1, type2,
135146
type1->getElements(), type2->getElements());

include/swift/AST/TypeMatcher.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,42 @@ class TypeMatcher {
143143
return mismatch(firstTuple.getPointer(), secondType, sugaredFirstType);
144144
}
145145

146+
bool visitPackType(CanPackType firstTuple, Type secondType,
147+
Type sugaredFirstType) {
148+
if (auto secondTuple = secondType->getAs<PackType>()) {
149+
auto sugaredFirstTuple = sugaredFirstType->getAs<PackType>();
150+
if (firstTuple->getNumElements() != secondTuple->getNumElements())
151+
return mismatch(firstTuple.getPointer(), secondTuple,
152+
sugaredFirstType);
153+
154+
for (unsigned i = 0, n = firstTuple->getNumElements(); i != n; ++i) {
155+
Type secondElt = secondTuple->getElementType(i);
156+
157+
// Recurse on the pack elements.
158+
if (!this->visit(firstTuple.getElementType(i), secondElt,
159+
sugaredFirstTuple->getElementType(i)))
160+
return false;
161+
}
162+
163+
return true;
164+
}
165+
166+
// Pack/non-pack mismatch.
167+
return mismatch(firstTuple.getPointer(), secondType, sugaredFirstType);
168+
}
169+
170+
bool visitPackExpansionType(CanPackExpansionType firstPE, Type secondType,
171+
Type sugaredFirstType) {
172+
if (auto secondInOut = secondType->getAs<PackExpansionType>()) {
173+
return this->visit(firstPE.getPatternType(),
174+
secondInOut->getPatternType(),
175+
sugaredFirstType->castTo<PackExpansionType>()
176+
->getPatternType());
177+
}
178+
179+
return mismatch(firstPE.getPointer(), secondType, sugaredFirstType);
180+
}
181+
146182
bool visitReferenceStorageType(CanReferenceStorageType firstStorage,
147183
Type secondType, Type sugaredFirstType) {
148184
auto _secondStorage = secondType->getCanonicalType();

include/swift/AST/TypeNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ TYPE(ProtocolComposition, Type)
165165
TYPE(Existential, Type)
166166
TYPE(LValue, Type)
167167
TYPE(InOut, Type)
168+
TYPE(Pack, Type)
169+
TYPE(PackExpansion, Type)
168170
UNCHECKED_TYPE(TypeVariable, Type)
169171
ABSTRACT_SUGARED_TYPE(Sugar, Type)
170172
SUGARED_TYPE(Paren, SugarType)

0 commit comments

Comments
 (0)