Skip to content

Commit 20cc067

Browse files
AzoyDougGregor
authored andcommitted
[AST] Introduce BuiltinProtocolConformance
1 parent fb4ee55 commit 20cc067

13 files changed

+283
-22
lines changed

include/swift/AST/ASTContext.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ namespace swift {
105105
class InheritedProtocolConformance;
106106
class SelfProtocolConformance;
107107
class SpecializedProtocolConformance;
108+
class BuiltinProtocolConformance;
108109
enum class ProtocolConformanceState;
109110
class Pattern;
110111
enum PointerTypeKind : unsigned;
@@ -1029,6 +1030,11 @@ class ASTContext final {
10291030
SelfProtocolConformance *
10301031
getSelfConformance(ProtocolDecl *protocol);
10311032

1033+
/// Produce the builtin conformance for some structural type to some protocol.
1034+
BuiltinProtocolConformance *
1035+
getBuiltinConformance(Type type, ProtocolDecl *protocol,
1036+
ArrayRef<ProtocolConformanceRef> conformances);
1037+
10321038
/// A callback used to produce a diagnostic for an ill-formed protocol
10331039
/// conformance that was type-checked before we're actually walking the
10341040
/// 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

@@ -987,6 +993,106 @@ class InheritedProtocolConformance : public ProtocolConformance,
987993
}
988994
};
989995

996+
/// A builtin conformance appears when a non-nominal type has a
997+
/// conformance that is synthesized by the implementation.
998+
class BuiltinProtocolConformance final : public RootProtocolConformance,
999+
private llvm::TrailingObjects<BuiltinProtocolConformance,
1000+
ProtocolConformanceRef> {
1001+
friend ASTContext;
1002+
friend TrailingObjects;
1003+
1004+
ProtocolDecl *protocol = nullptr;
1005+
size_t numConformances;
1006+
1007+
mutable Optional<ArrayRef<Requirement>> conditionalConformances = None;
1008+
1009+
BuiltinProtocolConformance(Type conformingType, ProtocolDecl *protocol,
1010+
ArrayRef<ProtocolConformanceRef> conformances);
1011+
1012+
size_t numTrailingObjects(OverloadToken<ProtocolConformanceRef>) const {
1013+
return numConformances;
1014+
}
1015+
1016+
public:
1017+
/// Get the protocol being conformed to.
1018+
ProtocolDecl *getProtocol() const {
1019+
return protocol;
1020+
}
1021+
1022+
/// Get the trailing conformances that this builtin conformance needs.
1023+
MutableArrayRef<ProtocolConformanceRef> getConformances() {
1024+
return {getTrailingObjects<ProtocolConformanceRef>(), numConformances};
1025+
}
1026+
1027+
/// Get the trailing conformances that this builtin conformance needs.
1028+
ArrayRef<ProtocolConformanceRef> getConformances() const {
1029+
return {getTrailingObjects<ProtocolConformanceRef>(), numConformances};
1030+
}
1031+
1032+
/// Get any requirements that must be satisfied for this conformance to apply.
1033+
Optional<ArrayRef<Requirement>>
1034+
getConditionalRequirementsIfAvailable() const {
1035+
return ArrayRef<Requirement>();
1036+
}
1037+
1038+
/// Get any requirements that must be satisfied for this conformance to apply.
1039+
ArrayRef<Requirement> getConditionalRequirements() const;
1040+
1041+
/// Get the declaration context that contains the nominal type declaration.
1042+
DeclContext *getDeclContext() const {
1043+
return getProtocol();
1044+
}
1045+
1046+
/// Retrieve the state of this conformance.
1047+
ProtocolConformanceState getState() const {
1048+
return ProtocolConformanceState::Complete;
1049+
}
1050+
1051+
/// Get the kind of source from which this conformance comes.
1052+
ConformanceEntryKind getSourceKind() const {
1053+
return ConformanceEntryKind::Synthesized;
1054+
}
1055+
/// Get the protocol conformance which implied this implied conformance.
1056+
NormalProtocolConformance *getImplyingConformance() const {
1057+
return nullptr;
1058+
}
1059+
1060+
bool hasTypeWitness(AssociatedTypeDecl *assocType) const {
1061+
llvm_unreachable("builtin-conformances never have associated types");
1062+
}
1063+
1064+
/// Retrieve the type witness and type decl (if one exists)
1065+
/// for the given associated type.
1066+
TypeWitnessAndDecl
1067+
getTypeWitnessAndDecl(AssociatedTypeDecl *assocType,
1068+
SubstOptions options=None) const {
1069+
llvm_unreachable("builtin-conformances never have associated types");
1070+
}
1071+
1072+
/// Given that the requirement signature of the protocol directly states
1073+
/// that the given dependent type must conform to the given protocol,
1074+
/// return its associated conformance.
1075+
ProtocolConformanceRef
1076+
getAssociatedConformance(Type assocType, ProtocolDecl *protocol) const {
1077+
llvm_unreachable("builtin-conformances never have associated types");
1078+
}
1079+
1080+
/// Retrieve the witness corresponding to the given value requirement.
1081+
ConcreteDeclRef getWitnessDeclRef(ValueDecl *requirement) const {
1082+
return ConcreteDeclRef(requirement);
1083+
}
1084+
1085+
/// Determine whether the witness for the given requirement
1086+
/// is either the default definition or was otherwise deduced.
1087+
bool usesDefaultDefinition(AssociatedTypeDecl *requirement) const {
1088+
llvm_unreachable("builtin-conformances never have associated types");
1089+
}
1090+
1091+
static bool classof(const ProtocolConformance *conformance) {
1092+
return conformance->getKind() == ProtocolConformanceKind::Builtin;
1093+
}
1094+
};
1095+
9901096
inline bool ProtocolConformance::isInvalid() const {
9911097
return getRootConformance()->isInvalid();
9921098
}

