Skip to content

Commit e5ad88d

Browse files
authored
Merge pull request #17994 from slavapestov/misc-conformance-cleanups
Miscellaneous conformance cleanups
2 parents 986e093 + fc80f75 commit e5ad88d

13 files changed

+132
-59
lines changed

include/swift/AST/ProtocolConformance.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,11 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {
313313
/// be satisfied.
314314
ArrayRef<Requirement> getConditionalRequirements() const;
315315

316+
/// Substitute the conforming type and produce a ProtocolConformance that
317+
/// applies to the substituted type.
318+
ProtocolConformance *subst(Type substType,
319+
SubstitutionMap subMap) const;
320+
316321
/// Substitute the conforming type and produce a ProtocolConformance that
317322
/// applies to the substituted type.
318323
ProtocolConformance *subst(Type substType,

include/swift/AST/ProtocolConformanceRef.h

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,8 @@ class ProtocolConformanceRef {
4747
using UnionType = llvm::PointerUnion<ProtocolDecl*, ProtocolConformance*>;
4848
UnionType Union;
4949

50-
explicit ProtocolConformanceRef(UnionType value) : Union(value) {
51-
assert(value && "cannot construct ProtocolConformanceRef with null");
52-
}
50+
explicit ProtocolConformanceRef(UnionType value) : Union(value) {}
51+
5352
public:
5453
/// Create an abstract protocol conformance reference.
5554
explicit ProtocolConformanceRef(ProtocolDecl *proto) : Union(proto) {
@@ -63,17 +62,30 @@ class ProtocolConformanceRef {
6362
"cannot construct ProtocolConformanceRef with null");
6463
}
6564

65+
static ProtocolConformanceRef forInvalid() {
66+
return ProtocolConformanceRef(UnionType((ProtocolDecl *)nullptr));
67+
}
68+
69+
bool isInvalid() const {
70+
return !Union;
71+
}
72+
6673
/// Create either a concrete or an abstract protocol conformance reference,
6774
/// depending on whether ProtocolConformance is null.
6875
explicit ProtocolConformanceRef(ProtocolDecl *protocol,
6976
ProtocolConformance *conf);
7077

71-
bool isConcrete() const { return Union.is<ProtocolConformance*>(); }
78+
bool isConcrete() const {
79+
return !isInvalid() && Union.is<ProtocolConformance*>();
80+
}
7281
ProtocolConformance *getConcrete() const {
7382
return Union.get<ProtocolConformance*>();
7483
}
7584

76-
bool isAbstract() const { return Union.is<ProtocolDecl*>(); }
85+
bool isAbstract() const {
86+
return !isInvalid() && Union.is<ProtocolDecl*>();
87+
}
88+
7789
ProtocolDecl *getAbstract() const {
7890
return Union.get<ProtocolDecl*>();
7991
}
@@ -87,6 +99,10 @@ class ProtocolConformanceRef {
8799
/// Return the protocol requirement.
88100
ProtocolDecl *getRequirement() const;
89101

102+
/// Apply a substitution to the conforming type.
103+
ProtocolConformanceRef subst(Type origType,
104+
SubstitutionMap subMap) const;
105+
90106
/// Apply a substitution to the conforming type.
91107
ProtocolConformanceRef subst(Type origType,
92108
TypeSubstitutionFn subs,

include/swift/SIL/TypeSubstCloner.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,7 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
172172

173173
ProtocolConformanceRef remapConformance(Type type,
174174
ProtocolConformanceRef conf) {
175-
return conf.subst(type,
176-
QuerySubstitutionMap{SubsMap},
177-
LookUpConformanceInSubstitutionMap(SubsMap));
175+
return conf.subst(type, SubsMap);
178176
}
179177

180178
SubstitutionMap remapSubstitutionMap(SubstitutionMap Subs) {

include/swift/Serialization/DeclTypeRecordNodes.def

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ TYPE(TUPLE)
8787
TRAILING_INFO(TUPLE_TYPE_ELT)
8888
TYPE(FUNCTION)
8989
TYPE(METATYPE)
90-
TYPE(LVALUE_unused)
9190
TYPE(INOUT)
9291
TYPE(ARCHETYPE)
9392
TYPE(PROTOCOL_COMPOSITION)
@@ -144,42 +143,44 @@ PATTERN(ANY)
144143
PATTERN(TYPED)
145144
PATTERN(VAR)
146145

147-
OTHER(PARAMETERLIST, 226)
148-
OTHER(PARAMETERLIST_ELT, 227)
149-
OTHER(FOREIGN_ERROR_CONVENTION, 228)
150-
OTHER(DECL_CONTEXT, 229)
151-
OTHER(XREF_TYPE_PATH_PIECE, 230)
152-
OTHER(XREF_VALUE_PATH_PIECE, 231)
153-
OTHER(XREF_EXTENSION_PATH_PIECE, 232)
154-
OTHER(XREF_OPERATOR_OR_ACCESSOR_PATH_PIECE, 233)
155-
OTHER(XREF_GENERIC_PARAM_PATH_PIECE, 234)
156-
OTHER(XREF_INITIALIZER_PATH_PIECE, 235)
157-
158-
OTHER(ABSTRACT_CLOSURE_EXPR_CONTEXT, 236)
159-
OTHER(PATTERN_BINDING_INITIALIZER_CONTEXT, 237)
160-
OTHER(DEFAULT_ARGUMENT_INITIALIZER_CONTEXT, 238)
161-
OTHER(TOP_LEVEL_CODE_DECL_CONTEXT, 239)
162-
163-
OTHER(GENERIC_PARAM_LIST, 240)
146+
OTHER(PARAMETERLIST, 210)
147+
OTHER(PARAMETERLIST_ELT, 211)
148+
OTHER(FOREIGN_ERROR_CONVENTION, 212)
149+
OTHER(DECL_CONTEXT, 213)
150+
OTHER(XREF_TYPE_PATH_PIECE, 214)
151+
OTHER(XREF_VALUE_PATH_PIECE, 215)
152+
OTHER(XREF_EXTENSION_PATH_PIECE, 216)
153+
OTHER(XREF_OPERATOR_OR_ACCESSOR_PATH_PIECE, 217)
154+
OTHER(XREF_GENERIC_PARAM_PATH_PIECE, 218)
155+
OTHER(XREF_INITIALIZER_PATH_PIECE, 219)
156+
157+
OTHER(ABSTRACT_CLOSURE_EXPR_CONTEXT, 220)
158+
OTHER(PATTERN_BINDING_INITIALIZER_CONTEXT, 221)
159+
OTHER(DEFAULT_ARGUMENT_INITIALIZER_CONTEXT, 222)
160+
OTHER(TOP_LEVEL_CODE_DECL_CONTEXT, 223)
161+
162+
OTHER(GENERIC_PARAM_LIST, 230)
164163
TRAILING_INFO(GENERIC_PARAM)
165164
TRAILING_INFO(GENERIC_REQUIREMENT)
166165
TRAILING_INFO(LAYOUT_REQUIREMENT)
167-
OTHER(GENERIC_SIGNATURE, 244)
168-
OTHER(SIL_GENERIC_ENVIRONMENT, 245)
169-
OTHER(SUBSTITUTION_MAP, 246)
170-
171-
OTHER(LOCAL_DISCRIMINATOR, 248)
172-
OTHER(PRIVATE_DISCRIMINATOR, 249)
173-
174-
OTHER(ABSTRACT_PROTOCOL_CONFORMANCE, 250)
175-
OTHER(NORMAL_PROTOCOL_CONFORMANCE, 251)
176-
OTHER(SPECIALIZED_PROTOCOL_CONFORMANCE, 252)
177-
OTHER(INHERITED_PROTOCOL_CONFORMANCE, 253)
178-
OTHER(SIL_LAYOUT, 197) // FIXME: Note out-of-order
179-
OTHER(NORMAL_PROTOCOL_CONFORMANCE_ID, 198) // FIXME: Note out-of-order
180-
OTHER(PROTOCOL_CONFORMANCE_XREF, 199) // FIXME: Note out-of-order
181-
OTHER(MEMBERS, 254)
182-
OTHER(XREF, 255)
166+
OTHER(GENERIC_SIGNATURE, 234)
167+
OTHER(SIL_GENERIC_ENVIRONMENT, 235)
168+
OTHER(SUBSTITUTION_MAP, 236)
169+
170+
OTHER(LOCAL_DISCRIMINATOR, 237)
171+
OTHER(PRIVATE_DISCRIMINATOR, 238)
172+
173+
OTHER(ABSTRACT_PROTOCOL_CONFORMANCE, 240)
174+
OTHER(NORMAL_PROTOCOL_CONFORMANCE, 241)
175+
OTHER(SPECIALIZED_PROTOCOL_CONFORMANCE, 242)
176+
OTHER(INHERITED_PROTOCOL_CONFORMANCE, 243)
177+
OTHER(INVALID_PROTOCOL_CONFORMANCE, 244)
178+
179+
OTHER(SIL_LAYOUT, 245)
180+
OTHER(NORMAL_PROTOCOL_CONFORMANCE_ID, 246)
181+
OTHER(PROTOCOL_CONFORMANCE_XREF, 247)
182+
OTHER(MEMBERS, 248)
183+
OTHER(XREF, 249)
183184

184185
#undef RECORD
185186
#undef DECLTYPERECORDNODES_HAS_RECORD_VAL

include/swift/Serialization/ModuleFormat.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
5757
/// Don't worry about adhering to the 80-column limit for this line.
58-
const uint16_t VERSION_MINOR = 426; // SIL key path external components with local attempts
58+
const uint16_t VERSION_MINOR = 427; // Invalid conformances
5959

6060
using DeclIDField = BCFixed<31>;
6161

@@ -1287,6 +1287,11 @@ namespace decls_block {
12871287
DeclIDField // the protocol
12881288
>;
12891289

1290+
/// A placeholder for an invalid conformance.
1291+
using InvalidProtocolConformanceLayout = BCRecordLayout<
1292+
INVALID_PROTOCOL_CONFORMANCE
1293+
>;
1294+
12901295
using NormalProtocolConformanceLayout = BCRecordLayout<
12911296
NORMAL_PROTOCOL_CONFORMANCE,
12921297
DeclIDField, // the protocol

lib/AST/ASTDumper.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2852,7 +2852,9 @@ static void dumpProtocolConformanceRefRec(
28522852
const ProtocolConformanceRef conformance, llvm::raw_ostream &out,
28532853
unsigned indent,
28542854
llvm::SmallPtrSetImpl<const ProtocolConformance *> &visited) {
2855-
if (conformance.isConcrete()) {
2855+
if (conformance.isInvalid()) {
2856+
out.indent(indent) << "(invalid_conformance)";
2857+
} else if (conformance.isConcrete()) {
28562858
dumpProtocolConformanceRec(conformance.getConcrete(), out, indent, visited);
28572859
} else {
28582860
out.indent(indent) << "(abstract_conformance protocol="

lib/AST/ProtocolConformance.cpp

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,30 @@ ProtocolConformanceRef::ProtocolConformanceRef(ProtocolDecl *protocol,
7474
}
7575

7676
ProtocolDecl *ProtocolConformanceRef::getRequirement() const {
77+
assert(!isInvalid());
78+
7779
if (isConcrete()) {
7880
return getConcrete()->getProtocol();
7981
} else {
8082
return getAbstract();
8183
}
8284
}
8385

86+
ProtocolConformanceRef
87+
ProtocolConformanceRef::subst(Type origType,
88+
SubstitutionMap subMap) const {
89+
return subst(origType,
90+
QuerySubstitutionMap{subMap},
91+
LookUpConformanceInSubstitutionMap(subMap));
92+
}
93+
8494
ProtocolConformanceRef
8595
ProtocolConformanceRef::subst(Type origType,
8696
TypeSubstitutionFn subs,
8797
LookupConformanceFn conformances) const {
98+
if (isInvalid())
99+
return *this;
100+
88101
auto substType = origType.subst(subs, conformances,
89102
SubstFlags::UseErrorType);
90103

@@ -96,8 +109,7 @@ ProtocolConformanceRef::subst(Type origType,
96109
// If this is a class, we need to traffic in the actual type that
97110
// implements the protocol, not 'Self' and not any subclasses (with their
98111
// inherited conformances).
99-
substType =
100-
substType->eraseDynamicSelfType()->getSuperclassForDecl(classDecl);
112+
substType = substType->getSuperclassForDecl(classDecl);
101113
}
102114
return ProtocolConformanceRef(
103115
getConcrete()->subst(substType, subs, conformances));
@@ -130,6 +142,8 @@ ProtocolConformanceRef::getTypeWitnessByName(Type type,
130142
ProtocolConformanceRef conformance,
131143
Identifier name,
132144
LazyResolver *resolver) {
145+
assert(!conformance.isInvalid());
146+
133147
// Find the named requirement.
134148
AssociatedTypeDecl *assocType = nullptr;
135149
auto members = conformance.getRequirement()->lookupDirect(name);
@@ -739,9 +753,7 @@ ProtocolConformanceRef::getAssociatedConformance(Type conformingType,
739753
SubstitutionMap::getProtocolSubstitutions(getRequirement(),
740754
conformingType, *this);
741755
auto abstractConf = ProtocolConformanceRef(protocol);
742-
return abstractConf.subst(assocType,
743-
QuerySubstitutionMap{subMap},
744-
LookUpConformanceInSubstitutionMap(subMap));
756+
return abstractConf.subst(assocType, subMap);
745757
}
746758

747759
ProtocolConformanceRef
@@ -942,9 +954,7 @@ SpecializedProtocolConformance::getAssociatedConformance(Type assocType,
942954
? conformance.getConcrete()->getType()
943955
: GenericConformance->getAssociatedType(assocType, resolver));
944956

945-
return conformance.subst(origType,
946-
QuerySubstitutionMap{subMap},
947-
LookUpConformanceInSubstitutionMap(subMap));
957+
return conformance.subst(origType, subMap);
948958
}
949959

950960
ConcreteDeclRef
@@ -1027,6 +1037,14 @@ bool ProtocolConformance::isVisibleFrom(const DeclContext *dc) const {
10271037
return true;
10281038
}
10291039

1040+
ProtocolConformance *
1041+
ProtocolConformance::subst(Type substType,
1042+
SubstitutionMap subMap) const {
1043+
return subst(substType,
1044+
QuerySubstitutionMap{subMap},
1045+
LookUpConformanceInSubstitutionMap(subMap));
1046+
}
1047+
10301048
ProtocolConformance *
10311049
ProtocolConformance::subst(Type substType,
10321050
TypeSubstitutionFn subs,
@@ -1351,14 +1369,14 @@ ProtocolConformance *ProtocolConformance::getCanonicalConformance() {
13511369

13521370
/// Check of all types used by the conformance are canonical.
13531371
bool ProtocolConformanceRef::isCanonical() const {
1354-
if (isAbstract())
1372+
if (isAbstract() || isInvalid())
13551373
return true;
13561374
return getConcrete()->isCanonical();
13571375
}
13581376

13591377
ProtocolConformanceRef
13601378
ProtocolConformanceRef::getCanonicalConformanceRef() const {
1361-
if (isAbstract())
1379+
if (isAbstract() || isInvalid())
13621380
return *this;
13631381
return ProtocolConformanceRef(getConcrete()->getCanonicalConformance());
13641382
}

lib/AST/SubstitutionMap.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ SubstitutionMap SubstitutionMap::get(GenericSignature *genericSig,
224224
auto protoType = req.getSecondType()->castTo<ProtocolType>();
225225
auto proto = protoType->getDecl();
226226
auto conformance = lookupConformance(depTy, replacement, proto)
227-
.getValueOr(ProtocolConformanceRef(proto));
227+
.getValueOr(ProtocolConformanceRef::forInvalid());
228228
conformances.push_back(conformance);
229229
}
230230

@@ -369,6 +369,9 @@ SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const {
369369
continue;
370370
}
371371

372+
if (conformance->isInvalid())
373+
return conformance;
374+
372375
// If we've hit an abstract conformance, everything from here on out is
373376
// abstract.
374377
// FIXME: This may not always be true, but it holds for now.
@@ -444,7 +447,7 @@ SubstitutionMap SubstitutionMap::subst(TypeSubstitutionFn subs,
444447
ProtocolDecl *proto) ->Optional<ProtocolConformanceRef> {
445448
auto conformance =
446449
lookupConformance(dependentType, proto)
447-
.getValueOr(ProtocolConformanceRef(proto));
450+
.getValueOr(ProtocolConformanceRef::forInvalid());
448451
auto substType = dependentType.subst(*this, SubstFlags::UseErrorType);
449452
return conformance.subst(substType, subs, conformances);
450453
});
@@ -610,6 +613,9 @@ void SubstitutionMap::verify() const {
610613

611614
auto conformance = getConformances()[conformanceIndex];
612615

616+
if (conformance.isInvalid())
617+
continue;
618+
613619
// An existential type can have an abstract conformance to
614620
// AnyObject or an @objc protocol.
615621
if (conformance.isAbstract() &&

lib/SILGen/SILGenBuilder.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ MetatypeInst *SILGenBuilder::createMetatype(SILLocation loc, SILType metatype) {
7070
if (!decl)
7171
return false;
7272

73+
if (isa<ProtocolDecl>(decl))
74+
return false;
75+
7376
auto *genericSig = decl->getGenericSignature();
7477
if (!genericSig)
7578
return false;

lib/Sema/ConstraintSystem.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1998,9 +1998,14 @@ Type simplifyTypeImpl(ConstraintSystem &cs, Type type, Fn getFixedTypeFn) {
19981998
Type lookupBaseType = newBase->getWithoutSpecifierType();
19991999

20002000
if (lookupBaseType->mayHaveMembers()) {
2001-
auto subs = lookupBaseType->getContextSubstitutionMap(
2002-
cs.DC->getParentModule(),
2003-
assocType->getDeclContext());
2001+
auto *proto = assocType->getProtocol();
2002+
auto conformance = cs.DC->getParentModule()->lookupConformance(
2003+
lookupBaseType, proto);
2004+
if (!conformance)
2005+
return DependentMemberType::get(lookupBaseType, assocType);
2006+
2007+
auto subs = SubstitutionMap::getProtocolSubstitutions(
2008+
proto, lookupBaseType, *conformance);
20042009
auto result = assocType->getDeclaredInterfaceType().subst(subs);
20052010

20062011
if (result && !result->hasError())

lib/Serialization/Deserialization.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,10 @@ ProtocolConformanceRef ModuleFile::readConformance(
469469

470470
unsigned kind = Cursor.readRecord(next.ID, scratch);
471471
switch (kind) {
472+
case INVALID_PROTOCOL_CONFORMANCE: {
473+
return ProtocolConformanceRef::forInvalid();
474+
}
475+
472476
case ABSTRACT_PROTOCOL_CONFORMANCE: {
473477
DeclID protoID;
474478
AbstractProtocolConformanceLayout::readRecord(scratch, protoID);

lib/Serialization/SILFormat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ namespace sil_block {
179179
= decls_block::SPECIALIZED_PROTOCOL_CONFORMANCE,
180180
INHERITED_PROTOCOL_CONFORMANCE
181181
= decls_block::INHERITED_PROTOCOL_CONFORMANCE,
182+
INVALID_PROTOCOL_CONFORMANCE = decls_block::INVALID_PROTOCOL_CONFORMANCE,
182183
GENERIC_PARAM = decls_block::GENERIC_PARAM,
183184
GENERIC_REQUIREMENT = decls_block::GENERIC_REQUIREMENT,
184185
LAYOUT_REQUIREMENT = decls_block::LAYOUT_REQUIREMENT,

0 commit comments

Comments
 (0)