Skip to content

Commit cf0fdc0

Browse files
committed
AST: Add new implementation of getOpenedExistentialSignature()
This will replace all existing usages of the old implementation.
1 parent 44dbebd commit cf0fdc0

File tree

2 files changed

+89
-4
lines changed

2 files changed

+89
-4
lines changed

include/swift/AST/ASTContext.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,30 @@ class MissingWitnessesBase {
220220
virtual ~MissingWitnessesBase();
221221
};
222222

223+
/// Return value of ASTContext::getOpenedExistentialSignature().
224+
struct OpenedExistentialSignature {
225+
/// The generalized existential type.
226+
///
227+
/// The actual generic arguments of superclass and parameterized protocol
228+
/// types become fresh generic parameters in the generalization signature.
229+
CanType Shape;
230+
231+
/// A substitution map sending each generic parameter of the generalization
232+
/// signature to the corresponding generic argument in the original
233+
/// existential type. May contain type variables.
234+
SubstitutionMap Generalization;
235+
236+
/// The opened existential signature derived from the generalization signature.
237+
///
238+
/// This is the generalization signature with one more generic parameter
239+
/// `Self` at the next highest depth, subject to the requirement
240+
/// `Self: Shape`, where `Shape` is above.
241+
CanGenericSignature OpenedSig;
242+
243+
/// The `Self` parameter in the opened existential signature.
244+
CanType SelfType;
245+
};
246+
223247
/// ASTContext - This object creates and owns the AST objects.
224248
/// However, this class does more than just maintain context within an AST.
225249
/// It is the closest thing to thread-local or compile-local storage in this
@@ -1435,6 +1459,18 @@ class ASTContext final {
14351459
CanGenericSignature getOpenedExistentialSignature(Type type,
14361460
GenericSignature parentSig);
14371461

1462+
/// Retrieve a generic signature with a single type parameter conforming
1463+
/// to the given protocol or composition type, like <T: P>.
1464+
///
1465+
/// The opened archetype may have a different set of conformances from the
1466+
/// corresponding existential. The opened archetype conformances are dictated
1467+
/// by the ABI for generic arguments, while the existential value conformances
1468+
/// are dictated by their layout (see \c Type::getExistentialLayout()). In
1469+
/// particular, the opened archetype signature does not have requirements for
1470+
/// conformances inherited from superclass constraints while existential
1471+
/// values do.
1472+
OpenedExistentialSignature getOpenedExistentialSignature(Type type);
1473+
14381474
/// Get a generic signature where the generic parameter τ_d_i represents
14391475
/// the element of the pack generic parameter τ_d_i… in \p baseGenericSig.
14401476
///

lib/AST/ASTContext.cpp

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -557,8 +557,11 @@ struct ASTContext::Implementation {
557557
llvm::FoldingSet<LayoutConstraintInfo> LayoutConstraints;
558558
llvm::DenseMap<std::pair<OpaqueTypeDecl *, SubstitutionMap>,
559559
GenericEnvironment *> OpaqueArchetypeEnvironments;
560-
llvm::DenseMap<OpenedExistentialKey, GenericEnvironment *>
561-
OpenedExistentialEnvironments;
560+
561+
llvm::DenseMap<CanType,
562+
OpenedExistentialSignature> ExistentialSignatures;
563+
llvm::DenseMap<OpenedExistentialKey,
564+
GenericEnvironment *> OpenedExistentialEnvironments;
562565

563566
/// The set of function types.
564567
llvm::FoldingSet<FunctionType> FunctionTypes;
@@ -6156,12 +6159,58 @@ ASTContext::getOpenedExistentialSignature(Type type, GenericSignature parentSig)
61566159

61576160
auto result = getImpl().ExistentialSignatures.insert(
61586161
std::make_pair(key, genericSig));
6159-
assert(result.second);
6160-
(void) result;
6162+
ASSERT(result.second);
61616163

61626164
return genericSig;
61636165
}
61646166

6167+
OpenedExistentialSignature
6168+
ASTContext::getOpenedExistentialSignature(Type type) {
6169+
assert(type->isExistentialType());
6170+
6171+
if (auto existential = type->getAs<ExistentialType>())
6172+
type = existential->getConstraintType();
6173+
6174+
const CanType constraint = type->getCanonicalType();
6175+
6176+
// The constraint type might contain type variables.
6177+
auto properties = constraint->getRecursiveProperties();
6178+
auto arena = getArena(properties);
6179+
6180+
// Check the cache.
6181+
const auto &sigs = getImpl().getArena(arena).ExistentialSignatures;
6182+
auto found = sigs.find(constraint);
6183+
if (found != sigs.end())
6184+
return found->second;
6185+
6186+
OpenedExistentialSignature existentialSig;
6187+
6188+
// Generalize the existential type, to move type variables and primary
6189+
// archetypes into the substitution map.
6190+
auto gen = ExistentialTypeGeneralization::get(constraint);
6191+
existentialSig.Shape = gen.Shape->getCanonicalType();
6192+
existentialSig.Generalization = gen.Generalization;
6193+
6194+
// Now, we have an existential type written with type parameters only.
6195+
// Open the generalization signature by adding a new generic parameter
6196+
// for `Self`.
6197+
auto parentSig = gen.Generalization.getGenericSignature();
6198+
existentialSig.OpenedSig =
6199+
getOpenedExistentialSignature(gen.Shape, parentSig);
6200+
6201+
// Stash the `Self` type.
6202+
existentialSig.SelfType =
6203+
OpenedArchetypeType::getSelfInterfaceTypeFromContext(parentSig, *this)
6204+
->getCanonicalType();
6205+
6206+
// Cache the result.
6207+
auto result = getImpl().getArena(arena).ExistentialSignatures.insert(
6208+
std::make_pair(constraint, existentialSig));
6209+
ASSERT(result.second);
6210+
6211+
return existentialSig;
6212+
}
6213+
61656214
CanGenericSignature
61666215
ASTContext::getOpenedElementSignature(CanGenericSignature baseGenericSig,
61676216
CanGenericTypeParamType shapeClass) {

0 commit comments

Comments
 (0)