Skip to content

Commit 8bcd09a

Browse files
committed
SIL: Preliminary refactoring of SILWitnessTable::AssociatedConformanceWitness
The Protocol field isn't really necessary, because the conformance stores the protocol. But we do need the substituted subject type of the requirement, just temporarily, until an abstract conformance stores its own subject type too.
1 parent 2a41a32 commit 8bcd09a

File tree

19 files changed

+105
-61
lines changed

19 files changed

+105
-61
lines changed

SwiftCompilerSources/Sources/AST/Conformance.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ public struct Conformance: CustomStringConvertible, NoReflectionChildren {
3737
return Type(bridged: bridged.getType())
3838
}
3939

40+
public var proto: ProtocolDecl {
41+
return bridged.getRequirement().getAs(ProtocolDecl.self)
42+
}
4043
public var isSpecialized: Bool {
4144
assert(isConcrete)
4245
return bridged.isSpecializedConformance()

SwiftCompilerSources/Sources/Optimizer/Utilities/GenericSpecialization.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,17 @@ func specializeWitnessTable(forConformance conformance: Conformance,
144144
case .associatedType(let requirement, let witness):
145145
let substType = witness.subst(with: conformance.specializedSubstitutions)
146146
return .associatedType(requirement: requirement, witness: substType)
147-
case .associatedConformance(let requirement, let proto, _):
148-
let concreteAssociateConf = conformance.getAssociatedConformance(ofAssociatedType: requirement.rawType, to: proto)
147+
case .associatedConformance(let requirement, let substType, let assocConf):
148+
// FIXME: let concreteAssociateConf = assocConf.subst(with: conformance.specializedSubstitutions)
149+
let concreteAssociateConf = conformance.getAssociatedConformance(ofAssociatedType: requirement.rawType, to: assocConf.proto)
149150
if concreteAssociateConf.isSpecialized {
150151
specializeWitnessTable(forConformance: concreteAssociateConf,
151152
errorLocation: errorLocation,
152153
context, notifyNewWitnessTable)
153154
}
154-
return .associatedConformance(requirement: requirement, protocol: proto, witness: concreteAssociateConf)
155+
return .associatedConformance(requirement: requirement,
156+
substType: substType.subst(with: conformance.specializedSubstitutions),
157+
witness: concreteAssociateConf)
155158
}
156159
}
157160
let newWT = context.createWitnessTable(entries: newEntries,conformance: conformance,

SwiftCompilerSources/Sources/SIL/WitnessTable.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public struct WitnessTable : CustomStringConvertible, NoReflectionChildren {
3131
case associatedType(requirement: AssociatedTypeDecl, witness: CanonicalType)
3232

3333
/// A witness table entry describing the witness for an associated type's protocol requirement.
34-
case associatedConformance(requirement: CanonicalType, protocol: ProtocolDecl, witness: Conformance)
34+
case associatedConformance(requirement: CanonicalType, substType: CanonicalType, witness: Conformance)
3535

3636
/// A witness table entry referencing the protocol conformance for a refined base protocol.
3737
case baseProtocol(requirement: ProtocolDecl, witness: Conformance)
@@ -48,7 +48,7 @@ public struct WitnessTable : CustomStringConvertible, NoReflectionChildren {
4848
witness: CanonicalType(bridged: bridged.getAssociatedTypeWitness()))
4949
case .associatedConformance:
5050
self = .associatedConformance(requirement: CanonicalType(bridged: bridged.getAssociatedConformanceRequirement()),
51-
protocol: bridged.getAssociatedConformanceDecl().getAs(ProtocolDecl.self),
51+
substType: CanonicalType(bridged: bridged.getAssociatedConformanceSubstType()),
5252
witness: Conformance(bridged: bridged.getAssociatedConformanceWitness()))
5353
case .baseProtocol:
5454
self = .baseProtocol(requirement: bridged.getBaseProtocolRequirement().getAs(ProtocolDecl.self),
@@ -71,9 +71,9 @@ public struct WitnessTable : CustomStringConvertible, NoReflectionChildren {
7171
OptionalBridgedFunction(obj: witness?.bridged.obj))
7272
case .associatedType(let requirement, let witness):
7373
return BridgedWitnessTableEntry.createAssociatedType(requirement.bridged, witness.bridged)
74-
case .associatedConformance(let requirement, let protocolDecl, let witness):
74+
case .associatedConformance(let requirement, let substType, let witness):
7575
return BridgedWitnessTableEntry.createAssociatedConformance(requirement.bridged,
76-
protocolDecl.bridged,
76+
substType.bridged,
7777
witness.bridged)
7878
case .baseProtocol(let requirement, let witness):
7979
return BridgedWitnessTableEntry.createBaseProtocol(requirement.bridged, witness.bridged)

include/swift/AST/ASTBridging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3110,6 +3110,7 @@ struct BridgedConformance {
31103110
BRIDGED_INLINE bool isSpecializedConformance() const;
31113111
BRIDGED_INLINE bool isInheritedConformance() const;
31123112
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType getType() const;
3113+
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedDeclObj getRequirement() const;
31133114
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedConformance getGenericConformance() const;
31143115
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedConformance getInheritedConformance() const;
31153116
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedSubstitutionMap getSpecializedSubstitutions() const;

include/swift/AST/ASTBridgingImpl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,10 @@ BridgedASTType BridgedConformance::getType() const {
601601
return {unbridged().getConcrete()->getType().getPointer()};
602602
}
603603

604+
BridgedDeclObj BridgedConformance::getRequirement() const {
605+
return {unbridged().getRequirement()};
606+
}
607+
604608
BridgedConformance BridgedConformance::getGenericConformance() const {
605609
auto *specPC = swift::cast<swift::SpecializedProtocolConformance>(unbridged().getConcrete());
606610
return {swift::ProtocolConformanceRef(specPC->getGenericConformance())};

include/swift/SIL/SILBridging.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,7 +1007,7 @@ struct BridgedWitnessTableEntry {
10071007
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedDeclObj getAssociatedTypeRequirement() const;
10081008
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedCanType getAssociatedTypeWitness() const;
10091009
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedCanType getAssociatedConformanceRequirement() const;
1010-
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedDeclObj getAssociatedConformanceDecl() const;
1010+
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedCanType getAssociatedConformanceSubstType() const;
10111011
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedConformance getAssociatedConformanceWitness() const;
10121012
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedDeclObj getBaseProtocolRequirement() const;
10131013
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedConformance getBaseProtocolWitness() const;
@@ -1022,7 +1022,7 @@ struct BridgedWitnessTableEntry {
10221022
BridgedCanType witness);
10231023
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE
10241024
static BridgedWitnessTableEntry createAssociatedConformance(BridgedCanType requirement,
1025-
BridgedDeclObj protocolDecl,
1025+
BridgedCanType substType,
10261026
BridgedConformance witness);
10271027
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE
10281028
static BridgedWitnessTableEntry createBaseProtocol(BridgedDeclObj requirement,

include/swift/SIL/SILBridgingImpl.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1832,8 +1832,8 @@ BridgedCanType BridgedWitnessTableEntry::getAssociatedConformanceRequirement() c
18321832
return unbridged().getAssociatedConformanceWitness().Requirement;
18331833
}
18341834

1835-
BridgedDeclObj BridgedWitnessTableEntry::getAssociatedConformanceDecl() const {
1836-
return {unbridged().getAssociatedConformanceWitness().Protocol};
1835+
BridgedCanType BridgedWitnessTableEntry::getAssociatedConformanceSubstType() const {
1836+
return {unbridged().getAssociatedConformanceWitness().SubstType};
18371837
}
18381838

18391839
BridgedConformance BridgedWitnessTableEntry::getAssociatedConformanceWitness() const {
@@ -1867,11 +1867,11 @@ BridgedWitnessTableEntry BridgedWitnessTableEntry::createAssociatedType(BridgedD
18671867
}
18681868

18691869
BridgedWitnessTableEntry BridgedWitnessTableEntry::createAssociatedConformance(BridgedCanType requirement,
1870-
BridgedDeclObj protocolDecl,
1870+
BridgedCanType substType,
18711871
BridgedConformance witness) {
18721872
return bridge(swift::SILWitnessTable::Entry(
18731873
swift::SILWitnessTable::AssociatedConformanceWitness{requirement.unbridged(),
1874-
protocolDecl.getAs<swift::ProtocolDecl>(),
1874+
substType.unbridged(),
18751875
witness.unbridged()}));
18761876
}
18771877

include/swift/SIL/SILWitnessTable.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,11 @@ class SILWitnessTable : public llvm::ilist_node<SILWitnessTable>,
6464
/// A witness table entry describing the witness for an associated type's
6565
/// protocol requirement.
6666
struct AssociatedConformanceWitness {
67-
/// The associated type required. A dependent type in the protocol's
68-
/// context.
67+
/// The subject type of the associated requirement.
6968
CanType Requirement;
70-
/// The protocol requirement on the type.
71-
ProtocolDecl *Protocol;
72-
/// The ProtocolConformance satisfying the requirement. Null if the
73-
/// conformance is dependent.
69+
/// FIXME: Temporary.
70+
CanType SubstType;
71+
/// The ProtocolConformanceRef satisfying the requirement.
7472
ProtocolConformanceRef Witness;
7573
};
7674

@@ -160,6 +158,7 @@ class SILWitnessTable : public llvm::ilist_node<SILWitnessTable>,
160158
/// conditional. These aren't public, but any witness thunks need to feed them
161159
/// into the true witness functions.
162160
struct ConditionalConformance {
161+
/// FIXME: Temporary.
163162
CanType Requirement;
164163
ProtocolConformanceRef Conformance;
165164
};

lib/IRGen/GenMeta.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,14 +1182,17 @@ namespace {
11821182

11831183
for (auto &entry : DefaultWitnesses->getEntries()) {
11841184
if (!entry.isValid() ||
1185-
entry.getKind() != SILWitnessTable::AssociatedConformance ||
1186-
entry.getAssociatedConformanceWitness().Protocol != requirement ||
1187-
entry.getAssociatedConformanceWitness().Requirement != association)
1185+
entry.getKind() != SILWitnessTable::AssociatedConformance)
1186+
continue;
1187+
1188+
auto assocConf = entry.getAssociatedConformanceWitness();
1189+
if (assocConf.Requirement != association ||
1190+
assocConf.Witness.getRequirement() != requirement)
11881191
continue;
11891192

1190-
auto witness = entry.getAssociatedConformanceWitness().Witness;
11911193
AssociatedConformance conformance(Proto, association, requirement);
1192-
defineDefaultAssociatedConformanceAccessFunction(conformance, witness);
1194+
defineDefaultAssociatedConformanceAccessFunction(
1195+
conformance, assocConf.Witness);
11931196
return IGM.getMangledAssociatedConformance(nullptr, conformance);
11941197
}
11951198

lib/IRGen/GenProto.cpp

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,9 +1780,6 @@ class AccessorConformanceInfo : public ConformanceInfo {
17801780
auto associatedWitness = entry.getAssociatedConformanceWitness();
17811781
assert(associatedWitness.Requirement == requirement.getAssociation()
17821782
&& "sil witness table does not match protocol");
1783-
assert(associatedWitness.Protocol ==
1784-
requirement.getAssociatedRequirement()
1785-
&& "sil witness table does not match protocol");
17861783
auto piIndex = PI.getAssociatedConformanceIndex(requirement);
17871784
assert((size_t)piIndex.getValue() ==
17881785
Table.size() - WitnessTableFirstRequirementOffset &&
@@ -1792,10 +1789,8 @@ class AccessorConformanceInfo : public ConformanceInfo {
17921789
if (IGM.Context.LangOpts.hasFeature(Feature::Embedded)) {
17931790
// In Embedded Swift associated-conformance entries simply point to the witness table
17941791
// of the associated conformance.
1795-
ProtocolConformanceRef assocConf =
1796-
SILWT->getConformance()->getAssociatedConformance(requirement.getAssociation(),
1797-
requirement.getAssociatedRequirement());
1798-
llvm::Constant *witnessEntry = IGM.getAddrOfWitnessTable(assocConf.getConcrete());
1792+
ProtocolConformance *assocConf = associatedWitness.Witness.getConcrete();
1793+
llvm::Constant *witnessEntry = IGM.getAddrOfWitnessTable(assocConf);
17991794
auto &schema = IGM.getOptions().PointerAuth
18001795
.ProtocolAssociatedTypeWitnessTableAccessFunctions;
18011796
Table.addSignedPointer(witnessEntry, schema, requirement);
@@ -2030,10 +2025,11 @@ void ResilientWitnessTableBuilder::collectResilientWitnesses(
20302025

20312026
ProtocolConformanceRef associatedConformance =
20322027
ConformanceInContext.getAssociatedConformance(witness.Requirement,
2033-
witness.Protocol);
2028+
witness.Witness.getRequirement());
2029+
20342030
AssociatedConformance requirement(SILWT->getProtocol(),
20352031
witness.Requirement,
2036-
witness.Protocol);
2032+
witness.Witness.getRequirement());
20372033

20382034
llvm::Constant *witnessEntry =
20392035
getAssociatedConformanceWitness(requirement, associate,
@@ -2353,7 +2349,7 @@ namespace {
23532349

23542350
AssociatedConformance requirement(SILWT->getProtocol(),
23552351
witness.Requirement,
2356-
witness.Protocol);
2352+
witness.Witness.getRequirement());
23572353
auto assocConformanceDescriptor =
23582354
IGM.getAddrOfLLVMVariableOrGOTEquivalent(
23592355
LinkEntity::forAssociatedConformanceDescriptor(requirement));

lib/SIL/IR/SILPrinter.cpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4269,13 +4269,18 @@ void SILWitnessTable::Entry::print(llvm::raw_ostream &out, bool verbose,
42694269
case WitnessKind::AssociatedConformance: {
42704270
// associated_conformance (AssociatedTypeName: Protocol): <conformance>
42714271
auto &assocProtoWitness = getAssociatedConformanceWitness();
4272+
if (assocProtoWitness.Witness.isInvalid())
4273+
return;
42724274
out << "associated_conformance (";
42734275
(void) printAssociatedTypePath(out, assocProtoWitness.Requirement);
4274-
out << ": " << assocProtoWitness.Protocol->getName() << "): ";
4275-
if (assocProtoWitness.Witness.isConcrete())
4276-
assocProtoWitness.Witness.getConcrete()->printName(out, options);
4277-
else
4278-
out << "dependent";
4276+
auto conformance = assocProtoWitness.Witness;
4277+
out << ": " << conformance.getRequirement()->getName() << "): ";
4278+
if (conformance.isConcrete())
4279+
conformance.getConcrete()->printName(out, options);
4280+
else {
4281+
out << "dependent ";
4282+
assocProtoWitness.SubstType->print(out, options);
4283+
}
42794284
break;
42804285
}
42814286
case WitnessKind::BaseProtocol: {
@@ -4316,14 +4321,19 @@ void SILWitnessTable::print(llvm::raw_ostream &OS, bool Verbose) const {
43164321
for (auto conditionalConformance : getConditionalConformances()) {
43174322
// conditional_conformance (TypeName: Protocol):
43184323
// <conformance>
4324+
if (conditionalConformance.Conformance.isInvalid())
4325+
continue;
4326+
43194327
OS << " conditional_conformance (";
43204328
conditionalConformance.Requirement.print(OS, Options);
43214329
OS << ": " << conditionalConformance.Conformance.getRequirement()->getName()
43224330
<< "): ";
43234331
if (conditionalConformance.Conformance.isConcrete())
43244332
conditionalConformance.Conformance.getConcrete()->printName(OS, Options);
4325-
else
4326-
OS << "dependent";
4333+
else {
4334+
OS << "dependent ";
4335+
conditionalConformance.Requirement->print(OS, Options);
4336+
}
43274337

43284338
OS << '\n';
43294339
}

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8168,23 +8168,47 @@ static bool parseSILWitnessTableEntry(
81688168
P.parseToken(tok::colon, diag::expected_sil_witness_colon))
81698169
return true;
81708170

8171-
// FIXME: Passing an empty Type() here temporarily.
8172-
auto conformance = ProtocolConformanceRef::forAbstract(Type(), proto);
8171+
CanType substType;
8172+
ProtocolConformanceRef conformance;
81738173
if (P.Tok.getText() != "dependent") {
81748174
auto concrete =
81758175
witnessState.parseProtocolConformance();
81768176
// Ignore invalid and abstract witness entries.
81778177
if (concrete.isInvalid() || !concrete.isConcrete())
81788178
return false;
8179+
substType = concrete.getConcrete()->getType()->getCanonicalType();
81798180
conformance = concrete;
81808181
} else {
81818182
P.consumeToken();
8183+
8184+
// Parse AST type.
8185+
ParserResult<TypeRepr> TyR = P.parseType();
8186+
if (TyR.isNull())
8187+
return true;
8188+
8189+
SILTypeResolutionContext silContext(/*isSILType=*/false,
8190+
witnessParams,
8191+
/*openedPacks=*/nullptr);
8192+
auto Ty =
8193+
swift::performTypeResolution(TyR.get(), P.Context,
8194+
witnessSig, &silContext,
8195+
&P.SF);
8196+
if (witnessSig) {
8197+
Ty = witnessSig.getGenericEnvironment()->mapTypeIntoContext(Ty);
8198+
}
8199+
8200+
if (Ty->hasError())
8201+
return true;
8202+
8203+
substType = Ty->getCanonicalType();
8204+
conformance = ProtocolConformanceRef::forAbstract(
8205+
Ty->getCanonicalType(), proto);
81828206
}
81838207

81848208
if (EntryKeyword.str() == "associated_conformance")
81858209
witnessEntries.push_back(
81868210
SILWitnessTable::AssociatedConformanceWitness{assocOrSubject,
8187-
proto,
8211+
substType,
81888212
conformance});
81898213
else
81908214
conditionalConformances.push_back(

lib/SILGen/SILGenType.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -670,12 +670,13 @@ class SILGenConformance : public SILGenWitnessTable<SILGenConformance> {
670670
auto assocConformance =
671671
Conformance->getAssociatedConformance(req.getAssociation(),
672672
req.getAssociatedRequirement());
673+
auto substType =
674+
Conformance->getAssociatedType(req.getAssociation())->getCanonicalType();
673675

674676
SGM.useConformance(assocConformance);
675677

676678
Entries.push_back(SILWitnessTable::AssociatedConformanceWitness{
677-
req.getAssociation(), req.getAssociatedRequirement(),
678-
assocConformance});
679+
req.getAssociation(), substType, assocConformance});
679680
}
680681

681682
void addConditionalRequirements() {
@@ -1105,7 +1106,7 @@ class SILGenDefaultWitnessTable
11051106
return addMissingDefault();
11061107

11071108
auto entry = SILWitnessTable::AssociatedConformanceWitness{
1108-
req.getAssociation(), req.getAssociatedRequirement(), witness};
1109+
req.getAssociation(), req.getAssociation(), witness};
11091110
DefaultWitnesses.push_back(entry);
11101111
}
11111112
};

lib/Serialization/DeserializeSIL.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4446,16 +4446,16 @@ void SILDeserializer::readWitnessTableEntries(
44464446
proto, conformance.getConcrete()
44474447
});
44484448
} else if (kind == SIL_WITNESS_ASSOC_PROTOCOL) {
4449-
TypeID assocId;
4450-
DeclID protoId;
4449+
TypeID origTypeId;
4450+
DeclID substTypeId;
44514451
ProtocolConformanceID conformanceId;
4452-
WitnessAssocProtocolLayout::readRecord(scratch, assocId, protoId,
4452+
WitnessAssocProtocolLayout::readRecord(scratch, origTypeId, substTypeId,
44534453
conformanceId);
4454-
CanType type = MF->getType(assocId)->getCanonicalType();
4455-
ProtocolDecl *proto = cast<ProtocolDecl>(MF->getDecl(protoId));
4454+
CanType origType = MF->getType(origTypeId)->getCanonicalType();
4455+
CanType substType = MF->getType(substTypeId)->getCanonicalType();
44564456
auto conformance = MF->getConformance(conformanceId);
44574457
witnessEntries.push_back(SILWitnessTable::AssociatedConformanceWitness{
4458-
type, proto, conformance
4458+
origType, substType, conformance
44594459
});
44604460
} else if (kind == SIL_WITNESS_ASSOC_ENTRY) {
44614461
DeclID assocId;

lib/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 925; // isolated conformances
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 926; // abstract conformances
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///

lib/Serialization/SILFormat.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,8 @@ namespace sil_block {
244244

245245
using WitnessAssocProtocolLayout = BCRecordLayout<
246246
SIL_WITNESS_ASSOC_PROTOCOL,
247-
TypeIDField, // ID of associated type
248-
DeclIDField, // ID of ProtocolDecl
247+
TypeIDField, // ID of requirement subject type
248+
TypeIDField, // ID of substituted subject type
249249
ProtocolConformanceIDField
250250
>;
251251

0 commit comments

Comments
 (0)