Skip to content

Commit bf2dca3

Browse files
authored
Merge pull request #16541 from DougGregor/demangle-to-metadata-ext-4.2
2 parents b2a75e2 + 2c8db0f commit bf2dca3

File tree

5 files changed

+181
-19
lines changed

5 files changed

+181
-19
lines changed

include/swift/Demangling/TypeDecoder.h

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ namespace Demangle {
2929

3030
/// Strip generic arguments from the "spine" of a context node, producing a
3131
/// bare context to be used in (e.g.) forming nominal type descriptors.
32-
NodePointer stripGenericArgsFromContextNode(const NodePointer &node,
32+
NodePointer stripGenericArgsFromContextNode(NodePointer node,
3333
NodeFactory &factory);
3434

3535
/// Describe a function parameter, parameterized on the type
@@ -482,22 +482,30 @@ class TypeDecoder {
482482
if (node->getNumChildren() < 2)
483483
return false;
484484

485-
auto moduleOrParentType = node->getChild(0);
485+
auto parentContext = node->getChild(0);
486486

487487
// Nested types are handled a bit funny here because a
488488
// nominal typeref always stores its full mangled name,
489489
// in addition to a reference to the parent type. The
490490
// mangled name already includes the module and parent
491491
// types, if any.
492492
nominalNode = node;
493-
if (moduleOrParentType->getKind() != NodeKind::Module) {
494-
parent = decodeMangledType(moduleOrParentType);
495-
if (!parent) return false;
496-
493+
switch (parentContext->getKind()) {
494+
case Node::Kind::Module:
495+
break;
496+
case Node::Kind::Extension:
497+
// Decode the type being extended.
498+
if (parentContext->getNumChildren() < 2)
499+
return false;
500+
parentContext = parentContext->getChild(1);
501+
LLVM_FALLTHROUGH;
502+
default:
503+
parent = decodeMangledType(parentContext);
497504
// Remove any generic arguments from the context node, producing a
498-
// node that reference the nominal type declaration.
505+
// node that references the nominal type declaration.
499506
nominalNode =
500507
stripGenericArgsFromContextNode(node, Builder.getNodeFactory());
508+
break;
501509
}
502510
}
503511
typeDecl = Builder.createNominalTypeDecl(nominalNode);
@@ -507,7 +515,7 @@ class TypeDecoder {
507515
}
508516

509517
BuiltProtocolDecl decodeMangledProtocolType(
510-
const Demangle::NodePointer &node) {
518+
const Demangle::NodePointer &node) {
511519
if (node->getKind() == NodeKind::Type)
512520
return decodeMangledProtocolType(node->getChild(0));
513521

lib/Demangling/Demangler.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,8 @@ bool swift::Demangle::isStruct(llvm::StringRef mangledName) {
264264
return isStructNode(Dem.demangleType(mangledName));
265265
}
266266

267-
namespace swift {
268-
namespace Demangle {
267+
using namespace swift;
268+
using namespace Demangle;
269269

270270
//////////////////////////////////
271271
// Node member functions //
@@ -2682,6 +2682,3 @@ NodePointer Demangler::demangleObjCTypeName() {
26822682

26832683
return Global;
26842684
}
2685-
2686-
} // namespace Demangle
2687-
} // namespace swift

lib/Demangling/TypeDecoder.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
using namespace swift;
1919
using namespace Demangle;
2020

21-
NodePointer Demangle::stripGenericArgsFromContextNode(const NodePointer &node,
21+
NodePointer Demangle::stripGenericArgsFromContextNode(NodePointer node,
2222
NodeFactory &factory) {
2323
switch (node->getKind()) {
2424
case Demangle::Node::Kind::BoundGenericClass:
@@ -53,6 +53,23 @@ NodePointer Demangle::stripGenericArgsFromContextNode(const NodePointer &node,
5353
newNode->addChild(node->getChild(i), factory);
5454
return newNode;
5555
}
56+
57+
case Demangle::Node::Kind::Extension: {
58+
// Strip generic arguments from the extended type.
59+
if (node->getNumChildren() < 2)
60+
return node;
61+
62+
auto newExtended = stripGenericArgsFromContextNode(node->getChild(1),
63+
factory);
64+
if (newExtended == node->getChild(1)) return node;
65+
66+
auto newNode = factory.createNode(Node::Kind::Extension);
67+
newNode->addChild(node->getChild(0), factory);
68+
newNode->addChild(newExtended, factory);
69+
if (node->getNumChildren() == 3)
70+
newNode->addChild(node->getChild(2), factory);
71+
return newNode;
72+
}
5673

5774
case Demangle::Node::Kind::Module:
5875
// Modules terminate the recursion.

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,17 @@ swift::swift_registerTypeMetadataRecords(const TypeMetadataRecord *begin,
153153
_registerTypeMetadataRecords(T, begin, end);
154154
}
155155

156+
static const TypeContextDescriptor *
157+
_findNominalTypeDescriptor(Demangle::NodePointer node,
158+
Demangle::Demangler &Dem);
159+
156160
bool
157161
swift::_contextDescriptorMatchesMangling(const ContextDescriptor *context,
158162
Demangle::NodePointer node) {
159-
if (node->getKind() == Demangle::Node::Kind::Type)
160-
node = node->getChild(0);
161-
162163
while (context) {
164+
if (node->getKind() == Demangle::Node::Kind::Type)
165+
node = node->getChild(0);
166+
163167
// We can directly match symbolic references to the current context.
164168
if (node && node->getKind() == Demangle::Node::Kind::SymbolicReference) {
165169
if (equalContexts(context, reinterpret_cast<const ContextDescriptor *>(
@@ -182,8 +186,56 @@ swift::_contextDescriptorMatchesMangling(const ContextDescriptor *context,
182186
}
183187

184188
case ContextDescriptorKind::Extension: {
185-
// TODO: Check whether the extension context constraints match.
186-
return false;
189+
auto extension = cast<ExtensionContextDescriptor>(context);
190+
191+
// Check whether the extension context matches the mangled context.
192+
if (node->getKind() != Demangle::Node::Kind::Extension)
193+
return false;
194+
if (node->getNumChildren() < 2)
195+
return false;
196+
197+
// Check that the context being extended matches as well.
198+
auto extendedContextNode = node->getChild(1);
199+
auto extendedContextMangledName = extension->getMangledExtendedContext();
200+
auto demangler = getDemanglerForRuntimeTypeResolution();
201+
auto extendedContextDemangled =
202+
demangler.demangleType(extendedContextMangledName);
203+
if (!extendedContextDemangled)
204+
return false;
205+
if (extendedContextDemangled->getKind() == Node::Kind::Type) {
206+
if (extendedContextDemangled->getNumChildren() < 1)
207+
return false;
208+
extendedContextDemangled = extendedContextDemangled->getChild(0);
209+
}
210+
extendedContextDemangled =
211+
stripGenericArgsFromContextNode(extendedContextDemangled, demangler);
212+
213+
auto extendedDescriptorFromNode =
214+
_findNominalTypeDescriptor(extendedContextNode, demangler);
215+
auto extendedDescriptorFromDemangled =
216+
_findNominalTypeDescriptor(extendedContextDemangled, demangler);
217+
218+
if (!extendedDescriptorFromNode || !extendedDescriptorFromDemangled ||
219+
!equalContexts(extendedDescriptorFromNode,
220+
extendedDescriptorFromDemangled))
221+
return false;
222+
223+
// Check whether the generic signature of the extension matches the
224+
// mangled constraints, if any.
225+
226+
if (node->getNumChildren() >= 3) {
227+
// NB: If we ever support extensions with independent generic arguments
228+
// like `extension <T> Array where Element == Optional<T>`, we'd need
229+
// to look at the mangled context name to match up generic arguments.
230+
// That would probably need a new extension mangling form, though.
231+
232+
// TODO
233+
}
234+
235+
// The parent context of the extension should match in the mangling and
236+
// context descriptor.
237+
node = node->getChild(0);
238+
break;
187239
}
188240

189241
default:

test/Runtime/demangleToMetadata.swift

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,5 +333,93 @@ DemangleToMetadataTests.test("superclass requirements") {
333333
expectNil(_typeByMangledName("4main4SG10VyAA2C3CG"))
334334
}
335335

336+
//
337+
// Extensions of external types, and constrained extensions
338+
//
339+
340+
struct SG11<T> {}
341+
342+
extension Dictionary {
343+
struct Inner<V: P1> {}
344+
}
345+
346+
extension SG11 where T: P1 {
347+
struct InnerTConformsToP1<U: P2> { }
348+
}
349+
350+
extension SG11.InnerTConformsToP1 where U: P3 {
351+
struct InnermostUConformsToP3<V: P4> { }
352+
}
353+
354+
struct ConformsToP2AndP3: P2, P3 { }
355+
356+
DemangleToMetadataTests.test("Nested types in extensions") {
357+
expectEqual(
358+
Dictionary<String, Int>.Inner<ConformsToP1>.self,
359+
_typeByMangledName("s10DictionaryV4mainE5InnerVySSSi_AC12ConformsToP1VG")!)
360+
expectEqual(
361+
SG11<ConformsToP1>.InnerTConformsToP1<ConformsToP2>.self,
362+
_typeByMangledName("4main4SG11VA2A2P1RzlE016InnerTConformsToC0VyAA08ConformsfC0V_AA0gF2P2VG")!)
363+
expectEqual(
364+
SG11<ConformsToP1>.InnerTConformsToP1<ConformsToP2AndP3>
365+
.InnermostUConformsToP3<ConformsToP4a>.self,
366+
_typeByMangledName("4main4SG11VA2A2P1RzlE016InnerTConformsToC0VA2A2P3Rd__rlE018InnermostUConformsfG0VyAA08ConformsfC0V_AA0jf5P2AndG0V_AA0jF3P4aVG")!)
367+
368+
// Failure case: Dictionary's outer `Key: Hashable` constraint not sastified
369+
// TODO: expectNil(_typeByMangledName("s10DictionaryV4mainE5InnerVyAC12ConformsToP1VSi_AC12ConformsToP1VG"))
370+
// Failure case: Dictionary's inner `V: P1` constraint not satisfied
371+
expectNil(_typeByMangledName("s10DictionaryV4mainE5InnerVySSSi_AC12ConformsToP2VG"))
372+
373+
// Failure case: SG11's outer `T: P1` constraint not satisfied
374+
expectNil(_typeByMangledName("4main4SG11VA2A2P1RzlE016InnerTConformsToC0VyAA08ConformsF2P2V_AHGMa"))
375+
// Failure case: SG11's inner `U: P2` constraint not satisfied
376+
expectNil(_typeByMangledName("4main4SG11VA2A2P1RzlE016InnerTConformsToC0VyAA08ConformsfC0V_AHGMa"))
377+
378+
// TODO: Failure case: InnermostUConformsToP3's 'U: P3' constraint not satisfied
379+
380+
}
381+
382+
//
383+
// Nested types in same-type-constrained extensions
384+
//
385+
386+
/* TODO
387+
388+
struct SG12<T: P1, U: P2> {}
389+
390+
struct ConformsToP1AndP2 : P1, P2 { }
391+
392+
extension SG12 where U == T {
393+
struct InnerTEqualsU<V: P3> { }
394+
}
395+
396+
extension SG12 where T == ConformsToP1 {
397+
struct InnerTEqualsConformsToP1<V: P3> { }
398+
}
399+
400+
extension SG12 where U == ConformsToP2 {
401+
struct InnerUEqualsConformsToP2<V: P3> { }
402+
}
403+
404+
DemangleToMetadataTests.test("Nested types in same-type-constrained extensions") {
405+
expectEqual(
406+
SG12<ConformsToP1AndP2, ConformsToP1AndP2>.InnerTEqualsU<ConformsToP3>.self,
407+
_typeByMangledName("4main4SG12VA2A2P2Rzq_RszrlE13InnerTEqualsUVyAA015ConformsToP1AndC0VAH_AA0fG2P3VG")!)
408+
expectEqual(
409+
SG12<ConformsToP1, ConformsToP2>.InnerTEqualsConformsToP1<ConformsToP3>.self,
410+
_typeByMangledName("4main4SG12VA2A12ConformsToP1VRszrlE012InnerTEqualscdE0VyAeA0cD2P2V_AA0cD2P3VG")!)
411+
expectEqual(
412+
SG12<ConformsToP1, ConformsToP2>.InnerUEqualsConformsToP2<ConformsToP3>.self,
413+
_typeByMangledName("4main4SG12VA2A12ConformsToP2VRs_rlE012InnerUEqualscdE0VyAA0cD2P1VAE_AA0cD2P3VG")!)
414+
415+
// TODO: Cases where mangled name doesn't match constraints
416+
// T != U in InnerTEqualsU
417+
// V !: P3 in InnerTEqualsU
418+
// T != ConformsToP1 in InnerTEqualsConformsToP1
419+
// V !: P3 in InnerTEqualsConformsToP1
420+
}
421+
422+
*/
423+
336424
runAllTests()
337425

0 commit comments

Comments
 (0)