Skip to content

Commit d73a2e0

Browse files
committed
[Runtime] Properly form generic arguments for metadata-to-demangle-tree.
When mapping from type metadata to a demangle tree, fill in the complete set of generic arguments. Most of the effort here is in dealing with extensions that involve same-type constraints on a generic parameter, e.g., extension Array where String == Element { } extension Dictionary where Key == Value { } In such cases, the metadata won’t contain generic arguments for every generic parameter. Rather, the generic arguments for non-key generic parameters will need to be computed based on the same-type requirements of the context. Do so, and eliminate the old hacks that put the generic arguments on the innermost type. We don’t need them any more. Part of rdar://problem/37170296.
1 parent 7896558 commit d73a2e0

File tree

6 files changed

+94
-50
lines changed

6 files changed

+94
-50
lines changed

stdlib/public/runtime/Demangle.cpp

Lines changed: 86 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ using namespace swift;
2828
Demangle::NodePointer
2929
swift::_buildDemanglingForContext(const ContextDescriptor *context,
3030
llvm::ArrayRef<NodePointer> demangledGenerics,
31-
bool concretizedGenerics,
3231
Demangle::Demangler &Dem) {
3332
unsigned usedDemangledGenerics = 0;
3433
NodePointer node = nullptr;
@@ -45,13 +44,6 @@ swift::_buildDemanglingForContext(const ContextDescriptor *context,
4544

4645
auto getGenericArgsTypeListForContext =
4746
[&](const ContextDescriptor *context) -> NodePointer {
48-
// ABI TODO: As a hack to maintain existing broken behavior,
49-
// if there were any generic arguments eliminated by same type
50-
// constraints, we don't mangle any of them into intermediate contexts,
51-
// and pile all of the non-concrete arguments into the innermost context.
52-
if (concretizedGenerics)
53-
return nullptr;
54-
5547
if (demangledGenerics.empty())
5648
return nullptr;
5749

@@ -73,7 +65,6 @@ swift::_buildDemanglingForContext(const ContextDescriptor *context,
7365
return genericArgsList;
7466
};
7567

76-
auto innermostComponent = descriptorPath.front();
7768
for (auto component : reversed(descriptorPath)) {
7869
switch (auto kind = component->getKind()) {
7970
case ContextDescriptorKind::Module: {
@@ -91,9 +82,6 @@ swift::_buildDemanglingForContext(const ContextDescriptor *context,
9182
selfType = selfType->getChild(0);
9283

9384
// Substitute in the generic arguments.
94-
// TODO: This kludge only kinda works if there are no same-type
95-
// constraints. We'd need to handle those correctly everywhere else too
96-
// though.
9785
auto genericArgsList = getGenericArgsTypeListForContext(component);
9886

9987
if (selfType->getKind() == Node::Kind::BoundGenericEnum
@@ -197,28 +185,6 @@ swift::_buildDemanglingForContext(const ContextDescriptor *context,
197185
node = genericNode;
198186
}
199187

200-
// ABI TODO: If there were concretized generic arguments, just pile
201-
// all the non-concretized generic arguments into the innermost context.
202-
if (concretizedGenerics
203-
&& !demangledGenerics.empty()
204-
&& component == innermostComponent) {
205-
auto unspecializedType = Dem.createNode(Node::Kind::Type);
206-
unspecializedType->addChild(node, Dem);
207-
208-
auto genericTypeList = Dem.createNode(Node::Kind::TypeList);
209-
for (auto arg : demangledGenerics) {
210-
if (!arg) continue;
211-
genericTypeList->addChild(arg, Dem);
212-
}
213-
214-
if (genericTypeList->getNumChildren() > 0) {
215-
auto genericNode = Dem.createNode(genericNodeKind);
216-
genericNode->addChild(unspecializedType, Dem);
217-
genericNode->addChild(genericTypeList, Dem);
218-
node = genericNode;
219-
}
220-
}
221-
222188
break;
223189
}
224190

@@ -312,8 +278,10 @@ _buildDemanglingForNominalType(const Metadata *type, Demangle::Demangler &Dem) {
312278

313279
// Demangle the generic arguments.
314280
std::vector<NodePointer> demangledGenerics;
315-
bool concretizedGenerics = false;
281+
316282
if (auto generics = description->getGenericContext()) {
283+
std::vector<const Metadata *> allGenericArgs;
284+
bool concretizedGenerics = false;
317285
auto genericArgs = description->getGenericArguments(type);
318286
for (auto param : generics->getGenericParams()) {
319287
switch (param.getKind()) {
@@ -332,10 +300,12 @@ _buildDemanglingForNominalType(const Metadata *type, Demangle::Demangler &Dem) {
332300
_swift_buildDemanglingForMetadata(paramType, Dem);
333301
if (!paramDemangling)
334302
return nullptr;
303+
allGenericArgs.push_back(paramType);
335304
demangledGenerics.push_back(paramDemangling);
336305
} else {
337306
// Leave a gap for us to fill in by looking at same type info.
338307
demangledGenerics.push_back(nullptr);
308+
allGenericArgs.push_back(nullptr);
339309
concretizedGenerics = true;
340310
}
341311
break;
@@ -358,11 +328,88 @@ _buildDemanglingForNominalType(const Metadata *type, Demangle::Demangler &Dem) {
358328

359329
// If we have concretized generic arguments, check for same type
360330
// requirements to get the argument values.
361-
// ABI TODO
331+
if (concretizedGenerics) {
332+
// Retrieve the mapping information needed for depth/index -> flat index.
333+
std::vector<unsigned> genericParamCounts;
334+
(void)_gatherGenericParameterCounts(description, genericParamCounts);
335+
336+
// Walk through the generic requirements to evaluate same-type
337+
// constraints that are needed to fill in missing generic arguments.
338+
for (const auto &req : generics->getGenericRequirements()) {
339+
// We only care about same-type constraints.
340+
if (req.Flags.getKind() != GenericRequirementKind::SameType)
341+
continue;
342+
343+
// Where the left-hand side is a generic parameter.
344+
if (req.Param.begin() != req.Param.end())
345+
continue;
346+
347+
// If we don't yet have an argument for this parameter, it's a
348+
// same-type-to-concrete constraint.
349+
unsigned lhsFlatIndex = req.Param.getRootParamIndex();
350+
if (!allGenericArgs[lhsFlatIndex]) {
351+
// Substitute into the right-hand side.
352+
auto genericArg =
353+
_getTypeByMangledName(req.getMangledTypeName(),
354+
[&](unsigned depth, unsigned index) {
355+
if (auto flatIndex = _depthIndexToFlatIndex(depth, index,
356+
genericParamCounts))
357+
return allGenericArgs[*flatIndex];
358+
359+
return (const Metadata *)nullptr;
360+
});
361+
if (!genericArg)
362+
return nullptr;
363+
364+
allGenericArgs[lhsFlatIndex] = genericArg;
365+
366+
// Form a demangling for this argument.
367+
auto argDemangling =
368+
_swift_buildDemanglingForMetadata(genericArg, Dem);
369+
if (!argDemangling)
370+
return nullptr;
371+
372+
demangledGenerics[lhsFlatIndex] = argDemangling;
373+
continue;
374+
}
375+
376+
// If we do have an argument for this parameter, it might be that
377+
// the right-hand side is itself a generic parameter, which means
378+
// we have a same-type constraint A == B where A is already filled in.
379+
Demangler demangler;
380+
NodePointer node = demangler.demangleType(req.getMangledTypeName());
381+
if (!node)
382+
continue;
383+
384+
// Find the flat index that the right-hand side refers to.
385+
if (node->getKind() == Demangle::Node::Kind::Type)
386+
node = node->getChild(0);
387+
if (node->getKind() != Demangle::Node::Kind::DependentGenericParamType)
388+
continue;
389+
390+
auto rhsFlatIndex =
391+
_depthIndexToFlatIndex(node->getChild(0)->getIndex(),
392+
node->getChild(1)->getIndex(),
393+
genericParamCounts);
394+
if (!rhsFlatIndex || *rhsFlatIndex > allGenericArgs.size())
395+
return nullptr;
396+
397+
if (allGenericArgs[*rhsFlatIndex] || !allGenericArgs[lhsFlatIndex])
398+
continue;
399+
400+
allGenericArgs[*rhsFlatIndex] = allGenericArgs[lhsFlatIndex];
401+
demangledGenerics[*rhsFlatIndex] = demangledGenerics[lhsFlatIndex];
402+
}
403+
404+
// Make sure that all of the demangled generics are filled in now.
405+
for (const auto node : demangledGenerics) {
406+
if (!node)
407+
return nullptr;
408+
}
409+
}
362410
}
363411

364-
return _buildDemanglingForContext(description, demangledGenerics,
365-
concretizedGenerics, Dem);
412+
return _buildDemanglingForContext(description, demangledGenerics, Dem);
366413
}
367414

368415
// Build a demangled type tree for a type.
@@ -449,8 +496,7 @@ swift::_swift_buildDemanglingForMetadata(const Metadata *type,
449496
#endif
450497

451498
auto protocolNode =
452-
_buildDemanglingForContext(protocol.getSwiftProtocol(), { }, false,
453-
Dem);
499+
_buildDemanglingForContext(protocol.getSwiftProtocol(), { }, Dem);
454500
if (!protocolNode)
455501
return nullptr;
456502

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ _findNominalTypeDescriptor(Demangle::NodePointer node,
527527
[&](const void *context) -> NodePointer {
528528
return _buildDemanglingForContext(
529529
(const ContextDescriptor *) context,
530-
{}, false, Dem);
530+
{}, Dem);
531531
});
532532

533533
// Look for an existing entry.
@@ -662,7 +662,7 @@ _findProtocolDescriptor(const Demangle::NodePointer &node,
662662
[&](const void *context) -> NodePointer {
663663
return _buildDemanglingForContext(
664664
(const ContextDescriptor *) context,
665-
{}, false, Dem);
665+
{}, Dem);
666666
});
667667

668668
// Look for an existing entry.

stdlib/public/runtime/Private.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,6 @@ class TypeInfo {
345345
Demangle::NodePointer
346346
_buildDemanglingForContext(const ContextDescriptor *context,
347347
llvm::ArrayRef<NodePointer> demangledGenerics,
348-
bool concretizedGenerics,
349348
Demangle::Demangler &Dem);
350349

351350
/// Symbolic reference resolver that produces the demangling tree for the
@@ -360,7 +359,7 @@ class TypeInfo {
360359
auto descriptor =
361360
(const ContextDescriptor *)detail::applyRelativeOffset(base, offset);
362361

363-
return _buildDemanglingForContext(descriptor, {}, false, Dem);
362+
return _buildDemanglingForContext(descriptor, {}, Dem);
364363
}
365364
};
366365

test/stdlib/Mirror.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1822,9 +1822,8 @@ mirrors.test("GenericNestedWithSameTypeConstraints") {
18221822
var output = ""
18231823
dump(value, to: &output)
18241824

1825-
// FIXME: The generic arguments are in the wrong place
18261825
let expected =
1827-
"▿ (extension in Mirror):Mirror.OuterTwoParams.InnerEqualParams<Mirror.ConformsToP1AndP2, Mirror.ConformsToP3>\n" +
1826+
"▿ (extension in Mirror):Mirror.OuterTwoParams<Mirror.ConformsToP1AndP2, Mirror.ConformsToP1AndP2>.InnerEqualParams<Mirror.ConformsToP3>\n" +
18281827
" - x: Mirror.ConformsToP1AndP2\n" +
18291828
" - y: Mirror.ConformsToP1AndP2\n" +
18301829
" - z: Mirror.ConformsToP3\n"

test/stdlib/RuntimeObjC.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -782,8 +782,8 @@ RuntimeClassNamesTestSuite.test("private class nested in same-type-constrained e
782782
let clas = unsafeBitCast(type(of: util), to: NSObject.self)
783783
// Name should look like _TtC1aP.*Inner
784784
let desc = clas.description
785-
expectEqual(desc.prefix(7), "_TtC1aP")
786-
expectEqual(desc.suffix(5), "Inner")
785+
expectEqual("_TtGC1a", desc.prefix(7))
786+
expectEqual("Data_", desc.suffix(5))
787787
}
788788

789789
runAllTests()

test/stdlib/TypeName.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,9 @@ extension SomeOuterGenericClass where T == Int {
203203
}
204204

205205
TypeNameTests.test("NestedInConstrainedExtension") {
206-
expectEqual("(extension in main):main.SomeOuterGenericClass.AnotherInnerStruct",
206+
expectEqual("(extension in main):main.SomeOuterGenericClass<Swift.Int>.AnotherInnerStruct",
207207
_typeName(SomeOuterGenericClass<Int>.AnotherInnerStruct.self));
208-
expectEqual("(extension in main):main.SomeOuterGenericClass.AnotherInnerGenericStruct<Swift.String>",
208+
expectEqual("(extension in main):main.SomeOuterGenericClass<Swift.Int>.AnotherInnerGenericStruct<Swift.String>",
209209
_typeName(SomeOuterGenericClass<Int>.AnotherInnerGenericStruct<String>.self));
210210
}
211211

0 commit comments

Comments
 (0)