lib/AST/ASTContext.cpp

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

442+
/// The set of builtin protocol conformances.
443+
llvm::DenseMap<std::pair<Type, ProtocolDecl *>,
444+
BuiltinProtocolConformance *> BuiltinConformances;
445+
442446
/// The set of substitution maps (uniqued by their storage).
443447
llvm::FoldingSet<SubstitutionMap::Storage> SubstitutionMaps;
444448

@@ -2243,6 +2247,24 @@ ASTContext::getSelfConformance(ProtocolDecl *protocol) {
22432247
return entry;
22442248
}
22452249

2250+
/// Produce the builtin conformance for some non-nominal to some protocol.
2251+
BuiltinProtocolConformance *
2252+
ASTContext::getBuiltinConformance(Type type, ProtocolDecl *protocol,
2253+
ArrayRef<ProtocolConformanceRef> conformances) {
2254+
auto key = std::make_pair(type, protocol);
2255+
AllocationArena arena = getArena(type->getRecursiveProperties());
2256+
auto &builtinConformances = getImpl().getArena(arena).BuiltinConformances;
2257+
2258+
auto &entry = builtinConformances[key];
2259+
if (!entry) {
2260+
auto size = BuiltinProtocolConformance::
2261+
totalSizeToAlloc<ProtocolConformanceRef>(conformances.size());
2262+
auto mem = this->Allocate(size, alignof(BuiltinProtocolConformance), arena);
2263+
entry = new (mem) BuiltinProtocolConformance(type, protocol, conformances);
2264+
}
2265+
return entry;
2266+
}
2267+
22462268
/// If one of the ancestor conformances already has a matching type, use
22472269
/// that instead.
22482270
static ProtocolConformance *collapseSpecializedConformance(
@@ -2259,6 +2281,7 @@ static ProtocolConformance *collapseSpecializedConformance(
22592281
case ProtocolConformanceKind::Normal:
22602282
case ProtocolConformanceKind::Inherited:
22612283
case ProtocolConformanceKind::Self:
2284+
case ProtocolConformanceKind::Builtin:
22622285
// If the conformance matches, return it.
22632286
if (conformance->getType()->isEqual(type)) {
22642287
for (auto subConformance : substitutions.getConformances())
@@ -2496,6 +2519,7 @@ size_t ASTContext::Implementation::Arena::getTotalMemory() const {
24962519
// NormalConformances ?
24972520
// SpecializedConformances ?
24982521
// InheritedConformances ?
2522+
// BuiltinConformances ?
24992523
}
25002524

25012525
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
@@ -3262,6 +3262,10 @@ static void dumpProtocolConformanceRec(
32623262
visited);
32633263
break;
32643264
}
3265+
3266+
case ProtocolConformanceKind::Builtin: {
3267+
printCommon("builtin");
3268+
}
32653269
}
32663270

32673271
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
@@ -209,9 +209,11 @@ std::string ASTMangler::mangleWitnessTable(const RootProtocolConformance *C) {
209209
if (isa<NormalProtocolConformance>(C)) {
210210
appendProtocolConformance(C);
211211
appendOperator("WP");
212-
} else {
212+
} else if (isa<SelfProtocolConformance>(C)) {
213213
appendProtocolName(cast<SelfProtocolConformance>(C)->getProtocol());
214214
appendOperator("WS");
215+
} else {
216+
llvm_unreachable("mangling unknown conformance kind");
215217
}
216218
return finalize();
217219
}
@@ -235,7 +237,11 @@ std::string ASTMangler::mangleWitnessThunk(
235237
}
236238

237239
if (Conformance) {
238-
appendOperator(isa<SelfProtocolConformance>(Conformance) ? "TS" : "TW");
240+
if (isa<SelfProtocolConformance>(Conformance)) {
241+
appendOperator("TS");
242+
} else {
243+
appendOperator("TW");
244+
}
239245
}
240246
return finalize();
241247
}
@@ -1556,7 +1562,8 @@ void ASTMangler::appendBoundGenericArgs(Type type, bool &isFirstArgList) {
15561562
static bool conformanceHasIdentity(const RootProtocolConformance *root) {
15571563
auto conformance = dyn_cast<NormalProtocolConformance>(root);
15581564
if (!conformance) {
1559-
assert(isa<SelfProtocolConformance>(root));
1565+
assert(isa<SelfProtocolConformance>(root) ||
1566+
isa<BuiltinProtocolConformance>(root));
15601567
return true;
15611568
}
15621569

@@ -1577,8 +1584,9 @@ static bool conformanceHasIdentity(const RootProtocolConformance *root) {
15771584
static bool isRetroactiveConformance(const RootProtocolConformance *root) {
15781585
auto conformance = dyn_cast<NormalProtocolConformance>(root);
15791586
if (!conformance) {
1580-
assert(isa<SelfProtocolConformance>(root));
1581-
return false; // self-conformances are never retroactive.
1587+
assert(isa<SelfProtocolConformance>(root) ||
1588+
isa<BuiltinProtocolConformance>(root));
1589+
return false; // self-conformances are never retroactive. nor are builtin.
15821590
}
15831591

15841592
return conformance->isRetroactive();
@@ -3058,6 +3066,10 @@ ASTMangler::appendProtocolConformance(const ProtocolConformance *conformance) {
30583066
appendModule(Mod, DC->getAsDecl()->getAlternateModuleName());
30593067
}
30603068

3069+
// If this is a non-nominal type, we're done.
3070+
if (!conformingType->getAnyNominal())
3071+
return;
3072+
30613073
contextSig =
30623074
conformingType->getAnyNominal()->getGenericSignatureOfContext();
30633075

@@ -3082,6 +3094,9 @@ void ASTMangler::appendProtocolConformanceRef(
30823094
assert(DC->getAsDecl());
30833095
appendModule(conformance->getDeclContext()->getParentModule(),
30843096
DC->getAsDecl()->getAlternateModuleName());
3097+
// Builtin conformances are always from the Swift module.
3098+
} else if (isa<BuiltinProtocolConformance>(conformance)) {
3099+
appendOperator("HP");
30853100
} else if (conformance->getDeclContext()->getParentModule() ==
30863101
conformance->getType()->getAnyNominal()->getParentModule()) {
30873102
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
@@ -5699,6 +5699,12 @@ void ProtocolConformance::printName(llvm::raw_ostream &os,
56995699
os << ")";
57005700
break;
57015701
}
5702+
case ProtocolConformanceKind::Builtin: {
5703+
auto builtin = cast<BuiltinProtocolConformance>(this);
5704+
os << builtin->getProtocol()->getName()
5705+
<< " type " << builtin->getType();
5706+
break;
5707+
}
57025708
}
57035709
}
57045710

0 commit comments

Comments
 (0)