Skip to content

Commit e7e5367

Browse files
committed
AST: Introduce ParametrizedProtocolType
1 parent 327a508 commit e7e5367

23 files changed

+269
-4
lines changed

include/swift/AST/TypeDifferenceVisitor.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,15 @@ class CanTypeDifferenceVisitor : public CanTypePairVisitor<Impl, bool> {
339339
type1->getMembers(), type2->getMembers());
340340
}
341341

342+
bool visitParametrizedProtocolType(CanParametrizedProtocolType type1,
343+
CanParametrizedProtocolType type2) {
344+
if (asImpl().visit(type1.getBaseType(), type2.getBaseType()))
345+
return true;
346+
347+
return asImpl().visit(type1.getArgumentType(),
348+
type2.getArgumentType());
349+
}
350+
342351
bool visitExistentialType(CanExistentialType type1,
343352
CanExistentialType type2) {
344353
return asImpl().visit(type1.getConstraintType(),

include/swift/AST/TypeMatcher.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,27 @@ class TypeMatcher {
305305
TRIVIAL_CASE(SILBoxType)
306306
TRIVIAL_CASE(ProtocolCompositionType)
307307

308+
bool visitParametrizedProtocolType(CanParametrizedProtocolType firstParametrizedProto,
309+
Type secondType,
310+
Type sugaredFirstType) {
311+
if (auto secondParametrizedProto = secondType->getAs<ParametrizedProtocolType>()) {
312+
if (!this->visit(firstParametrizedProto.getBaseType(),
313+
secondParametrizedProto->getBaseType(),
314+
sugaredFirstType->castTo<ParametrizedProtocolType>()
315+
->getBaseType())) {
316+
return false;
317+
}
318+
319+
return this->visit(firstParametrizedProto.getArgumentType(),
320+
secondParametrizedProto->getArgumentType(),
321+
sugaredFirstType->castTo<ParametrizedProtocolType>()
322+
->getArgumentType());
323+
}
324+
325+
return mismatch(firstParametrizedProto.getPointer(), secondType,
326+
sugaredFirstType);
327+
}
328+
308329
bool visitExistentialType(CanExistentialType firstExistential,
309330
Type secondType,
310331
Type sugaredFirstType) {

include/swift/AST/TypeNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ ARTIFICIAL_TYPE(SILBlockStorage, Type)
161161
ARTIFICIAL_TYPE(SILBox, Type)
162162
ARTIFICIAL_TYPE(SILToken, Type)
163163
TYPE(ProtocolComposition, Type)
164+
TYPE(ParametrizedProtocol, Type)
164165
TYPE(Existential, Type)
165166
TYPE(LValue, Type)
166167
TYPE(InOut, Type)

include/swift/AST/Types.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5243,6 +5243,65 @@ class ProtocolCompositionType final : public TypeBase,
52435243
BEGIN_CAN_TYPE_WRAPPER(ProtocolCompositionType, Type)
52445244
END_CAN_TYPE_WRAPPER(ProtocolCompositionType, Type)
52455245

5246+
/// ParametrizedProtocolType - A type that constrains the primary associated
5247+
/// type of a protocol to an argument type.
5248+
///
5249+
/// Written like a bound generic type, eg Sequence<Int>.
5250+
///
5251+
/// For now, these are only supported in generic requirement-like contexts:
5252+
/// - Inheritance clauses of protocols, generic parameters, associated types
5253+
/// - Conformance requirements in where clauses
5254+
/// - Extensions
5255+
///
5256+
/// Assuming that the primary associated type of Sequence is Element, the
5257+
/// desugaring is that T : Sequence<Int> is equivalent to
5258+
///
5259+
/// \code
5260+
/// T : Sequence where T.Element == Int.
5261+
/// \endcode
5262+
class ParametrizedProtocolType final : public TypeBase,
5263+
public llvm::FoldingSetNode {
5264+
ProtocolType *Base;
5265+
Type Arg;
5266+
5267+
public:
5268+
/// Retrieve an instance of a protocol composition type with the
5269+
/// given set of members.
5270+
static Type get(const ASTContext &C, ProtocolType *base,
5271+
Type arg);
5272+
5273+
ProtocolType *getBaseType() const {
5274+
return Base;
5275+
}
5276+
5277+
Type getArgumentType() const {
5278+
return Arg;
5279+
}
5280+
5281+
void Profile(llvm::FoldingSetNodeID &ID) {
5282+
Profile(ID, Base, Arg);
5283+
}
5284+
static void Profile(llvm::FoldingSetNodeID &ID,
5285+
ProtocolType *base,
5286+
Type arg);
5287+
5288+
// Implement isa/cast/dyncast/etc.
5289+
static bool classof(const TypeBase *T) {
5290+
return T->getKind() == TypeKind::ParametrizedProtocol;
5291+
}
5292+
5293+
private:
5294+
ParametrizedProtocolType(const ASTContext *ctx,
5295+
ProtocolType *base, Type arg,
5296+
RecursiveTypeProperties properties)
5297+
: TypeBase(TypeKind::ParametrizedProtocol, /*Context=*/ctx, properties),
5298+
Base(base), Arg(arg) { }
5299+
};
5300+
BEGIN_CAN_TYPE_WRAPPER(ParametrizedProtocolType, Type)
5301+
PROXY_CAN_TYPE_SIMPLE_GETTER(getBaseType)
5302+
PROXY_CAN_TYPE_SIMPLE_GETTER(getArgumentType)
5303+
END_CAN_TYPE_WRAPPER(ParametrizedProtocolType, Type)
5304+
52465305
/// An existential type, spelled with \c any .
52475306
///
52485307
/// In Swift 5 mode, a plain protocol name in type

lib/AST/ASTContext.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ struct ASTContext::Implementation {
405405
llvm::FoldingSet<UnboundGenericType> UnboundGenericTypes;
406406
llvm::FoldingSet<BoundGenericType> BoundGenericTypes;
407407
llvm::FoldingSet<ProtocolCompositionType> ProtocolCompositionTypes;
408+
llvm::FoldingSet<ParametrizedProtocolType> ParametrizedProtocolTypes;
408409
llvm::FoldingSet<LayoutConstraintInfo> LayoutConstraints;
409410
llvm::DenseMap<std::pair<OpaqueTypeDecl *, SubstitutionMap>,
410411
GenericEnvironment *> OpaqueArchetypeEnvironments;
@@ -3240,10 +3241,37 @@ ProtocolCompositionType::build(const ASTContext &C, ArrayRef<Type> Members,
32403241
Members,
32413242
HasExplicitAnyObject,
32423243
properties);
3243-
C.getImpl().getArena(arena).ProtocolCompositionTypes.InsertNode(compTy, InsertPos);
3244+
C.getImpl().getArena(arena).ProtocolCompositionTypes.InsertNode(
3245+
compTy, InsertPos);
32443246
return compTy;
32453247
}
32463248

3249+
Type ParametrizedProtocolType::get(const ASTContext &C,
3250+
ProtocolType *baseTy,
3251+
Type argTy) {
3252+
bool isCanonical = baseTy->isCanonical();
3253+
RecursiveTypeProperties properties = baseTy->getRecursiveProperties();
3254+
properties |= argTy->getRecursiveProperties();
3255+
isCanonical &= argTy->isCanonical();
3256+
3257+
auto arena = getArena(properties);
3258+
3259+
void *InsertPos = nullptr;
3260+
llvm::FoldingSetNodeID ID;
3261+
ParametrizedProtocolType::Profile(ID, baseTy, argTy);
3262+
3263+
if (auto paramTy
3264+
= C.getImpl().getArena(arena).ParametrizedProtocolTypes
3265+
.FindNodeOrInsertPos(ID, InsertPos))
3266+
return paramTy;
3267+
3268+
auto paramTy = new (C, arena) ParametrizedProtocolType(
3269+
isCanonical ? &C : nullptr, baseTy, argTy, properties);
3270+
C.getImpl().getArena(arena).ParametrizedProtocolTypes.InsertNode(
3271+
paramTy, InsertPos);
3272+
return paramTy;
3273+
}
3274+
32473275
ReferenceStorageType *ReferenceStorageType::get(Type T,
32483276
ReferenceOwnership ownership,
32493277
const ASTContext &C) {

lib/AST/ASTDumper.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3942,6 +3942,14 @@ namespace {
39423942
PrintWithColorRAII(OS, ParenthesisColor) << ')';
39433943
}
39443944

3945+
void visitParametrizedProtocolType(ParametrizedProtocolType *T,
3946+
StringRef label) {
3947+
printCommon(label, "parametrized_protocol_type");
3948+
printRec("base", T->getBaseType());
3949+
printRec("arg", T->getArgumentType());
3950+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
3951+
}
3952+
39453953
void visitExistentialType(ExistentialType *T,
39463954
StringRef label) {
39473955
printCommon(label, "existential_type");

lib/AST/ASTMangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,6 +1266,11 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
12661266
return appendExistentialLayout(layout, sig, forDecl);
12671267
}
12681268

1269+
case TypeKind::ParametrizedProtocol: {
1270+
llvm::errs() << "Not implemented\n";
1271+
abort();
1272+
}
1273+
12691274
case TypeKind::Existential: {
12701275
auto constraint = cast<ExistentialType>(tybase)->getConstraintType();
12711276
return appendType(constraint, sig, forDecl);

lib/AST/ASTPrinter.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5877,6 +5877,13 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
58775877
}
58785878
}
58795879

5880+
void visitParametrizedProtocolType(ParametrizedProtocolType *T) {
5881+
visit(T->getBaseType());
5882+
Printer << "<";
5883+
visit(T->getArgumentType());
5884+
Printer << ">";
5885+
}
5886+
58805887
void visitExistentialType(ExistentialType *T) {
58815888
if (Options.PrintExplicitAny)
58825889
Printer << "any ";

lib/AST/Type.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ bool CanType::isReferenceTypeImpl(CanType type, const GenericSignatureImpl *sig,
191191
return cast<ProtocolType>(type)->requiresClass();
192192
case TypeKind::ProtocolComposition:
193193
return cast<ProtocolCompositionType>(type)->requiresClass();
194+
case TypeKind::ParametrizedProtocol:
195+
return cast<ParametrizedProtocolType>(type)->getBaseType()->requiresClass();
194196
case TypeKind::Existential:
195197
return isReferenceTypeImpl(cast<ExistentialType>(type).getConstraintType(),
196198
sig, functionsCount);
@@ -1497,6 +1499,14 @@ CanType TypeBase::computeCanonicalType() {
14971499
Result = Composition.getPointer();
14981500
break;
14991501
}
1502+
case TypeKind::ParametrizedProtocol: {
1503+
auto *PPT = cast<ParametrizedProtocolType>(this);
1504+
auto Base = cast<ProtocolType>(PPT->getBaseType()->getCanonicalType());
1505+
auto Arg = PPT->getArgumentType()->getCanonicalType();
1506+
auto &C = Base->getASTContext();
1507+
Result = ParametrizedProtocolType::get(C, Base, Arg).getPointer();
1508+
break;
1509+
}
15001510
case TypeKind::Existential: {
15011511
auto *existential = cast<ExistentialType>(this);
15021512
auto constraint = existential->getConstraintType()->getCanonicalType();
@@ -3798,6 +3808,13 @@ void ProtocolCompositionType::Profile(llvm::FoldingSetNodeID &ID,
37983808
ID.AddPointer(T.getPointer());
37993809
}
38003810

3811+
void ParametrizedProtocolType::Profile(llvm::FoldingSetNodeID &ID,
3812+
ProtocolType *baseTy,
3813+
Type argTy) {
3814+
ID.AddPointer(baseTy);
3815+
ID.AddPointer(argTy.getPointer());
3816+
}
3817+
38013818
bool ProtocolType::requiresClass() {
38023819
return getDecl()->requiresClass();
38033820
}
@@ -5528,6 +5545,36 @@ case TypeKind::Id:
55285545
substMembers,
55295546
pc->hasExplicitAnyObject());
55305547
}
5548+
5549+
case TypeKind::ParametrizedProtocol: {
5550+
auto *ppt = cast<ParametrizedProtocolType>(base);
5551+
Type base = ppt->getBaseType();
5552+
Type arg = ppt->getArgumentType();
5553+
5554+
bool anyChanged = false;
5555+
5556+
auto substBase = base.transformRec(fn);
5557+
if (!substBase)
5558+
return Type();
5559+
5560+
if (substBase.getPointer() != base.getPointer())
5561+
anyChanged = true;
5562+
5563+
auto substArg = arg.transformRec(fn);
5564+
if (!substArg)
5565+
return Type();
5566+
5567+
if (substArg.getPointer() != arg.getPointer())
5568+
anyChanged = true;
5569+
5570+
if (!anyChanged)
5571+
return *this;
5572+
5573+
return ParametrizedProtocolType::get(
5574+
Ptr->getASTContext(),
5575+
substBase->castTo<ProtocolType>(),
5576+
substArg);
5577+
}
55315578
}
55325579

55335580
llvm_unreachable("Unhandled type in transformation");
@@ -5687,6 +5734,12 @@ ReferenceCounting TypeBase::getReferenceCounting() {
56875734
return ReferenceCounting::Unknown;
56885735
}
56895736

5737+
case TypeKind::ParametrizedProtocol: {
5738+
return cast<ParametrizedProtocolType>(this)
5739+
->getBaseType()
5740+
->getReferenceCounting();
5741+
}
5742+
56905743
case TypeKind::Existential:
56915744
return cast<ExistentialType>(type)->getConstraintType()
56925745
->getReferenceCounting();

lib/AST/TypeWalker.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,13 @@ class Traversal : public TypeVisitor<Traversal, bool>
174174
return false;
175175
}
176176

177+
bool visitParametrizedProtocolType(ParametrizedProtocolType *ty) {
178+
if (doIt(ty->getBaseType()))
179+
return true;
180+
181+
return doIt(ty->getArgumentType());
182+
}
183+
177184
bool visitExistentialType(ExistentialType *ty) {
178185
return doIt(ty->getConstraintType());
179186
}

0 commit comments

Comments
 (0)