Skip to content

AST: Add new implementation of getOpenedExistentialSignature() #76206

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,30 @@ class MissingWitnessesBase {
virtual ~MissingWitnessesBase();
};

/// Return value of ASTContext::getOpenedExistentialSignature().
struct OpenedExistentialSignature {
/// The generalized existential type.
///
/// The actual generic arguments of superclass and parameterized protocol
/// types become fresh generic parameters in the generalization signature.
CanType Shape;

/// A substitution map sending each generic parameter of the generalization
/// signature to the corresponding generic argument in the original
/// existential type. May contain type variables.
SubstitutionMap Generalization;

/// The opened existential signature derived from the generalization signature.
///
/// This is the generalization signature with one more generic parameter
/// `Self` at the next highest depth, subject to the requirement
/// `Self: Shape`, where `Shape` is above.
CanGenericSignature OpenedSig;

/// The `Self` parameter in the opened existential signature.
CanType SelfType;
};

/// ASTContext - This object creates and owns the AST objects.
/// However, this class does more than just maintain context within an AST.
/// It is the closest thing to thread-local or compile-local storage in this
Expand Down Expand Up @@ -1435,6 +1459,18 @@ class ASTContext final {
CanGenericSignature getOpenedExistentialSignature(Type type,
GenericSignature parentSig);

/// Retrieve a generic signature with a single type parameter conforming
/// to the given protocol or composition type, like <T: P>.
///
/// The opened archetype may have a different set of conformances from the
/// corresponding existential. The opened archetype conformances are dictated
/// by the ABI for generic arguments, while the existential value conformances
/// are dictated by their layout (see \c Type::getExistentialLayout()). In
/// particular, the opened archetype signature does not have requirements for
/// conformances inherited from superclass constraints while existential
/// values do.
OpenedExistentialSignature getOpenedExistentialSignature(Type type);

/// Get a generic signature where the generic parameter τ_d_i represents
/// the element of the pack generic parameter τ_d_i… in \p baseGenericSig.
///
Expand Down
16 changes: 4 additions & 12 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3335,16 +3335,8 @@ class ValueDecl : public Decl {
/// that this declaration dynamically replaces.
ValueDecl *getDynamicallyReplacedDecl() const;

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

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

inline void
Expand Down
4 changes: 2 additions & 2 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ class alignas(1 << TypeAlignInBits) TypeBase
/// Canonical protocol composition types are minimized only to a certain
/// degree to preserve ABI compatibility. This routine enables performing
/// slower, but stricter minimization at need (e.g. redeclaration checking).
CanType getMinimalCanonicalType(const DeclContext *useDC) const;
CanType getMinimalCanonicalType() const;

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

/// Retrieve the set of members composed to create this type.
///
Expand Down
57 changes: 53 additions & 4 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -557,8 +557,11 @@ struct ASTContext::Implementation {
llvm::FoldingSet<LayoutConstraintInfo> LayoutConstraints;
llvm::DenseMap<std::pair<OpaqueTypeDecl *, SubstitutionMap>,
GenericEnvironment *> OpaqueArchetypeEnvironments;
llvm::DenseMap<OpenedExistentialKey, GenericEnvironment *>
OpenedExistentialEnvironments;

llvm::DenseMap<CanType,
OpenedExistentialSignature> ExistentialSignatures;
llvm::DenseMap<OpenedExistentialKey,
GenericEnvironment *> OpenedExistentialEnvironments;

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

auto result = getImpl().ExistentialSignatures.insert(
std::make_pair(key, genericSig));
assert(result.second);
(void) result;
ASSERT(result.second);

return genericSig;
}

OpenedExistentialSignature
ASTContext::getOpenedExistentialSignature(Type type) {
assert(type->isExistentialType());

if (auto existential = type->getAs<ExistentialType>())
type = existential->getConstraintType();

const CanType constraint = type->getCanonicalType();

// The constraint type might contain type variables.
auto properties = constraint->getRecursiveProperties();
auto arena = getArena(properties);

// Check the cache.
const auto &sigs = getImpl().getArena(arena).ExistentialSignatures;
auto found = sigs.find(constraint);
if (found != sigs.end())
return found->second;

OpenedExistentialSignature existentialSig;

// Generalize the existential type, to move type variables and primary
// archetypes into the substitution map.
auto gen = ExistentialTypeGeneralization::get(constraint);
existentialSig.Shape = gen.Shape->getCanonicalType();
existentialSig.Generalization = gen.Generalization;

// Now, we have an existential type written with type parameters only.
// Open the generalization signature by adding a new generic parameter
// for `Self`.
auto parentSig = gen.Generalization.getGenericSignature();
existentialSig.OpenedSig =
getOpenedExistentialSignature(gen.Shape, parentSig);

// Stash the `Self` type.
existentialSig.SelfType =
OpenedArchetypeType::getSelfInterfaceTypeFromContext(parentSig, *this)
->getCanonicalType();

// Cache the result.
auto result = getImpl().getArena(arena).ExistentialSignatures.insert(
std::make_pair(constraint, existentialSig));
ASSERT(result.second);

return existentialSig;
}

CanGenericSignature
ASTContext::getOpenedElementSignature(CanGenericSignature baseGenericSig,
CanGenericTypeParamType shapeClass) {
Expand Down
Loading