Skip to content

Commit 5e232de

Browse files
committed
[Mangling] Mangle retroactive conformances using the new conformance mangling
Change the retroactive conformance mangling to use the new any-protocol-conformance mangling, which maintains more information about concrete conformances. Specifically, it maintains conformance information for conditional requirements. It also uses the protocol-conformance-ref production that will eventually allow symbolic references to protocol conformance descriptors. While here, extend the “is retroactive” check during mangling to look for retroactive conformances in the conditional requirements of a conformance. The immediate conformance might not be retroactive, but its specialization might depend on a retroactive conformance. Mangle these as “retroactive”, so we can correctly reconstruct the exact type.
1 parent 1efe2bc commit 5e232de

File tree

8 files changed

+88
-31
lines changed

8 files changed

+88
-31
lines changed

docs/ABI/Mangling.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,7 @@ from any character in a ``<GENERIC-PARAM-COUNT>``.
717717

718718
::
719719

720-
retroactive-conformance ::= protocol-conformance 'g' INDEX
720+
retroactive-conformance ::= any-protocol-conformance 'g' INDEX
721721

722722
When a protocol conformance used to satisfy one of a bound generic type's
723723
generic requirements is retroactive (i.e., it is specified in a module other

lib/AST/ASTMangler.cpp

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,48 @@ void ASTMangler::appendBoundGenericArgs(Type type, bool &isFirstArgList) {
11121112
}
11131113
}
11141114

