Skip to content

Commit f21a306

Browse files
committed
[AST] Introduce BuiltinProtocolConformance
1 parent 64ec60b commit f21a306

16 files changed

+294
-27
lines changed

include/swift/AST/ASTContext.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ namespace swift {
103103
class InheritedProtocolConformance;
104104
class SelfProtocolConformance;
105105
class SpecializedProtocolConformance;
106+
class BuiltinProtocolConformance;
106107
enum class ProtocolConformanceState;
107108
class Pattern;
108109
enum PointerTypeKind : unsigned;
@@ -948,6 +949,11 @@ class ASTContext final {
948949
SelfProtocolConformance *
949950
getSelfConformance(ProtocolDecl *protocol);
950951

952+
/// Produce the builtin conformance for some structural type to some protocol.
953+
BuiltinProtocolConformance *
954+
getBuiltinConformance(Type type, ProtocolDecl *protocol,
955+
ArrayRef<ProtocolConformanceRef> conformances);
956+
951957
/// A callback used to produce a diagnostic for an ill-formed protocol
952958
/// conformance that was type-checked before we're actually walking the
953959
/// conformance itself, along with a bit indicating whether this diagnostic

include/swift/AST/ProtocolConformance.h

Lines changed: 110 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -66,7 +66,10 @@ enum class ProtocolConformanceKind {
6666
Specialized,
6767
/// Conformance of a generic class type projected through one of its
6868
/// superclass's conformances.
69-
Inherited
69+
Inherited,
70+
/// Builtin conformances are special conformaces that the runtime handles
71+
/// and isn't implemented directly in Swift.
72+
Builtin
7073
};
7174

7275
/// Describes the state of a protocol conformance, which may be complete,
@@ -329,7 +332,9 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {
329332
/// - the type is directly declared to conform to the protocol (a
330333
/// normal conformance) or
331334
/// - the protocol's existential type is known to conform to itself (a
332-
/// self-conformance).
335+
/// self-conformance) or
336+
/// - the type's conformance is declared within the runtime (a builtin
337+
/// conformance).
333338
class RootProtocolConformance : public ProtocolConformance {
334339
protected:
335340
RootProtocolConformance(ProtocolConformanceKind kind, Type conformingType)
@@ -380,7 +385,8 @@ class RootProtocolConformance : public ProtocolConformance {
380385

381386
static bool classof(const ProtocolConformance *conformance) {
382387
return conformance->getKind() == ProtocolConformanceKind::Normal ||
383-
conformance->getKind() == ProtocolConformanceKind::Self;
388+
conformance->getKind() == ProtocolConformanceKind::Self ||
389+
conformance->getKind() == ProtocolConformanceKind::Builtin;
384390
}
385391
};
386392

@@ -1014,6 +1020,106 @@ class InheritedProtocolConformance : public ProtocolConformance,
10141020
}
10151021
};
10161022

1023+
/// A builtin conformance appears when a special non-nominal type has a runtime
1024+
/// declared conformance. E.g. the runtime implements Equatable for tuples.
1025+
class BuiltinProtocolConformance final : public RootProtocolConformance,
1026+
private llvm::TrailingObjects<BuiltinProtocolConformance,
1027+
ProtocolConformanceRef> {
1028+
friend ASTContext;
1029+
friend TrailingObjects;
1030+
1031+
ProtocolDecl *protocol = nullptr;
1032+
size_t numConformances;
1033+
1034+
mutable Optional<ArrayRef<Requirement>> conditionalConformances = None;
1035+
1036+
BuiltinProtocolConformance(Type conformingType, ProtocolDecl *protocol,
1037+
ArrayRef<ProtocolConformanceRef> conformances);
1038+
1039+
size_t numTrailingObjects(OverloadToken<ProtocolConformanceRef>) const {
1040+
return numConformances;
1041+
}
1042+
1043+
public:
1044+
/// Get the protocol being conformed to.
1045+
ProtocolDecl *getProtocol() const {
1046+
return protocol;
1047+
}
1048+
1049+
/// Get the trailing conformances that this builtin conformance needs.
1050+
MutableArrayRef<ProtocolConformanceRef> getConformances() {
1051+
return {getTrailingObjects<ProtocolConformanceRef>(), numConformances};
1052+
}
1053+
1054+
/// Get the trailing conformances that this builtin conformance needs.
1055+
ArrayRef<ProtocolConformanceRef> getConformances() const {
1056+
return {getTrailingObjects<ProtocolConformanceRef>(), numConformances};
1057+
}
1058+
1059+
/// Get any requirements that must be satisfied for this conformance to apply.
1060+
Optional<ArrayRef<Requirement>>
1061+
getConditionalRequirementsIfAvailable() const {
1062+
return ArrayRef<Requirement>();
1063+
}
1064+
1065+
/// Get any requirements that must be satisfied for this conformance to apply.
1066+
ArrayRef<Requirement> getConditionalRequirements() const;
1067+
1068+
/// Get the declaration context that contains the nominal type declaration.
1069+
DeclContext *getDeclContext() const {
1070+
return getProtocol();
1071+
}
1072+
1073+
/// Retrieve the state of this conformance.
1074+
ProtocolConformanceState getState() const {
1075+
return ProtocolConformanceState::Complete;
1076+
}
1077+
1078+
/// Get the kind of source from which this conformance comes.
1079+
ConformanceEntryKind getSourceKind() const {
1080+
return ConformanceEntryKind::Synthesized;
1081+
}
1082+
/// Get the protocol conformance which implied this implied conformance.
1083+
NormalProtocolConformance *getImplyingConformance() const {
1084+
return nullptr;
1085+
}
1086+
1087+
bool hasTypeWitness(AssociatedTypeDecl *assocType) const {
1088+
llvm_unreachable("builtin-conformances never have associated types");
1089+
}
1090+
1091+
/// Retrieve the type witness and type decl (if one exists)
1092+
/// for the given associated type.
1093+
TypeWitnessAndDecl
1094+
getTypeWitnessAndDecl(AssociatedTypeDecl *assocType,
1095+
SubstOptions options=None) const {
1096+
llvm_unreachable("builtin-conformances never have associated types");
1097+
}
1098+
1099+
/// Given that the requirement signature of the protocol directly states
1100+
/// that the given dependent type must conform to the given protocol,
1101+
/// return its associated conformance.
1102+
ProtocolConformanceRef
1103+
getAssociatedConformance(Type assocType, ProtocolDecl *protocol) const {
1104+
llvm_unreachable("builtin-conformances never have associated types");
1105+
}
1106+
1107+
/// Retrieve the witness corresponding to the given value requirement.
1108+
ConcreteDeclRef getWitnessDeclRef(ValueDecl *requirement) const {
1109+
return ConcreteDeclRef(requirement);
1110+
}
1111+
1112+
/// Determine whether the witness for the given requirement
1113+
/// is either the default definition or was otherwise deduced.
1114+
bool usesDefaultDefinition(AssociatedTypeDecl *requirement) const {
1115+
llvm_unreachable("builtin-conformances never have associated types");
1116+
}
1117+
1118+
static bool classof(const ProtocolConformance *conformance) {
1119+
return conformance->getKind() == ProtocolConformanceKind::Builtin;
1120+
}
1121+
};
1122+
10171123
inline bool ProtocolConformance::isInvalid() const {
10181124
return getRootConformance()->isInvalid();
10191125
}

include/swift/SIL/SILCloner.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -2093,7 +2093,8 @@ SILCloner<ImplClass>::visitWitnessMethodInst(WitnessMethodInst *Inst) {
20932093
if (conformance.isConcrete()) {
20942094
CanType Ty = conformance.getConcrete()->getType()->getCanonicalType();
20952095

2096-
if (Ty != newLookupType) {
2096+
if (Ty != newLookupType &&
2097+
!isa<BuiltinProtocolConformance>(conformance.getConcrete())) {
20972098
assert(
20982099
(Ty->isExactSuperclassOf(newLookupType) ||
20992100
getBuilder().getModule().Types.getLoweredRValueType(

lib/AST/ASTContext.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,10 @@ struct ASTContext::Implementation {
406406
/// The set of inherited protocol conformances.
407407
llvm::FoldingSet<InheritedProtocolConformance> InheritedConformances;
408408

409+
/// The set of builtin protocol conformances.
410+
llvm::DenseMap<std::pair<Type, ProtocolDecl *>,
411+
BuiltinProtocolConformance *> BuiltinConformances;
412+
409413
/// The set of substitution maps (uniqued by their storage).
410414
llvm::FoldingSet<SubstitutionMap::Storage> SubstitutionMaps;
411415

@@ -2014,6 +2018,24 @@ ASTContext::getSelfConformance(ProtocolDecl *protocol) {
20142018
return entry;
20152019
}
20162020

2021+
/// Produce the builtin conformance for some non-nominal to some protocol.
2022+
BuiltinProtocolConformance *
2023+
ASTContext::getBuiltinConformance(Type type, ProtocolDecl *protocol,
2024+
ArrayRef<ProtocolConformanceRef> conformances) {
2025+
auto key = std::make_pair(type, protocol);
2026+
auto &builtinConformances =
2027+
getImpl().getArena(AllocationArena::Permanent).BuiltinConformances;
2028+
auto &entry = builtinConformances[key];
2029+
if (!entry) {
2030+
auto size = BuiltinProtocolConformance::
2031+
totalSizeToAlloc<ProtocolConformanceRef>(conformances.size());
2032+
auto mem = this->Allocate(size, alignof(BuiltinProtocolConformance),
2033+
AllocationArena::Permanent);
2034+
entry = new (mem) BuiltinProtocolConformance(type, protocol, conformances);
2035+
}
2036+
return entry;
2037+
}
2038+
20172039
/// If one of the ancestor conformances already has a matching type, use
20182040
/// that instead.
20192041
static ProtocolConformance *collapseSpecializedConformance(
@@ -2030,6 +2052,7 @@ static ProtocolConformance *collapseSpecializedConformance(
20302052
case ProtocolConformanceKind::Normal:
20312053
case ProtocolConformanceKind::Inherited:
20322054
case ProtocolConformanceKind::Self:
2055+
case ProtocolConformanceKind::Builtin:
20332056
// If the conformance matches, return it.
20342057
if (conformance->getType()->isEqual(type)) {
20352058
for (auto subConformance : substitutions.getConformances())
@@ -2252,6 +2275,7 @@ size_t ASTContext::Implementation::Arena::getTotalMemory() const {
22522275
// NormalConformances ?
22532276
// SpecializedConformances ?
22542277
// InheritedConformances ?
2278+
// BuiltinConformances ?
22552279
}
22562280

22572281
void AbstractFunctionDecl::setForeignErrorConvention(

lib/AST/ASTDumper.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -3310,6 +3310,10 @@ static void dumpProtocolConformanceRec(
33103310
visited);
33113311
break;
33123312
}
3313+
3314+
case ProtocolConformanceKind::Builtin: {
3315+
printCommon("builtin");
3316+
}
33133317
}
33143318

33153319
PrintWithColorRAII(out, ParenthesisColor) << ')';

lib/AST/ASTMangler.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -200,9 +200,11 @@ std::string ASTMangler::mangleWitnessTable(const RootProtocolConformance *C) {
200200
if (isa<NormalProtocolConformance>(C)) {
201201
appendProtocolConformance(C);
202202
appendOperator("WP");
203-
} else {
203+
} else if (isa<SelfProtocolConformance>(C)) {
204204
appendProtocolName(cast<SelfProtocolConformance>(C)->getProtocol());
205205
appendOperator("WS");
206+
} else {
207+
llvm_unreachable("mangling unknown conformance kind");
206208
}
207209
return finalize();
208210
}
@@ -226,7 +228,11 @@ std::string ASTMangler::mangleWitnessThunk(
226228
}
227229

228230
if (Conformance) {
229-
appendOperator(isa<SelfProtocolConformance>(Conformance) ? "TS" : "TW");
231+
if (isa<SelfProtocolConformance>(Conformance)) {
232+
appendOperator("TS");
233+
} else {
234+
appendOperator("TW");
235+
}
230236
}
231237
return finalize();
232238
}
@@ -1462,7 +1468,8 @@ void ASTMangler::appendBoundGenericArgs(Type type, bool &isFirstArgList) {
14621468
static bool conformanceHasIdentity(const RootProtocolConformance *root) {
14631469
auto conformance = dyn_cast<NormalProtocolConformance>(root);
14641470
if (!conformance) {
1465-
assert(isa<SelfProtocolConformance>(root));
1471+
assert(isa<SelfProtocolConformance>(root) ||
1472+
isa<BuiltinProtocolConformance>(root));
14661473
return true;
14671474
}
14681475

@@ -1483,8 +1490,9 @@ static bool conformanceHasIdentity(const RootProtocolConformance *root) {
14831490
static bool isRetroactiveConformance(const RootProtocolConformance *root) {
14841491
auto conformance = dyn_cast<NormalProtocolConformance>(root);
14851492
if (!conformance) {
1486-
assert(isa<SelfProtocolConformance>(root));
1487-
return false; // self-conformances are never retroactive.
1493+
assert(isa<SelfProtocolConformance>(root) ||
1494+
isa<BuiltinProtocolConformance>(root));
1495+
return false; // self-conformances are never retroactive. nor are builtin.
14881496
}
14891497

14901498
return conformance->isRetroactive();
@@ -2910,6 +2918,10 @@ ASTMangler::appendProtocolConformance(const ProtocolConformance *conformance) {
29102918
appendModule(Mod, DC->getAsDecl()->getAlternateModuleName());
29112919
}
29122920

2921+
// If this is a non-nominal type, we're done.
2922+
if (!conformingType->getAnyNominal())
2923+
return;
2924+
29132925
contextSig =
29142926
conformingType->getAnyNominal()->getGenericSignatureOfContext();
29152927

@@ -2934,6 +2946,9 @@ void ASTMangler::appendProtocolConformanceRef(
29342946
assert(DC->getAsDecl());
29352947
appendModule(conformance->getDeclContext()->getParentModule(),
29362948
DC->getAsDecl()->getAlternateModuleName());
2949+
// Builtin conformances are always from the Swift module.
2950+
} else if (isa<BuiltinProtocolConformance>(conformance)) {
2951+
appendOperator("HP");
29372952
} else if (conformance->getDeclContext()->getParentModule() ==
29382953
conformance->getType()->getAnyNominal()->getParentModule()) {
29392954
appendOperator("HP");

lib/AST/ASTPrinter.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -5035,6 +5035,12 @@ void ProtocolConformance::printName(llvm::raw_ostream &os,
50355035
os << ")";
50365036
break;
50375037
}
5038+
case ProtocolConformanceKind::Builtin: {
5039+
auto builtin = cast<BuiltinProtocolConformance>(this);
5040+
os << builtin->getProtocol()->getName()
5041+
<< " type " << builtin->getType();
5042+
break;
5043+
}
50385044
}
50395045
}
50405046

0 commit comments

Comments
 (0)