Skip to content

Commit ba585fd

Browse files
authored
Merge pull request #76206 from slavapestov/existential-signature-rework-part-1
AST: Add new implementation of getOpenedExistentialSignature()
2 parents b3c13e4 + 39d77b8 commit ba585fd

15 files changed

+388
-232
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
///

include/swift/AST/Decl.h

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3335,16 +3335,8 @@ class ValueDecl : public Decl {
33353335
/// that this declaration dynamically replaces.
33363336
ValueDecl *getDynamicallyReplacedDecl() const;
33373337

3338-
/// Find references to 'Self' in the type signature of this declaration in the
3339-
/// context of the given existential base type.
3340-
///
3341-
/// \param treatNonResultCovariantSelfAsInvariant When set, covariant 'Self'
3342-
/// references that are not in covariant result type position are considered
3343-
/// invariant. This position is the uncurried interface type of a declaration,
3344-
/// stripped of any optionality. For example, this is true for 'Self' in
3345-
/// 'func foo(Int) -> () -> Self?'.
3346-
GenericParameterReferenceInfo findExistentialSelfReferences(
3347-
Type baseTy, bool treatNonResultCovariantSelfAsInvariant) const;
3338+
/// Find references to 'Self' in the type signature of this declaration.
3339+
GenericParameterReferenceInfo findExistentialSelfReferences() const;
33483340
};
33493341

33503342
/// This is a common base class for declarations which declare a type.
@@ -9532,8 +9524,8 @@ class MacroExpansionDecl : public Decl, public FreestandingMacroExpansion {
95329524
/// specifies the index of the parameter that shall be skipped.
95339525
GenericParameterReferenceInfo
95349526
findGenericParameterReferences(const ValueDecl *value, CanGenericSignature sig,
9535-
GenericTypeParamType *genericParam,
9536-
bool treatNonResultCovarianceAsInvariant,
9527+
GenericTypeParamType *origParam,
9528+
GenericTypeParamType *openedParam,
95379529
std::optional<unsigned> skipParamIndex);
95389530

95399531
inline void

include/swift/AST/Types.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ class alignas(1 << TypeAlignInBits) TypeBase
587587
/// Canonical protocol composition types are minimized only to a certain
588588
/// degree to preserve ABI compatibility. This routine enables performing
589589
/// slower, but stricter minimization at need (e.g. redeclaration checking).
590-
CanType getMinimalCanonicalType(const DeclContext *useDC) const;
590+
CanType getMinimalCanonicalType() const;
591591

592592
/// Reconstitute type sugar, e.g., for array types, dictionary
593593
/// types, optionals, etc.
@@ -6139,7 +6139,7 @@ class ProtocolCompositionType final : public TypeBase,
61396139
/// Canonical protocol composition types are minimized only to a certain
61406140
/// degree to preserve ABI compatibility. This routine enables performing
61416141
/// slower, but stricter minimization at need (e.g. redeclaration checking).
6142-
CanType getMinimalCanonicalType(const DeclContext *useDC) const;
6142+
CanType getMinimalCanonicalType() const;
61436143

61446144
/// Retrieve the set of members composed to create this type.
61456145
///

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;
@@ -6157,12 +6160,58 @@ ASTContext::getOpenedExistentialSignature(Type type, GenericSignature parentSig)
61576160

61586161
auto result = getImpl().ExistentialSignatures.insert(
61596162
std::make_pair(key, genericSig));
6160-
assert(result.second);
6161-
(void) result;
6163+
ASSERT(result.second);
61626164

61636165
return genericSig;
61646166
}
61656167

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

0 commit comments

Comments
 (0)