mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #74997 from jckarter/protocol-extension-self-same-type-runtime-resolution
Runtime: Fix runtime type resolution when mangled names refer to protocol extensions with Self same type constraints.
This commit is contained in:
@@ -402,6 +402,38 @@ _findExtendedTypeContextDescriptor(const ContextDescriptor *maybeExtension,
|
||||
Demangle::NodePointer &node = demangledNode ? *demangledNode : localNode;
|
||||
|
||||
auto mangledName = extension->getMangledExtendedContext();
|
||||
|
||||
// A extension of the form `extension Protocol where Self == ConcreteType`
|
||||
// is formally a protocol extension, so the formal generic parameter list
|
||||
// is `<Self>`, but because of the same type constraint, the extended context
|
||||
// looks like a reference to that nominal type. We want to match the
|
||||
// extension's formal generic environment rather than the nominal type's
|
||||
// in this case, so we should skip out on this case.
|
||||
//
|
||||
// We can detect this by looking at whether the generic context of the
|
||||
// extension has a first generic parameter, which would be the Self parameter,
|
||||
// with a same type constraint matching the extended type.
|
||||
for (auto &reqt : extension->getGenericRequirements()) {
|
||||
if (reqt.getKind() != GenericRequirementKind::SameType) {
|
||||
continue;
|
||||
}
|
||||
// 'x' is the mangling of the first generic parameter
|
||||
if (!reqt.getParam().equals("x")) {
|
||||
continue;
|
||||
}
|
||||
// Is the generic parameter same-type-constrained to the same type
|
||||
// we're extending? Then this is a `Self == ExtendedType` constraint.
|
||||
// This is impossible for normal generic nominal type extensions because
|
||||
// that would mean that you had:
|
||||
// struct Foo<T> {...}
|
||||
// extension Foo where T == Foo<T> {...}
|
||||
// which would mean that the extended type is the infinite expansion
|
||||
// Foo<Foo<Foo<Foo<...>>>>, which we don't allow.
|
||||
if (reqt.getMangledTypeName().data() == mangledName.data()) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
node = demangler.demangleType(mangledName,
|
||||
ResolveAsSymbolicReference(demangler));
|
||||
if (!node)
|
||||
@@ -1254,7 +1286,8 @@ _gatherGenericParameters(const ContextDescriptor *context,
|
||||
(void)_gatherGenericParameterCounts(context,
|
||||
genericParamCounts, demangler);
|
||||
unsigned numTotalGenericParams =
|
||||
genericParamCounts.empty() ? 0 : genericParamCounts.back();
|
||||
genericParamCounts.empty() ? context->getNumGenericParams()
|
||||
: genericParamCounts.back();
|
||||
|
||||
// Check whether we have the right number of generic arguments.
|
||||
if (genericArgs.size() == getLocalGenericParams(context).size()) {
|
||||
|
||||
27
test/Runtime/protocol_self_same_type_extension.swift
Normal file
27
test/Runtime/protocol_self_same_type_extension.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
// RUN: %target-run-simple-swift | %FileCheck %s
|
||||
// REQUIRES: executable_test
|
||||
// UNSUPPORTED: use_os_stdlib
|
||||
// UNSUPPORTED: back_deployment_runtime
|
||||
|
||||
// rdar://130168101: Make sure that we correctly resolve types in
|
||||
// the generic context of a protocol extension with a `Self` same
|
||||
// type constraint.
|
||||
|
||||
|
||||
protocol P { }
|
||||
|
||||
struct P2: P { }
|
||||
|
||||
extension P where Self == P2 {
|
||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||
dynamic func p2() -> some P {
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK: P2()
|
||||
if #available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) {
|
||||
print(P2().p2())
|
||||
} else {
|
||||
print(P2())
|
||||
}
|
||||
Reference in New Issue
Block a user