@@ -149,13 +149,20 @@ void ConformanceLookupTable::destroy() {
149149
150150namespace {
151151 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+
152157 ConformanceAttributes attributes;
153158
154159 ConformanceConstructionInfo () { }
155160
156161 ConformanceConstructionInfo (ProtocolDecl *item, SourceLoc loc,
162+ TypeRepr *inheritedTypeRepr,
157163 ConformanceAttributes attributes)
158- : Located(item, loc), attributes(attributes) {}
164+ : Located(item, loc), inheritedTypeRepr(inheritedTypeRepr),
165+ attributes (attributes) {}
159166 };
160167}
161168
@@ -210,8 +217,9 @@ void ConformanceLookupTable::forEachInStage(ConformanceStage stage,
210217 loader.first ->loadAllConformances (next, loader.second , conformances);
211218 registerProtocolConformances (next, conformances);
212219 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 ()});
215223 }
216224 } else if (next->getParentSourceFile () ||
217225 next->getParentModule ()->isBuiltinModule ()) {
@@ -220,7 +228,8 @@ void ConformanceLookupTable::forEachInStage(ConformanceStage stage,
220228 for (const auto &found :
221229 getDirectlyInheritedNominalTypeDecls (next, inverses, anyObject)) {
222230 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 });
224233 }
225234 }
226235
@@ -292,8 +301,6 @@ void ConformanceLookupTable::updateLookupTable(NominalTypeDecl *nominal,
292301 forEachInStage (
293302 stage, nominal,
294303 [&](NominalTypeDecl *nominal) {
295- auto source = ConformanceSource::forExplicit (nominal);
296-
297304 // Get all of the protocols in the inheritance clause.
298305 InvertibleProtocolSet inverses;
299306 bool anyObject = false ;
@@ -303,10 +310,12 @@ void ConformanceLookupTable::updateLookupTable(NominalTypeDecl *nominal,
303310 if (!proto)
304311 continue ;
305312 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!?" );
309316 if (!found.isSuppressed ) {
317+ auto source = ConformanceSource::forExplicit (
318+ nominal, found.inheritedTypeRepr );
310319 addProtocol (
311320 proto, found.Loc , source.withAttributes (found.attributes ));
312321 }
@@ -318,11 +327,12 @@ void ConformanceLookupTable::updateLookupTable(NominalTypeDecl *nominal,
318327 [&](ExtensionDecl *ext, ArrayRef<ConformanceConstructionInfo> protos) {
319328 // The extension decl may not be validated, so we can't use
320329 // 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+ }
326336 });
327337 break ;
328338
@@ -977,12 +987,17 @@ ConformanceLookupTable::getConformance(NominalTypeDecl *nominal,
977987 implyingConf = origImplyingConf->getRootNormalConformance ();
978988 }
979989
990+ TypeRepr *inheritedTypeRepr = nullptr ;
991+ if (entry->Source .getKind () == ConformanceEntryKind::Explicit) {
992+ inheritedTypeRepr = entry->Source .getInheritedTypeRepr ();
993+ }
994+
980995 // Create or find the normal conformance.
981996 auto normalConf = ctx.getNormalConformance (
982- conformingType, protocol, conformanceLoc, conformingDC ,
983- ProtocolConformanceState::Incomplete,
984- entry->Source .getOptions (),
985- entry-> Source . getPreconcurrencyLoc ());
997+ conformingType, protocol, conformanceLoc, inheritedTypeRepr ,
998+ conformingDC, ProtocolConformanceState::Incomplete,
999+ entry->Source .getOptions ());
1000+
9861001 // Invalid code may cause the getConformance call below to loop, so break
9871002 // the infinite recursion by setting this eagerly to shortcircuit with the
9881003 // early return at the start of this function.
@@ -1050,10 +1065,11 @@ void ConformanceLookupTable::registerProtocolConformance(
10501065
10511066 // Otherwise, add a new entry.
10521067 auto inherited = dyn_cast<InheritedProtocolConformance>(conformance);
1053- ConformanceSource source
1054- = inherited ? ConformanceSource::forInherited (cast<ClassDecl>(nominal)) :
1055- synthesized ? ConformanceSource::forSynthesized (dc) :
1056- ConformanceSource::forExplicit (dc);
1068+ ConformanceSource source =
1069+ inherited ? ConformanceSource::forInherited (cast<ClassDecl>(nominal))
1070+ : synthesized
1071+ ? ConformanceSource::forSynthesized (dc)
1072+ : ConformanceSource::forExplicit (dc, /* inheritedEntry=*/ nullptr );
10571073
10581074 ASTContext &ctx = nominal->getASTContext ();
10591075 ConformanceEntry *entry = new (ctx) ConformanceEntry (SourceLoc (),
0 commit comments