Skip to content

Commit 27ba7be

Browse files
authored
Merge pull request #89138 from augusto2112/fix-protocol-typealias-typeref
[RemoteInspection] Fix generic typealiases in DemanglingForTypeRef
2 parents cfc3ebf + 600d597 commit 27ba7be

2 files changed

Lines changed: 94 additions & 15 deletions

File tree

stdlib/public/RemoteInspection/TypeRef.cpp

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -638,26 +638,63 @@ class DemanglingForTypeRef
638638

639639
/// Produce the node to install as a nominal's context when swapping in the
640640
/// richer parent stored on the TypeRef.
641-
///
642-
/// Extensions are special because they're the only node that can appear
643-
/// instead of the parent (and contain it). For an Extension, the richer
644-
/// parent replaces the extended-type slot, preserving the module and any
645-
/// generic signature. For every other context kind, the richer parent
646-
/// replaces the context wholesale.
647-
///
648-
/// Returns nullptr if originalContext is a malformed Extension.
649641
Demangle::NodePointer
650642
substituteParentIntoContext(Demangle::NodePointer originalContext,
651643
Demangle::NodePointer parentNode) {
652-
if (originalContext->getKind() != Node::Kind::Extension)
644+
switch (originalContext->getKind()) {
645+
case Node::Kind::Extension: {
646+
// For a type nested in an extension vs a type nested in a parent type
647+
// directly, the mangling trees looks like this:
648+
//
649+
// Class Class
650+
// Extension Structure
651+
// Module: ModExt vs. Module: ModBase
652+
// Structure Identifier: Outer
653+
// Module: ModBase Identifier: Inner
654+
// Identifier: Outer
655+
// Identifier: Inner
656+
//
657+
if (originalContext->getNumChildren() < 2 ||
658+
originalContext->getNumChildren() > 3) {
659+
assert(false && "Extension node should have 2 or 3 children.");
660+
return nullptr;
661+
}
662+
originalContext->replaceChild(1, parentNode);
663+
return originalContext;
664+
}
665+
case Node::Kind::Protocol: {
666+
// Nominal members of a protocol are mangled with a BoundGenericProtocol
667+
// wrapping the protocol, where the generic argument slot holds the
668+
// relevant Self type (see the matching comment in TypeDecoder's
669+
// BoundGenericProtocol case). For example, accessing the typealias A from
670+
// protocol P through a conforming type S produces:
671+
//
672+
// protocol P { typealias A = ... }
673+
// struct S : P {}
674+
// let x: S.A = ...
675+
//
676+
// BoundGenericProtocol
677+
// |
678+
// --> Protocol: P
679+
// |
680+
// --> TypeList:
681+
// |
682+
// --> Structure: S
683+
auto bgp = Dem.createNode(Node::Kind::BoundGenericProtocol);
684+
auto typeProto = Dem.createNode(Node::Kind::Type);
685+
typeProto->addChild(originalContext, Dem);
686+
bgp->addChild(typeProto, Dem);
687+
688+
auto typeList = Dem.createNode(Node::Kind::TypeList);
689+
auto typeSelf = Dem.createNode(Node::Kind::Type);
690+
typeSelf->addChild(parentNode, Dem);
691+
typeList->addChild(typeSelf, Dem);
692+
bgp->addChild(typeList, Dem);
693+
return bgp;
694+
}
695+
default:
653696
return parentNode;
654-
if (originalContext->getNumChildren() < 2 ||
655-
originalContext->getNumChildren() > 3) {
656-
assert(false && "Extension node should have 2 or 3 children.");
657-
return nullptr;
658697
}
659-
originalContext->replaceChild(1, parentNode);
660-
return originalContext;
661698
}
662699

663700
public:
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -lswiftSwiftReflectionTest %s -o %t/reflect_generic_typealias_in_extension
3+
// RUN: %target-codesign %t/reflect_generic_typealias_in_extension
4+
5+
// RUN: %target-run %target-swift-reflection-test %t/reflect_generic_typealias_in_extension | %FileCheck %s
6+
7+
// REQUIRES: reflection_test_support
8+
// REQUIRES: executable_test
9+
// UNSUPPORTED: use_os_stdlib
10+
// UNSUPPORTED: asan
11+
12+
import SwiftReflectionTest
13+
14+
struct Outer<T> {}
15+
16+
extension Outer {
17+
typealias Pair<U> = (T, U)
18+
}
19+
20+
class TypealiasHolder {
21+
var pair: Outer<Int>.Pair<String> = (1, "hi")
22+
}
23+
24+
reflect(object: TypealiasHolder())
25+
26+
// CHECK: Reflecting an object.
27+
// CHECK: Type reference:
28+
// CHECK: (class {{.*}}TypealiasHolder
29+
// CHECK: Type info:
30+
// CHECK: (class_instance
31+
// CHECK: (field name=pair
32+
// CHECK: (tuple
33+
// CHECK: (field offset=0
34+
// CHECK: (struct size=8
35+
// CHECK: (field name=_value
36+
// CHECK: (field offset=8
37+
// CHECK: (struct size=16
38+
// CHECK: (field name=_guts
39+
40+
doneReflecting()
41+
42+
// CHECK: Done.

0 commit comments

Comments
 (0)