Skip to content

Commit 6a355ae

Browse files
authored
Merge pull request #39812 from DougGregor/marker-protocol-runtime-type-metadata-5.5
Don't emit marker protocols into runtime type metadata.
2 parents e61f8f1 + cb3fe3d commit 6a355ae

File tree

7 files changed

+103
-20
lines changed

7 files changed

+103
-20
lines changed

include/swift/AST/ASTMangler.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ class ASTMangler : public Mangler {
6161
/// concurrency library.
6262
bool AllowConcurrencyStandardSubstitutions = true;
6363

64+
/// If enabled, marker protocols can be encoded in the mangled name.
65+
bool AllowMarkerProtocols = true;
66+
6467
public:
6568
using SymbolicReferent = llvm::PointerUnion<const NominalTypeDecl *,
6669
const OpaqueTypeDecl *>;
@@ -294,6 +297,9 @@ class ASTMangler : public Mangler {
294297
static const clang::NamedDecl *
295298
getClangDeclForMangling(const ValueDecl *decl);
296299

300+
void appendExistentialLayout(
301+
const ExistentialLayout &layout, const ValueDecl *forDecl);
302+
297303
protected:
298304

299305
void appendSymbolKind(SymbolKind SKind);

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5827,6 +5827,9 @@ ERROR(marker_protocol_requirement, none,
58275827
ERROR(marker_protocol_inherit_nonmarker, none,
58285828
"marker protocol %0 cannot inherit non-marker protocol %1",
58295829
(DeclName, DeclName))
5830+
ERROR(marker_protocol_inherit_class, none,
5831+
"marker protocol %0 cannot inherit class %1",
5832+
(DeclName, Type))
58305833
ERROR(marker_protocol_cast,none,
58315834
"marker protocol %0 cannot be used in a conditional cast", (DeclName))
58325835
ERROR(marker_protocol_conditional_conformance,none,

lib/AST/ASTMangler.cpp

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,40 @@ void ASTMangler::appendOpaqueDeclName(const OpaqueTypeDecl *opaqueDecl) {
10201020
}
10211021
}
10221022

1023+
void ASTMangler::appendExistentialLayout(
1024+
const ExistentialLayout &layout, const ValueDecl *forDecl) {
1025+
bool First = true;
1026+
bool DroppedRequiresClass = false;
1027+
bool SawRequiresClass = false;
1028+
for (Type protoTy : layout.getProtocols()) {
1029+
auto proto = protoTy->castTo<ProtocolType>()->getDecl();
1030+
// If we aren't allowed to emit marker protocols, suppress them here.
1031+
if (!AllowMarkerProtocols && proto->isMarkerProtocol()) {
1032+
if (proto->requiresClass())
1033+
DroppedRequiresClass = true;
1034+
1035+
continue;
1036+
}
1037+
1038+
if (proto->requiresClass())
1039+
SawRequiresClass = true;
1040+
1041+
appendProtocolName(protoTy->castTo<ProtocolType>()->getDecl());
1042+
appendListSeparator(First);
1043+
}
1044+
if (First)
1045+
appendOperator("y");
1046+
1047+
if (auto superclass = layout.explicitSuperclass) {
1048+
appendType(superclass, forDecl);
1049+
return appendOperator("Xc");
1050+
} else if (layout.hasExplicitAnyObject ||
1051+
(DroppedRequiresClass && !SawRequiresClass)) {
1052+
return appendOperator("Xl");
1053+
}
1054+
return appendOperator("p");
1055+
}
1056+
10231057
/// Mangle a type into the buffer.
10241058
///
10251059
void ASTMangler::appendType(Type type, const ValueDecl *forDecl) {
@@ -1189,31 +1223,15 @@ void ASTMangler::appendType(Type type, const ValueDecl *forDecl) {
11891223
return appendOperator("t");
11901224

11911225
case TypeKind::Protocol: {
1192-
bool First = true;
1193-
appendProtocolName(cast<ProtocolType>(tybase)->getDecl());
1194-
appendListSeparator(First);
1195-
return appendOperator("p");
1226+
return appendExistentialLayout(
1227+
ExistentialLayout(cast<ProtocolType>(tybase)), forDecl);
11961228
}
11971229

11981230
case TypeKind::ProtocolComposition: {
11991231
// We mangle ProtocolType and ProtocolCompositionType using the
12001232
// same production:
1201-
bool First = true;
12021233
auto layout = type->getExistentialLayout();
1203-
for (Type protoTy : layout.getProtocols()) {
1204-
appendProtocolName(protoTy->castTo<ProtocolType>()->getDecl());
1205-
appendListSeparator(First);
1206-
}
1207-
if (First)
1208-
appendOperator("y");
1209-
1210-
if (auto superclass = layout.explicitSuperclass) {
1211-
appendType(superclass, forDecl);
1212-
return appendOperator("Xc");
1213-
} else if (layout.hasExplicitAnyObject) {
1214-
return appendOperator("Xl");
1215-
}
1216-
return appendOperator("p");
1234+
return appendExistentialLayout(layout, forDecl);
12171235
}
12181236

12191237
case TypeKind::UnboundGeneric:
@@ -2196,6 +2214,8 @@ void ASTMangler::appendModule(const ModuleDecl *module,
21962214
/// Mangle the name of a protocol as a substitution candidate.
21972215
void ASTMangler::appendProtocolName(const ProtocolDecl *protocol,
21982216
bool allowStandardSubstitution) {
2217+
assert(AllowMarkerProtocols || !protocol->isMarkerProtocol());
2218+
21992219
if (allowStandardSubstitution && tryAppendStandardSubstitution(protocol))
22002220
return;
22012221

@@ -2344,6 +2364,8 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {
23442364
appendOperator("a");
23452365
break;
23462366
case DeclKind::Protocol:
2367+
assert(AllowMarkerProtocols ||
2368+
!cast<ProtocolDecl>(decl)->isMarkerProtocol());
23472369
appendOperator("P");
23482370
break;
23492371
case DeclKind::Class:
@@ -2657,6 +2679,11 @@ void ASTMangler::appendRequirement(const Requirement &reqt) {
26572679
case RequirementKind::Layout: {
26582680
} break;
26592681
case RequirementKind::Conformance: {
2682+
// If we don't allow marker protocols but we have one here, skip it.
2683+
if (!AllowMarkerProtocols &&
2684+
reqt.getProtocolDecl()->isMarkerProtocol())
2685+
return;
2686+
26602687
appendProtocolName(reqt.getProtocolDecl());
26612688
} break;
26622689
case RequirementKind::Superclass:
@@ -3187,6 +3214,12 @@ void ASTMangler::appendAnyProtocolConformance(
31873214
CanGenericSignature genericSig,
31883215
CanType conformingType,
31893216
ProtocolConformanceRef conformance) {
3217+
// If we have a conformance to a marker protocol but we aren't allowed to
3218+
// emit marker protocols, skip it.
3219+
if (!AllowMarkerProtocols &&
3220+
conformance.getRequirement()->isMarkerProtocol())
3221+
return;
3222+
31903223
if (conformingType->isTypeParameter()) {
31913224
assert(genericSig && "Need a generic signature to resolve conformance");
31923225
auto path = genericSig->getConformanceAccessPath(conformingType,

lib/IRGen/IRGenMangler.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ IRGenMangler::mangleTypeForReflection(IRGenModule &IGM,
159159
AllowConcurrencyStandardSubstitutions = false;
160160
}
161161

162+
llvm::SaveAndRestore<bool> savedAllowMarkerProtocols(
163+
AllowMarkerProtocols, false);
162164
return withSymbolicReferences(IGM, [&]{
163165
bindGenericParameters(Sig);
164166
appendType(Ty);

lib/Sema/TypeCheckAttr.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5588,6 +5588,12 @@ void AttributeChecker::visitMarkerAttr(MarkerAttr *attr) {
55885588
}
55895589
}
55905590

5591+
if (Type superclass = proto->getSuperclass()) {
5592+
proto->diagnose(
5593+
diag::marker_protocol_inherit_class,
5594+
proto->getName(), superclass);
5595+
}
5596+
55915597
// A marker protocol cannot have any requirements.
55925598
for (auto member : proto->getAllMembers()) {
55935599
auto value = dyn_cast<ValueDecl>(member);

test/IRGen/marker_protocol.swift

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@
1313
extension Int: P { }
1414
extension Array: P where Element: P { }
1515

16-
// CHECK: @"$s15marker_protocol1QMp" = {{(dllexport |protected )?}}constant
16+
// No mention of the marker protocol for runtime type instantiation.
17+
// CHECK-LABEL: @"$sSS_15marker_protocol1P_ptMD" =
18+
// CHECK-SAME: @"symbolic SS_ypt"
19+
20+
// CHECK-LABEL: @"$s15marker_protocol1QMp" = {{(dllexport |protected )?}}constant
1721
// CHECK-SAME: i32 trunc{{.*}}s15marker_protocolMXM{{.*}}s15marker_protocol1QMp
1822
// CHECK-SAME: i32 0, i32 5, i32 0
1923
public protocol Q: P {
@@ -24,6 +28,31 @@ public protocol Q: P {
2428
func j()
2529
}
2630

31+
protocol R { }
32+
33+
@_marker protocol S: AnyObject { }
34+
35+
// Note: no mention of marker protocols here.
36+
// CHECK-LABEL: @"$s15marker_protocol10HasMarkersVMF" =
37+
// CHECK-SAME: @"symbolic yp"
38+
// CHECK-SAME: @"symbolic ______p 15marker_protocol1QP"
39+
// CHECK-SAME: @"symbolic ______p 15marker_protocol1RP"
40+
// CHECK-SAME: @"symbolic yXl"
41+
struct HasMarkers {
42+
var field1: P
43+
var field2: P & Q
44+
var field3: P & R
45+
var field4: S
46+
}
47+
48+
// Note: no mention of marker protocols when forming a dictionary.
49+
// CHECK-LABEL: define{{.*}}@"$s15marker_protocol0A12InDictionaryypyF"
50+
// CHECK: call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({{.*}} @"$sSS_15marker_protocol1P_ptMD")
51+
public func markerInDictionary() -> Any {
52+
let dict: [String: P] = ["answer" : 42]
53+
return dict
54+
}
55+
2756
// Note: no witness tables
2857
// CHECK: swiftcc void @"$s15marker_protocol7genericyyxAA1PRzlF"(%swift.opaque* noalias nocapture %0, %swift.type* %T)
2958
public func generic<T: P>(_: T) { }

test/attr/attr_marker_protocol.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ protocol P4 { } // expected-note{{'P4' declared here}}
1717

1818
@_marker protocol P5: P4 { } // expected-error{{marker protocol 'P5' cannot inherit non-marker protocol 'P4'}}
1919

20+
class C { }
21+
@_marker protocol P5a: AnyObject { } // okay
22+
@_marker protocol P5b: C { } // expected-error{{marker protocol 'P5b' cannot inherit class 'C'}}
23+
2024
// Legitimate uses of marker protocols.
2125
extension P3 {
2226
func f() { }

0 commit comments

Comments
 (0)