@@ -149,13 +149,20 @@ void ConformanceLookupTable::destroy() {
149
149
150
150
namespace {
151
151
struct ConformanceConstructionInfo : public Located <ProtocolDecl *> {
152
+ // / The `TypeRepr` of the inheritance clause entry from which this nominal
153
+ // / was sourced, if any. For example, if this is a conformance to `Y`
154
+ // / declared as `struct S: X, Y & Z {}`, this is the `TypeRepr` for `Y & Z`.
155
+ TypeRepr *inheritedTypeRepr;
156
+
152
157
ConformanceAttributes attributes;
153
158
154
159
ConformanceConstructionInfo () { }
155
160
156
161
ConformanceConstructionInfo (ProtocolDecl *item, SourceLoc loc,
162
+ TypeRepr *inheritedTypeRepr,
157
163
ConformanceAttributes attributes)
158
- : Located(item, loc), attributes(attributes) {}
164
+ : Located(item, loc), inheritedTypeRepr(inheritedTypeRepr),
165
+ attributes (attributes) {}
159
166
};
160
167
}
161
168
@@ -210,8 +217,9 @@ void ConformanceLookupTable::forEachInStage(ConformanceStage stage,
210
217
loader.first ->loadAllConformances (next, loader.second , conformances);
211
218
registerProtocolConformances (next, conformances);
212
219
for (auto conf : conformances) {
213
- protocols.push_back (
214
- {conf->getProtocol (), SourceLoc (), ConformanceAttributes ()});
220
+ protocols.push_back ({conf->getProtocol (), SourceLoc (),
221
+ /* inheritedTypeRepr=*/ nullptr ,
222
+ ConformanceAttributes ()});
215
223
}
216
224
} else if (next->getParentSourceFile () ||
217
225
next->getParentModule ()->isBuiltinModule ()) {
@@ -220,7 +228,8 @@ void ConformanceLookupTable::forEachInStage(ConformanceStage stage,
220
228
for (const auto &found :
221
229
getDirectlyInheritedNominalTypeDecls (next, inverses, anyObject)) {
222
230
if (auto proto = dyn_cast<ProtocolDecl>(found.Item ))
223
- protocols.push_back ({proto, found.Loc , found.attributes });
231
+ protocols.push_back (
232
+ {proto, found.Loc , found.inheritedTypeRepr , found.attributes });
224
233
}
225
234
}
226
235
@@ -292,8 +301,6 @@ void ConformanceLookupTable::updateLookupTable(NominalTypeDecl *nominal,
292
301
forEachInStage (
293
302
stage, nominal,
294
303
[&](NominalTypeDecl *nominal) {
295
- auto source = ConformanceSource::forExplicit (nominal);
296
-
297
304
// Get all of the protocols in the inheritance clause.
298
305
InvertibleProtocolSet inverses;
299
306
bool anyObject = false ;
@@ -303,10 +310,12 @@ void ConformanceLookupTable::updateLookupTable(NominalTypeDecl *nominal,
303
310
if (!proto)
304
311
continue ;
305
312
auto kp = proto->getKnownProtocolKind ();
306
- assert (!found.isSuppressed ||
307
- kp.has_value () &&
308
- " suppressed conformance for non-known protocol!?" );
313
+ assert (!found.isSuppressed ||
314
+ kp.has_value () &&
315
+ " suppressed conformance for non-known protocol!?" );
309
316
if (!found.isSuppressed ) {
317
+ auto source = ConformanceSource::forExplicit (
318
+ nominal, found.inheritedTypeRepr );
310
319
addProtocol (
311
320
proto, found.Loc , source.withAttributes (found.attributes ));
312
321
}
@@ -318,11 +327,12 @@ void ConformanceLookupTable::updateLookupTable(NominalTypeDecl *nominal,
318
327
[&](ExtensionDecl *ext, ArrayRef<ConformanceConstructionInfo> protos) {
319
328
// The extension decl may not be validated, so we can't use
320
329
// its inherited protocols directly.
321
- auto source = ConformanceSource::forExplicit (ext);
322
- for (auto locAndProto : protos)
323
- addProtocol (
324
- locAndProto.Item , locAndProto.Loc ,
325
- source.withAttributes (locAndProto.attributes ));
330
+ for (auto locAndProto : protos) {
331
+ auto source = ConformanceSource::forExplicit (
332
+ ext, locAndProto.inheritedTypeRepr );
333
+ addProtocol (locAndProto.Item , locAndProto.Loc ,
334
+ source.withAttributes (locAndProto.attributes ));
335
+ }
326
336
});
327
337
break ;
328
338
@@ -973,12 +983,17 @@ ConformanceLookupTable::getConformance(NominalTypeDecl *nominal,
973
983
implyingConf = origImplyingConf->getRootNormalConformance ();
974
984
}
975
985
986
+ TypeRepr *inheritedTypeRepr = nullptr ;
987
+ if (entry->Source .getKind () == ConformanceEntryKind::Explicit) {
988
+ inheritedTypeRepr = entry->Source .getInheritedTypeRepr ();
989
+ }
990
+
976
991
// Create or find the normal conformance.
977
992
auto normalConf = ctx.getNormalConformance (
978
- conformingType, protocol, conformanceLoc, conformingDC ,
979
- ProtocolConformanceState::Incomplete,
980
- entry->Source .getOptions (),
981
- entry-> Source . getPreconcurrencyLoc ());
993
+ conformingType, protocol, conformanceLoc, inheritedTypeRepr ,
994
+ conformingDC, ProtocolConformanceState::Incomplete,
995
+ entry->Source .getOptions ());
996
+
982
997
// Invalid code may cause the getConformance call below to loop, so break
983
998
// the infinite recursion by setting this eagerly to shortcircuit with the
984
999
// early return at the start of this function.
@@ -1046,10 +1061,11 @@ void ConformanceLookupTable::registerProtocolConformance(
1046
1061
1047
1062
// Otherwise, add a new entry.
1048
1063
auto inherited = dyn_cast<InheritedProtocolConformance>(conformance);
1049
- ConformanceSource source
1050
- = inherited ? ConformanceSource::forInherited (cast<ClassDecl>(nominal)) :
1051
- synthesized ? ConformanceSource::forSynthesized (dc) :
1052
- ConformanceSource::forExplicit (dc);
1064
+ ConformanceSource source =
1065
+ inherited ? ConformanceSource::forInherited (cast<ClassDecl>(nominal))
1066
+ : synthesized
1067
+ ? ConformanceSource::forSynthesized (dc)
1068
+ : ConformanceSource::forExplicit (dc, /* inheritedEntry=*/ nullptr );
1053
1069
1054
1070
ASTContext &ctx = nominal->getASTContext ();
1055
1071
ConformanceEntry *entry = new (ctx) ConformanceEntry (SourceLoc (),
0 commit comments