Skip to content

Commit 60ffd84

Browse files
authored
Merge pull request #64561 from slavapestov/constrained-existential-fixes
Fixes for constrained existential types
2 parents 21109a3 + 5452a89 commit 60ffd84

File tree

6 files changed

+65
-22
lines changed

6 files changed

+65
-22
lines changed

lib/AST/ASTContext.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3761,6 +3761,9 @@ ParameterizedProtocolType *ParameterizedProtocolType::get(const ASTContext &C,
37613761

37623762
auto size = totalSizeToAlloc<Type>(args.size());
37633763
auto mem = C.Allocate(size, alignof(ParameterizedProtocolType), arena);
3764+
3765+
properties |= RecursiveTypeProperties::HasParameterizedExistential;
3766+
37643767
auto paramTy = new (mem) ParameterizedProtocolType(
37653768
isCanonical ? &C : nullptr, baseTy, args, properties);
37663769
C.getImpl().getArena(arena).ParameterizedProtocolTypes.InsertNode(
@@ -3851,8 +3854,6 @@ ExistentialMetatypeType::get(Type T, Optional<MetatypeRepresentation> repr,
38513854
T = existential->getConstraintType();
38523855

38533856
auto properties = T->getRecursiveProperties();
3854-
if (T->is<ParameterizedProtocolType>())
3855-
properties |= RecursiveTypeProperties::HasParameterizedExistential;
38563857
auto arena = getArena(properties);
38573858

38583859
unsigned reprKey;
@@ -4722,8 +4723,6 @@ Type ExistentialType::get(Type constraint) {
47224723
printWithAny = false;
47234724

47244725
auto properties = constraint->getRecursiveProperties();
4725-
if (constraint->is<ParameterizedProtocolType>())
4726-
properties |= RecursiveTypeProperties::HasParameterizedExistential;
47274726
auto arena = getArena(properties);
47284727

47294728
auto &entry = C.getImpl().getArena(arena).ExistentialTypes[constraint];

lib/AST/ASTDemangler.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -674,8 +674,7 @@ Type ASTBuilder::createConstrainedExistentialType(
674674

675675
case RequirementKind::SameType:
676676
if (auto *DMT = req.getFirstType()->getAs<DependentMemberType>())
677-
if (baseDecl->getAssociatedType(DMT->getName()))
678-
cmap[DMT->getName()] = req.getSecondType();
677+
cmap[DMT->getName()] = req.getSecondType();
679678
}
680679
}
681680
llvm::SmallVector<Type, 4> args;

lib/AST/ASTMangler.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,14 +1411,18 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
14111411
}
14121412

14131413
case TypeKind::ProtocolComposition: {
1414+
auto *PCT = cast<ProtocolCompositionType>(tybase);
1415+
if (PCT->hasParameterizedExistential())
1416+
return appendConstrainedExistential(PCT, sig, forDecl);
1417+
14141418
// We mangle ProtocolType and ProtocolCompositionType using the
14151419
// same production:
1416-
auto layout = type->getExistentialLayout();
1420+
auto layout = PCT->getExistentialLayout();
14171421
return appendExistentialLayout(layout, sig, forDecl);
14181422
}
14191423

14201424
case TypeKind::ParameterizedProtocol:
1421-
llvm_unreachable("Handled by generalized existential mangling!");
1425+
return appendConstrainedExistential(tybase, sig, forDecl);
14221426

14231427
case TypeKind::Existential: {
14241428
auto *ET = cast<ExistentialType>(tybase);

lib/Demangling/NodePrinter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,6 @@ class NodePrinter {
310310
case Node::Kind::Pack:
311311
case Node::Kind::SILPackDirect:
312312
case Node::Kind::SILPackIndirect:
313-
case Node::Kind::ConstrainedExistential:
314313
case Node::Kind::ConstrainedExistentialRequirementList:
315314
case Node::Kind::ConstrainedExistentialSelf:
316315
case Node::Kind::Protocol:
@@ -340,6 +339,7 @@ class NodePrinter {
340339
case Node::Kind::ProtocolListWithAnyObject:
341340
return Node->getChild(0)->getChild(0)->getNumChildren() == 0;
342341

342+
case Node::Kind::ConstrainedExistential:
343343
case Node::Kind::PackExpansion:
344344
case Node::Kind::ProtocolListWithClass:
345345
case Node::Kind::AccessorAttachedMacroExpansion:

lib/IRGen/GenExistential.cpp

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1520,22 +1520,18 @@ static const TypeInfo *createExistentialTypeInfo(IRGenModule &IGM, CanType T) {
15201520
}
15211521

15221522
llvm::StructType *type;
1523-
if (T->hasParameterizedExistential()) {
1524-
type = IGM.createNominalType(T);
1525-
} else {
1526-
// Note: Protocol composition types are not nominal, but we name them
1527-
// anyway.
1528-
if (auto existential = T->getAs<ExistentialType>()) {
1529-
T = existential->getConstraintType()->getCanonicalType();
1530-
}
15311523

1532-
if (isa<ProtocolType>(T))
1533-
type = IGM.createNominalType(T);
1534-
else
1535-
type =
1536-
IGM.createNominalType(cast<ProtocolCompositionType>(T.getPointer()));
1524+
// Note: Protocol composition types are not nominal, but we name them
1525+
// anyway.
1526+
if (auto existential = T->getAs<ExistentialType>()) {
1527+
T = existential->getConstraintType()->getCanonicalType();
15371528
}
15381529

1530+
if (isa<ProtocolType>(T) || isa<ParameterizedProtocolType>(T))
1531+
type = IGM.createNominalType(T);
1532+
else
1533+
type = IGM.createNominalType(cast<ProtocolCompositionType>(T.getPointer()));
1534+
15391535
assert(type->isOpaque() && "creating existential type in concrete struct");
15401536

15411537
// In an opaque metadata, the first two fields are the fixed buffer
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-build-swift -emit-executable %s -g -o %t/constrained_existentials -emit-module -Xfrontend -disable-availability-checking
4+
// RUN: sed -ne '/\/\/ *DEMANGLE: /s/\/\/ *DEMANGLE: *//p' < %s > %t/input
5+
// RUN: %lldb-moduleimport-test %t/constrained_existentials -type-from-mangled=%t/input | %FileCheck %s
6+
7+
func blackHole(_: Any...) {}
8+
9+
protocol BaseProto<A, B> {
10+
associatedtype A
11+
associatedtype B
12+
}
13+
14+
protocol DerivedProto<A, B>: BaseProto {}
15+
16+
protocol OtherProto {}
17+
18+
struct S<A, B>: DerivedProto, OtherProto {}
19+
20+
// We should lift the artificial ban on compositions involving constrained protocol types
21+
typealias BaseProtoIntStringAndOtherProto = BaseProto<Int, String> & OtherProto
22+
23+
do {
24+
let e0: any BaseProto<Int, String> = S<Int, String>()
25+
let e1: any BaseProto<Int, String>.Type = S<Int, String>.self
26+
let e2: (any BaseProto<Int, String>).Type = (any BaseProto<Int, String>).self
27+
28+
blackHole(e0, e1, e2)
29+
}
30+
31+
// DEMANGLE: $s24constrained_existentials9BaseProto_pSi1AAaBPRts_SS1BADRtsXPD
32+
// DEMANGLE: $s24constrained_existentials9BaseProto_pSi1AAaBPRts_SS1BADRtsXPXmTD
33+
// DEMANGLE: $s24constrained_existentials9BaseProto_pSi1AAaBPRts_SS1BADRtsXPXMtD
34+
35+
// CHECK: BaseProto<Int, String>
36+
// CHECK: @thick BaseProto<Int, String>.Type
37+
// CHECK: @thin BaseProto<Int, String>.Protocol
38+
39+
do {
40+
let e0: any DerivedProto<Int, String> = S<Int, String>()
41+
let e1: any DerivedProto<Int, String>.Type = S<Int, String>.self
42+
let e2: (any DerivedProto<Int, String>).Type = (any DerivedProto<Int, String>).self
43+
44+
blackHole(e0, e1, e2)
45+
}

0 commit comments

Comments
 (0)