1115+
/// Determine whether the given protocol conformance is itself retroactive,
1116+
/// meaning that there might be multiple conflicting conformances of the
1117+
/// same type to the same protocol.
1118+
static bool isRetroactiveConformance(
1119+
const NormalProtocolConformance *conformance) {
1120+
/// Non-retroactive conformances are... never retroactive.
1121+
if (!conformance->isRetroactive())
1122+
return false;
1123+
1124+
/// Synthesized non-unique conformances all get collapsed together at run
1125+
/// time.
1126+
if (conformance->isSynthesizedNonUnique())
1127+
return false;
1128+
1129+
/// Objective-C protocol conformances don't have identity.
1130+
if (conformance->getProtocol()->isObjC())
1131+
return false;
1132+
1133+
return true;
1134+
}
1135+
1136+
/// Determine whether the given protocol conformance contains a retroactive
1137+
/// protocol conformance anywhere in it.
1138+
static bool containsRetroactiveConformance(
1139+
const ProtocolConformance *conformance,
1140+
ModuleDecl *module) {
1141+
// If the root conformance is retroactive, it's retroactive.
1142+
if (isRetroactiveConformance(conformance->getRootNormalConformance()))
1143+
return true;
1144+
1145+
// If any of the substitutions used to form this conformance are retroactive,
1146+
// it's retroactive.
1147+
auto subMap = conformance->getSubstitutions(module);
1148+
for (auto conformance : subMap.getConformances()) {
1149+
if (conformance.isConcrete() &&
1150+
containsRetroactiveConformance(conformance.getConcrete(), module))
1151+
return true;
1152+
}
1153+
1154+
return false;
1155+
}
1156+
11151157
void ASTMangler::appendRetroactiveConformances(Type type) {
11161158
auto nominal = type->getAnyNominal();
11171159
if (!nominal) return;
@@ -1124,28 +1166,20 @@ void ASTMangler::appendRetroactiveConformances(Type type) {
11241166
if (subMap.empty()) return;
11251167

11261168
unsigned numProtocolRequirements = 0;
1127-
for (const auto &req: genericSig->getRequirements()) {
1128-
if (req.getKind() != RequirementKind::Conformance)
1129-
continue;
1130-
1169+
for (auto conformance : subMap.getConformances()) {
11311170
SWIFT_DEFER {
11321171
++numProtocolRequirements;
11331172
};
11341173

1135-
// Fast path: we're in the module of the protocol.
1136-
auto proto = req.getSecondType()->castTo<ProtocolType>()->getDecl();
1137-
if (proto->getModuleContext() == module)
1174+
// Ignore abstract conformances.
1175+
if (!conformance.isConcrete())
11381176
continue;
11391177

1140-
auto conformance =
1141-
subMap.lookupConformance(req.getFirstType()->getCanonicalType(), proto);
1142-
if (!conformance || !conformance->isConcrete()) continue;
1143-
1144-
auto normal = conformance->getConcrete()->getRootNormalConformance();
1145-
if (!normal->isRetroactive() || normal->isSynthesizedNonUnique())
1178+
// Skip non-retroactive conformances.
1179+
if (!containsRetroactiveConformance(conformance.getConcrete(), module))
11461180
continue;
11471181

1148-
appendProtocolConformance(normal);
1182+
appendConcreteProtocolConformance(conformance.getConcrete());
11491183
appendOperator("g", Index(numProtocolRequirements));
11501184
}
11511185
}

lib/Demangling/Demangler.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,13 +1397,18 @@ NodePointer Demangler::demangleDependentProtocolConformanceAssociated() {
13971397
}
13981398

13991399
NodePointer Demangler::demangleRetroactiveConformance() {
1400-
NodePointer Index = demangleIndexAsNode();
1401-
NodePointer Conformance = popProtocolConformance();
1402-
if (!Index || !Conformance)
1400+
int index = demangleIndex();
1401+
if (index < 0)
1402+
return nullptr;
1403+
1404+
NodePointer conformance = popAnyProtocolConformance();
1405+
if (!conformance)
14031406
return nullptr;
14041407

1405-
return createWithChildren(Node::Kind::RetroactiveConformance,
1406-
Index, Conformance);
1408+
auto retroactiveConformance =
1409+
createNode(Node::Kind::RetroactiveConformance, index);
1410+
retroactiveConformance->addChild(conformance, *this);
1411+
return retroactiveConformance;
14071412
}
14081413

14091414
NodePointer Demangler::demangleBoundGenericType() {

lib/Demangling/Remangler.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,9 +1607,9 @@ void Remangler::mangleProtocol(Node *node) {
16071607
}
16081608

16091609
void Remangler::mangleRetroactiveConformance(Node *node) {
1610-
mangleProtocolConformance(node->getChild(1));
1610+
mangleAnyProtocolConformance(node->getChild(0));
16111611
Buffer << 'g';
1612-
mangleIndex(node->getChild(0)->getIndex());
1612+
mangleIndex(node->getIndex());
16131613
}
16141614

16151615
void Remangler::mangleProtocolConformance(Node *node) {

test/Demangle/Inputs/manglings.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ _T0So13GenericOptionas8HashableSCsACP9hashValueSivgTW ---> {T:} protocol witness
301301
_T0So11CrappyColorVs16RawRepresentableSCMA ---> reflection metadata associated type descriptor __C.CrappyColor : Swift.RawRepresentable in __C_Synthesized
302302
$S28protocol_conformance_records15NativeValueTypeVAA8RuncibleAAMc ---> protocol conformance descriptor for protocol_conformance_records.NativeValueType : protocol_conformance_records.Runcible in protocol_conformance_records
303303
$SSC9SomeErrorLeVD ---> __C_Synthesized.related decl 'e' for SomeError
304-
$S20mangling_retroactive5test0yyAA1ZVy12RetroactiveB1XVSiAE1YVAG0D1A1PAAg_AiJ1QAAg1_GF ---> mangling_retroactive.test0(mangling_retroactive.Z<RetroactiveB.X, Swift.Int, RetroactiveB.Y>) -> ()
304+
$s20mangling_retroactive5test1yyAA2Z2V5InnerVy12RetroactiveB1XV_AG1YVAI0F1A1PAAyHCg_AkL1QAAyHCg0_GF ---> mangling_retroactive.test1(mangling_retroactive.Z2<RetroactiveB.X>.Inner<RetroactiveB.Y>) -> ()
305305
_T0LiteralAByxGxd_tcfC ---> _T0LiteralAByxGxd_tcfC
306306
_T0XZ ---> _T0XZ
307307
_TTSf0os___TFVs17_LegacyStringCore15_invariantCheckfT_T_ ---> function signature specialization <Arg[0] = Guaranteed To Owned and Exploded> of Swift._LegacyStringCore._invariantCheck() -> ()
@@ -316,7 +316,6 @@ _$S3BBBBf0602365061_ ---> _$S3BBBBf0602365061_
316316
_$S3BBBBi0602365061_ ---> _$S3BBBBi0602365061_
317317
_$S3BBBBv0602365061_ ---> _$S3BBBBv0602365061_
318318
_T0lxxxmmmTk ---> _T0lxxxmmmTk
319-
$S11TestSupport20MockPackageContainerC12dependenciesSDySSSaySS9container_0D5Graph0dE10ConstraintV11RequirementOySS_SSAF0dE10IdentifierAAg_G11requirementtGGvg ---> TestSupport.MockPackageContainer.dependencies.getter : [Swift.String : [(container: Swift.String, requirement: PackageGraph.PackageContainerConstraint<Swift.String>.Requirement)]]
320319
$S3nix8MystructV1xACyxGx_tcfc7MyaliasL_ayx__GD ---> Myalias #1 in nix.Mystruct<A>.init(x: A) -> nix.Mystruct<A>
321320
$S3nix7MyclassCfd7MyaliasL_ayx__GD ---> Myalias #1 in nix.Myclass<A>.deinit
322321
$S3nix8MystructVyS2icig7MyaliasL_ayx__GD ---> Myalias #1 in nix.Mystruct<A>.subscript.getter : (Swift.Int) -> Swift.Int

test/IRGen/objc_bridge.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ import Foundation
8888
// CHECK: { i8*, i8*, i8* } {
8989
// CHECK: i8* getelementptr inbounds ([11 x i8], [11 x i8]* @"\01L_selector_data(acceptSet:)", i64 0, i64 0),
9090
// CHECK: i8* getelementptr inbounds ([11 x i8], [11 x i8]* @{{[0-9]+}}, i64 0, i64 0),
91-
// CHECK: i8* bitcast (void (%3*, i8*, %4*)* @"$s11objc_bridge3BasC9acceptSetyyShyACSo8NSObjectCSH10ObjectiveCg_GFTo" to i8*)
91+
// CHECK: i8* bitcast (void (%3*, i8*, %4*)* @"$s11objc_bridge3BasC9acceptSetyyShyA2CSH10ObjectiveCyHCg_GFTo" to i8*)
9292
// CHECK: }
9393
// CHECK: { i8*, i8*, i8* } {
9494
// CHECK: i8* getelementptr inbounds ([14 x i8], [14 x i8]* @"\01L_selector_data(.cxx_destruct)", i64 0, i64 0),

test/SILGen/mangling_retroactive.swift

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,31 @@ struct Z<T: P, U: Hashable, V: Q> { }
1212
extension X: P { } // retroactive
1313
extension Y: Q { } // retroactive
1414

15-
// CHECK: sil hidden @$s20mangling_retroactive5test0yyAA1ZVy12RetroactiveB1XVSiAE1YVAG0D1A1PAAg_AiJ1QAAg1_GF
15+
// CHECK: sil hidden @$s20mangling_retroactive5test0yyAA1ZVy12RetroactiveB1XVSiAE1YVAG0D1A1PAAyHCg_AiJ1QAAyHCg1_GF
1616
func test0(_: Z<X, Int, Y>) { }
1717

1818
struct Z2<T: P> {
1919
struct Inner<V: Q> { }
2020
}
2121

22-
// CHECK: sil hidden @$s20mangling_retroactive5test1yyAA2Z2V5InnerVy12RetroactiveB1XV_AG1YVAI0F1A1PAAg_AkL1QAAg0_GF
22+
// CHECK: sil hidden @$s20mangling_retroactive5test1yyAA2Z2V5InnerVy12RetroactiveB1XV_AG1YVAI0F1A1PAAyHCg_AkL1QAAyHCg0_GF
2323
func test1(_: Z2<X>.Inner<Y>) { }
24+
25+
extension X: Hashable {
26+
public static func ==(lhs: X, rhs: X) -> Bool { return true }
27+
public func hash(into hasher: inout Hasher) { }
28+
}
29+
extension Y: Hashable {
30+
public static func ==(lhs: Y, rhs: Y) -> Bool { return true }
31+
public func hash(into hasher: inout Hasher) { }
32+
}
33+
34+
extension Z: Equatable where T: Hashable, V: Equatable {
35+
static func ==(lhs: Z, rhs: Z) -> Bool { return true }
36+
}
37+
38+
struct RequiresEquatable<T: Equatable> { }
39+
40+
// Conditional requirement involves retroactive conformances.
41+
// CHECK: sil hidden @$s20mangling_retroactive5test2yyAA17RequiresEquatableVyAA1ZVy12RetroactiveB1XVSiAG1YVAI0F1A1PAAyHCg_AkL1QAAyHCg1_GAOSQAISHAAyHC_AKSQAAyHCHCg_GF
42+
func test2(_: RequiresEquatable<Z<X, Int, Y>>) { }

test/SILGen/objc_dictionary_bridging.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ import gizmo
5353
@objc var property: Dictionary<Foo, Foo> = [:]
5454

5555
// Property getter
56-
// CHECK-LABEL: sil hidden [thunk] @$s24objc_dictionary_bridging3FooC8propertySDyA2CSo8NSObjectCSH10Foundationg_GvgTo : $@convention(objc_method) (Foo) -> @autoreleased NSDictionary
56+
// CHECK-LABEL: sil hidden [thunk] @$s24objc_dictionary_bridging3FooC8propertySDyA3CSH10FoundationyHCg_GvgTo : $@convention(objc_method) (Foo) -> @autoreleased NSDictionary
5757
// @$s24objc_dictionary_bridging3FooC8propertySDyA2CSo8NSObjectCSH10Foundationg_Gvpfi
5858
// CHECK: bb0([[SELF:%[0-9]+]] : @unowned $Foo):
5959
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
6060
// CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
61-
// CHECK: [[GETTER:%[0-9]+]] = function_ref @$s24objc_dictionary_bridging3FooC8propertySDyA2CSo8NSObjectCSH10Foundationg_Gvg : $@convention(method) (@guaranteed Foo) -> @owned Dictionary<Foo, Foo>
61+
// CHECK: [[GETTER:%[0-9]+]] = function_ref @$s24objc_dictionary_bridging3FooC8propertySDyA3CSH10FoundationyHCg_Gvg : $@convention(method) (@guaranteed Foo) -> @owned Dictionary<Foo, Foo>
6262
// CHECK: [[DICT:%[0-9]+]] = apply [[GETTER]]([[BORROWED_SELF_COPY]]) : $@convention(method) (@guaranteed Foo) -> @owned Dictionary<Foo, Foo>
6363
// CHECK: end_borrow [[BORROWED_SELF_COPY]]
6464
// CHECK: destroy_value [[SELF_COPY]]
@@ -71,7 +71,7 @@ import gizmo
7171
// CHECK: } // end sil function
7272

7373
// Property setter
74-
// CHECK-LABEL: sil hidden [thunk] @$s24objc_dictionary_bridging3FooC8propertySDyA2CSo8NSObjectCSH10Foundationg_GvsTo : $@convention(objc_method) (NSDictionary, Foo) -> ()
74+
// CHECK-LABEL: sil hidden [thunk] @$s24objc_dictionary_bridging3FooC8propertySDyA3CSH10FoundationyHCg_GvsTo : $@convention(objc_method) (NSDictionary, Foo) -> ()
7575
// CHECK: bb0([[NSDICT:%[0-9]+]] : @unowned $NSDictionary, [[SELF:%[0-9]+]] : @unowned $Foo):
7676
// CHECK: [[NSDICT_COPY:%.*]] = copy_value [[NSDICT]]
7777
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
@@ -81,7 +81,7 @@ import gizmo
8181
// CHECK: [[DICT:%[0-9]+]] = apply [[CONVERTER]]<Foo, Foo>([[OPT_NSDICT]], [[DICT_META]])
8282

8383
// CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
84-
// CHECK: [[SETTER:%[0-9]+]] = function_ref @$s24objc_dictionary_bridging3FooC8propertySDyA2CSo8NSObjectCSH10Foundationg_Gvs : $@convention(method) (@owned Dictionary<Foo, Foo>, @guaranteed Foo) -> ()
84+
// CHECK: [[SETTER:%[0-9]+]] = function_ref @$s24objc_dictionary_bridging3FooC8propertySDyA3CSH10FoundationyHCg_Gvs : $@convention(method) (@owned Dictionary<Foo, Foo>, @guaranteed Foo) -> ()
8585
// CHECK: [[RESULT:%[0-9]+]] = apply [[SETTER]]([[DICT]], [[BORROWED_SELF_COPY]]) : $@convention(method) (@owned Dictionary<Foo, Foo>, @guaranteed Foo) -> ()
8686
// CHECK: end_borrow [[BORROWED_SELF_COPY]]
8787
// CHECK: destroy_value [[SELF_COPY]]

0 commit comments

Comments
 (0)