Skip to content

Commit 5c89eb8

Browse files
committed
[AST] Drop substitutions from type witnesses.
Nobody is using the actual substitutions, but we sure did a lot of work to cope with them.
1 parent f513ada commit 5c89eb8

19 files changed

+95
-206
lines changed

include/swift/AST/ProtocolConformance.h

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
#include "swift/AST/ConcreteDeclRef.h"
2020
#include "swift/AST/Decl.h"
21-
#include "swift/AST/Substitution.h"
21+
#include "swift/AST/SubstitutionList.h"
2222
#include "swift/AST/Type.h"
2323
#include "swift/AST/Types.h"
2424
#include "swift/AST/TypeAlignments.h"
@@ -48,9 +48,9 @@ typedef llvm::DenseMap<SubstitutableType *, Type> TypeSubstitutionMap;
4848
/// Map from non-type requirements to the corresponding conformance witnesses.
4949
typedef llvm::DenseMap<ValueDecl *, Witness> WitnessMap;
5050

51-
/// Map from associated type requirements to the corresponding substitution,
52-
/// which captures the replacement type along with any conformances it requires.
53-
typedef llvm::DenseMap<AssociatedTypeDecl *, std::pair<Substitution, TypeDecl*>>
51+
/// Map from associated type requirements to the corresponding type and
52+
/// the type declaration that was used to satisfy the requirement.
53+
typedef llvm::DenseMap<AssociatedTypeDecl *, std::pair<Type, TypeDecl*>>
5454
TypeWitnessMap;
5555

