Skip to content

Commit 69ec03c

Browse files
authored
Merge pull request #74999 from jckarter/protocol-extension-self-same-type-runtime-resolution-6.0
[6.0] Runtime: Fix runtime type resolution when mangled names refer to protocol extensions with Self same type constraints.
2 parents b9cb872 + d519d44 commit 69ec03c

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,38 @@ _findExtendedTypeContextDescriptor(const ContextDescriptor *maybeExtension,
400400
Demangle::NodePointer &node = demangledNode ? *demangledNode : localNode;
401401

402402
auto mangledName = extension->getMangledExtendedContext();
403+
404+
// A extension of the form `extension Protocol where Self == ConcreteType`
405+
// is formally a protocol extension, so the formal generic parameter list
406+
// is `<Self>`, but because of the same type constraint, the extended context
407+
// looks like a reference to that nominal type. We want to match the
408+
// extension's formal generic environment rather than the nominal type's
409+
// in this case, so we should skip out on this case.
410+
//
411+
// We can detect this by looking at whether the generic context of the
412+
// extension has a first generic parameter, which would be the Self parameter,
413+
// with a same type constraint matching the extended type.
414+
for (auto &reqt : extension->getGenericRequirements()) {
415+
if (reqt.getKind() != GenericRequirementKind::SameType) {
416+
continue;
417+
}
418+
// 'x' is the mangling of the first generic parameter
419+
if (!reqt.getParam().equals("x")) {
420+
continue;
421+
}
422+
// Is the generic parameter same-type-constrained to the same type
423+
// we're extending? Then this is a `Self == ExtendedType` constraint.
424+
// This is impossible for normal generic nominal type extensions because
425+
// that would mean that you had:
426+
// struct Foo<T> {...}
427+
// extension Foo where T == Foo<T> {...}
428+
// which would mean that the extended type is the infinite expansion
429+
// Foo<Foo<Foo<Foo<...>>>>, which we don't allow.
430+
if (reqt.getMangledTypeName().data() == mangledName.data()) {
431+
return nullptr;
432+
}
433+
}
434+
403435
node = demangler.demangleType(mangledName,
404436
ResolveAsSymbolicReference(demangler));
405437
if (!node)
@@ -1252,7 +1284,8 @@ _gatherGenericParameters(const ContextDescriptor *context,
12521284
(void)_gatherGenericParameterCounts(context,
12531285
genericParamCounts, demangler);
12541286
unsigned numTotalGenericParams =
1255-
genericParamCounts.empty() ? 0 : genericParamCounts.back();
1287+
genericParamCounts.empty() ? context->getNumGenericParams()
1288+
: genericParamCounts.back();
12561289

12571290
// Check whether we have the right number of generic arguments.
12581291
if (genericArgs.size() == getLocalGenericParams(context).size()) {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %target-run-simple-swift | %FileCheck %s
2+
// REQUIRES: executable_test
3+
// UNSUPPORTED: use_os_stdlib
4+
// UNSUPPORTED: back_deployment_runtime
5+
6+
// rdar://130168101: Make sure that we correctly resolve types in
7+
// the generic context of a protocol extension with a `Self` same
8+
// type constraint.
9+
10+
11+
protocol P { }
12+
13+
struct P2: P { }
14+
15+
extension P where Self == P2 {
16+
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
17+
dynamic func p2() -> some P {
18+
return self
19+
}
20+
}
21+
22+
// CHECK: P2()
23+
if #available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) {
24+
print(P2().p2())
25+
} else {
26+
print(P2())
27+
}

0 commit comments

Comments
 (0)