5656
/// Describes the kind of protocol conformance structure used to encode
@@ -96,7 +96,6 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {
9696

9797
/// \brief The interface type that conforms to the protocol.
9898
Type ConformingInterfaceType;
99-
10099

101100
protected:
102101
ProtocolConformance(ProtocolConformanceKind kind, Type conformingType,
@@ -144,21 +143,21 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {
144143
bool hasTypeWitness(AssociatedTypeDecl *assocType,
145144
LazyResolver *resolver = nullptr) const;
146145

147-
/// Retrieve the type witness substitution for the given associated type.
148-
const Substitution &getTypeWitness(AssociatedTypeDecl *assocType,
149-
LazyResolver *resolver) const;
146+
/// Retrieve the type witness for the given associated type.
147+
Type getTypeWitness(AssociatedTypeDecl *assocType,
148+
LazyResolver *resolver) const;
150149

151-
/// Retrieve the type witness substitution and type decl (if one exists)
150+
/// Retrieve the type witness and type decl (if one exists)
152151
/// for the given associated type.
153-
std::pair<const Substitution &, TypeDecl *>
154-
getTypeWitnessSubstAndDecl(AssociatedTypeDecl *assocType,
155-
LazyResolver *resolver) const;
152+
std::pair<Type, TypeDecl *>
153+
getTypeWitnessAndDecl(AssociatedTypeDecl *assocType,
154+
LazyResolver *resolver) const;
156155

157156
/// Apply the given function object to each type witness within this
158157
/// protocol conformance.
159158
///
160159
/// The function object should accept an \c AssociatedTypeDecl* for the
161-
/// requirement followed by the \c Substitution for the witness and a
160+
/// requirement followed by the \c Type for the witness and a
162161
/// (possibly null) \c TypeDecl* that explicitly declared the type.
163162
/// It should return true to indicate an early exit.
164163
///
@@ -175,7 +174,7 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {
175174
if (!resolver && !hasTypeWitness(assocTypeReq))
176175
continue;
177176

178-
const auto &TWInfo = getTypeWitnessSubstAndDecl(assocTypeReq, resolver);
177+
const auto &TWInfo = getTypeWitnessAndDecl(assocTypeReq, resolver);
179178
if (f(assocTypeReq, TWInfo.first, TWInfo.second))
180179
return true;
181180
}
@@ -331,7 +330,7 @@ class NormalProtocolConformance : public ProtocolConformance,
331330
/// the declarations that satisfy those requirements.
332331
mutable WitnessMap Mapping;
333332

334-
/// The mapping from associated type requirements to their substitutions.
333+
/// The mapping from associated type requirements to their types.
335334
mutable TypeWitnessMap TypeWitnesses;
336335

337336
/// Conformances that satisfy each of conformance requirements of the
@@ -422,11 +421,11 @@ class NormalProtocolConformance : public ProtocolConformance,
422421
return ContextAndInvalid.getPointer().dyn_cast<AbstractStorageDecl *>();
423422
}
424423

425-
/// Retrieve the type witness substitution and type decl (if one exists)
424+
/// Retrieve the type witness and type decl (if one exists)
426425
/// for the given associated type.
427-
std::pair<const Substitution &, TypeDecl *>
428-
getTypeWitnessSubstAndDecl(AssociatedTypeDecl *assocType,
429-
LazyResolver *resolver) const;
426+
std::pair<Type, TypeDecl *>
427+
getTypeWitnessAndDecl(AssociatedTypeDecl *assocType,
428+
LazyResolver *resolver) const;
430429

431430
/// Determine whether the protocol conformance has a type witness for the
432431
/// given associated type.
@@ -435,8 +434,7 @@ class NormalProtocolConformance : public ProtocolConformance,
435434

436435
/// Set the type witness for the given associated type.
437436
/// \param typeDecl the type decl the witness type came from, if one exists.
438-
void setTypeWitness(AssociatedTypeDecl *assocType,
439-
const Substitution &substitution,
437+
void setTypeWitness(AssociatedTypeDecl *assocType, Type type,
440438
TypeDecl *typeDecl) const;
441439

442440
/// Given that the requirement signature of the protocol directly states
@@ -479,7 +477,7 @@ class NormalProtocolConformance : public ProtocolConformance,
479477
/// Determine whether the witness for the given type requirement
480478
/// is the default definition.
481479
bool usesDefaultDefinition(AssociatedTypeDecl *requirement) const {
482-
return getTypeWitnessSubstAndDecl(requirement, nullptr)
480+
return getTypeWitnessAndDecl(requirement, nullptr)
483481
.second->isImplicit();
484482
}
485483

@@ -567,11 +565,11 @@ class SpecializedProtocolConformance : public ProtocolConformance,
567565
bool hasTypeWitness(AssociatedTypeDecl *assocType,
568566
LazyResolver *resolver = nullptr) const;
569567

570-
/// Retrieve the type witness substitution and type decl (if one exists)
568+
/// Retrieve the type witness and type decl (if one exists)
571569
/// for the given associated type.
572-
std::pair<const Substitution &, TypeDecl *>
573-
getTypeWitnessSubstAndDecl(AssociatedTypeDecl *assocType,
574-
LazyResolver *resolver) const;
570+
std::pair<Type, TypeDecl *>
571+
getTypeWitnessAndDecl(AssociatedTypeDecl *assocType,
572+
LazyResolver *resolver) const;
575573

576574
/// Retrieve the value witness corresponding to the given requirement.
577575
Witness getWitness(ValueDecl *requirement, LazyResolver *resolver) const;
@@ -668,12 +666,12 @@ class InheritedProtocolConformance : public ProtocolConformance,
668666
return InheritedConformance->hasTypeWitness(assocType, resolver);
669667
}
670668

671-
/// Retrieve the type witness substitution and type decl (if one exists)
669+
/// Retrieve the type witness and type decl (if one exists)
672670
/// for the given associated type.
673-
std::pair<const Substitution &, TypeDecl *>
674-
getTypeWitnessSubstAndDecl(AssociatedTypeDecl *assocType,
675-
LazyResolver *resolver) const {
676-
return InheritedConformance->getTypeWitnessSubstAndDecl(assocType,resolver);
671+
std::pair<Type, TypeDecl *>
672+
getTypeWitnessAndDecl(AssociatedTypeDecl *assocType,
673+
LazyResolver *resolver) const {
674+
return InheritedConformance->getTypeWitnessAndDecl(assocType, resolver);
677675
}
678676

679677
/// Retrieve the value witness corresponding to the given requirement.

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
5454
/// in source control, you should also update the comment to briefly
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.
57-
const uint16_t VERSION_MINOR = 330; // Last change: inherited conformances
57+
const uint16_t VERSION_MINOR = 331; // Last change: type witness substitutions
5858

5959
using DeclID = PointerEmbeddedInt<unsigned, 31>;
6060
using DeclIDField = BCFixed<31>;

lib/AST/ASTVerifier.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2016,8 +2016,7 @@ struct ASTNodeBase {};
20162016

20172017
// Make sure that the replacement type only uses archetypes allowed
20182018
// in the context where the normal conformance exists.
2019-
auto replacementType
2020-
= normal->getTypeWitness(assocType, nullptr).getReplacement();
2019+
auto replacementType = normal->getTypeWitness(assocType, nullptr);
20212020
Verifier(M, normal->getDeclContext())
20222021
.verifyChecked(replacementType);
20232022
continue;

lib/AST/ConformanceLookupTable.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1110,7 +1110,7 @@ ConformanceLookupTable::getSatisfiedProtocolRequirementsForMember(
11101110
continue;
11111111

11121112
conf->forEachTypeWitness(resolver, [&](const AssociatedTypeDecl *assoc,
1113-
const Substitution &subst,
1113+
Type type,
11141114
TypeDecl *typeDecl) -> bool {
11151115
if (typeDecl == member)
11161116
reqs.push_back(const_cast<AssociatedTypeDecl*>(assoc));

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,8 +1043,7 @@ static void maybeAddSameTypeRequirementForNestedType(
10431043
// Dig out the type witness.
10441044
auto superConformance = superSource->getProtocolConformance();
10451045
auto concreteType =
1046-
superConformance->getTypeWitness(assocType, builder.getLazyResolver())
1047-
.getReplacement();
1046+
superConformance->getTypeWitness(assocType, builder.getLazyResolver());
10481047
if (!concreteType) return;
10491048

10501049
// Add the same-type constraint.
@@ -1348,9 +1347,9 @@ static void concretizeNestedTypeFromConcreteParent(
13481347

13491348
Type witnessType;
13501349
if (conformance.isConcrete()) {
1351-
witnessType = conformance.getConcrete()
1352-
->getTypeWitness(assocType, builder.getLazyResolver())
1353-
.getReplacement();
1350+
witnessType =
1351+
conformance.getConcrete()
1352+
->getTypeWitness(assocType, builder.getLazyResolver());
13541353
} else {
13551354
witnessType = DependentMemberType::get(concreteParent, assocType);
13561355
}

lib/AST/ProtocolConformance.cpp

Lines changed: 22 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ ProtocolConformanceRef::getTypeWitnessByName(Type type,
187187
if (!concrete->hasTypeWitness(assocType, resolver)) {
188188
return nullptr;
189189
}
190-
return concrete->getTypeWitness(assocType, resolver).getReplacement();
190+
return concrete->getTypeWitness(assocType, resolver);
191191
}
192192

193193
void *ProtocolConformance::operator new(size_t bytes, ASTContext &context,
@@ -237,17 +237,15 @@ ProtocolConformance::hasTypeWitness(AssociatedTypeDecl *assocType,
237237
CONFORMANCE_SUBCLASS_DISPATCH(hasTypeWitness, (assocType, resolver));
238238
}
239239

240-
std::pair<const Substitution &, TypeDecl *>
241-
ProtocolConformance::getTypeWitnessSubstAndDecl(AssociatedTypeDecl *assocType,
240+
std::pair<Type, TypeDecl *>
241+
ProtocolConformance::getTypeWitnessAndDecl(AssociatedTypeDecl *assocType,
242242
LazyResolver *resolver) const {
243-
CONFORMANCE_SUBCLASS_DISPATCH(getTypeWitnessSubstAndDecl,
244-
(assocType, resolver))
243+
CONFORMANCE_SUBCLASS_DISPATCH(getTypeWitnessAndDecl, (assocType, resolver))
245244
}
246245

247-
const Substitution &
248-
ProtocolConformance::getTypeWitness(AssociatedTypeDecl *assocType,
249-
LazyResolver *resolver) const {
250-
return getTypeWitnessSubstAndDecl(assocType, resolver).first;
246+
Type ProtocolConformance::getTypeWitness(AssociatedTypeDecl *assocType,
247+
LazyResolver *resolver) const {
248+
return getTypeWitnessAndDecl(assocType, resolver).first;
251249
}
252250

253251
Witness ProtocolConformance::getWitness(ValueDecl *requirement,
@@ -363,10 +361,9 @@ bool NormalProtocolConformance::hasTypeWitness(AssociatedTypeDecl *assocType,
363361
return false;
364362
}
365363

366-
std::pair<const Substitution &, TypeDecl *>
367-
NormalProtocolConformance::getTypeWitnessSubstAndDecl(
368-
AssociatedTypeDecl *assocType,
369-
LazyResolver *resolver) const {
364+
std::pair<Type, TypeDecl *>
365+
NormalProtocolConformance::getTypeWitnessAndDecl(AssociatedTypeDecl *assocType,
366+
LazyResolver *resolver) const {
370367
if (Resolver)
371368
resolveLazyInfo();
372369

@@ -381,15 +378,14 @@ NormalProtocolConformance::getTypeWitnessSubstAndDecl(
381378
return known->second;
382379
}
383380

384-
void NormalProtocolConformance::setTypeWitness(
385-
AssociatedTypeDecl *assocType,
386-
const Substitution &substitution,
387-
TypeDecl *typeDecl) const {
381+
void NormalProtocolConformance::setTypeWitness(AssociatedTypeDecl *assocType,
382+
Type type,
383+
TypeDecl *typeDecl) const {
388384
assert(getProtocol() == cast<ProtocolDecl>(assocType->getDeclContext()) &&
389385
"associated type in wrong protocol");
390386
assert(TypeWitnesses.count(assocType) == 0 && "Type witness already known");
391387
assert((!isComplete() || isInvalid()) && "Conformance already complete?");
392-
TypeWitnesses[assocType] = std::make_pair(substitution, typeDecl);
388+
TypeWitnesses[assocType] = std::make_pair(type, typeDecl);
393389
}
394390

395391
Type ProtocolConformance::getAssociatedType(Type assocType,
@@ -421,7 +417,7 @@ Type ProtocolConformanceRef::getAssociatedType(Type conformingType,
421417
auto memberType = cast<DependentMemberType>(type);
422418
if (memberType.getBase()->isEqual(proto->getProtocolSelfType()) &&
423419
memberType->getAssocType()->getProtocol() == proto)
424-
return getTypeWitness(memberType->getAssocType(), nullptr).getReplacement();
420+
return getTypeWitness(memberType->getAssocType(), nullptr);
425421
#endif
426422

427423
// General case: consult the substitution map.
@@ -548,8 +544,8 @@ bool SpecializedProtocolConformance::hasTypeWitness(
548544
GenericConformance->hasTypeWitness(assocType, resolver);
549545
}
550546

551-
std::pair<const Substitution &, TypeDecl *>
552-
SpecializedProtocolConformance::getTypeWitnessSubstAndDecl(
547+
std::pair<Type, TypeDecl *>
548+
SpecializedProtocolConformance::getTypeWitnessAndDecl(
553549
AssociatedTypeDecl *assocType,
554550
LazyResolver *resolver) const {
555551
// If we've already created this type witness, return it.
@@ -565,49 +561,24 @@ SpecializedProtocolConformance::getTypeWitnessSubstAndDecl(
565561
genericEnv->getSubstitutionMap(GenericSubstitutions);
566562

567563
auto genericWitnessAndDecl
568-
= GenericConformance->getTypeWitnessSubstAndDecl(assocType, resolver);
564+
= GenericConformance->getTypeWitnessAndDecl(assocType, resolver);
569565

570566
auto &genericWitness = genericWitnessAndDecl.first;
571567
auto *typeDecl = genericWitnessAndDecl.second;
572568

573569
// Apply the substitution we computed above
574570
auto specializedType
575-
= genericWitness.getReplacement().subst(substitutionMap);
571+
= genericWitness.subst(substitutionMap);
576572
if (!specializedType)
577-
specializedType = ErrorType::get(genericWitness.getReplacement());
573+
specializedType = ErrorType::get(genericWitness);
578574

579575
// If the type witness was unchanged, just copy it directly.
580-
if (specializedType.getPointer() == genericWitness.getReplacement().getPointer()) {
576+
if (specializedType.getPointer() == genericWitness.getPointer()) {
581577
TypeWitnesses[assocType] = genericWitnessAndDecl;
582578
return TypeWitnesses[assocType];
583579
}
584580

585-
auto conformingDC = getDeclContext();
586-
auto conformingModule = conformingDC->getParentModule();
587-
588-
// Gather the conformances for the type witness. These should never fail.
589-
// FIXME: We should just be able to use the SubstitutionMap from above,
590-
// but we have no way to force inherited conformances to be filled in
591-
// through that mechanism.
592-
SmallVector<ProtocolConformanceRef, 4> conformances;
593-
for (auto proto : assocType->getConformingProtocols()) {
594-
auto conforms = conformingModule->lookupConformance(specializedType, proto,
595-
resolver);
596-
assert((conforms ||
597-
specializedType->isTypeVariableOrMember() ||
598-
specializedType->isTypeParameter() ||
599-
specializedType->hasError()) &&
600-
"Improperly checked substitution");
601-
conformances.push_back(conforms ? *conforms
602-
: ProtocolConformanceRef(proto));
603-
}
604-
605-
// Form the substitution.
606-
auto &ctx = assocType->getASTContext();
607-
TypeWitnesses[assocType] = std::make_pair(
608-
Substitution{specializedType,
609-
ctx.AllocateCopy(conformances)},
610-
typeDecl);
581+
TypeWitnesses[assocType] = std::make_pair(specializedType, typeDecl);
611582
return TypeWitnesses[assocType];
612583
}
613584

lib/AST/Type.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2818,8 +2818,8 @@ static Type getMemberForBaseType(LookupConformanceFn lookupConformances,
28182818
!conformance->getConcrete()->hasTypeWitness(assocType, nullptr))
28192819
return failed();
28202820

2821-
auto witness = conformance->getConcrete()
2822-
->getTypeWitness(assocType, resolver).getReplacement();
2821+
auto witness =
2822+
conformance->getConcrete()->getTypeWitness(assocType, resolver);
28232823

28242824
// This is a hacky feature allowing code completion to migrate to
28252825
// using Type::subst() without changing output.

lib/IDE/CodeCompletion.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2036,8 +2036,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
20362036
if (Conformance && Conformance->isConcrete()) {
20372037
return Conformance->getConcrete()
20382038
->getTypeWitness(const_cast<AssociatedTypeDecl *>(ATD),
2039-
TypeResolver.get())
2040-
.getReplacement();
2039+
TypeResolver.get());
20412040
}
20422041
}
20432042
}

lib/IRGen/GenProto.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -852,10 +852,10 @@ static bool isDependentConformance(IRGenModule &IGM,
852852

853853
// Check whether any of the associated types are dependent.
854854
if (conformance->forEachTypeWitness(nullptr,
855-
[&](AssociatedTypeDecl *requirement, const Substitution &sub,
855+
[&](AssociatedTypeDecl *requirement, Type type,
856856
TypeDecl *explicitDecl) -> bool {
857857
// RESILIENCE: this could be an opaque conformance
858-
return sub.getReplacement()->hasArchetype();
858+
return type->hasArchetype();
859859
})) {
860860
return true;
861861
}
@@ -1124,12 +1124,11 @@ class AccessorConformanceInfo : public ConformanceInfo {
11241124

11251125
SILEntries = SILEntries.slice(1);
11261126

1127-
const Substitution &sub =
1128-
Conformance.getTypeWitness(requirement, nullptr);
1127+
CanType associate =
1128+
Conformance.getTypeWitness(requirement, nullptr)->getCanonicalType();
11291129

11301130
// This type will be expressed in terms of the archetypes
11311131
// of the conforming context.
1132-
CanType associate = sub.getReplacement()->getCanonicalType();
11331132
assert(!associate->hasTypeParameter());
11341133

11351134
llvm::Constant *metadataAccessFunction =

0 commit comments

Comments
 (0)