Skip to content

Rework the relationship between generic environments and opaque archetypes #40747

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
60 changes: 54 additions & 6 deletions include/swift/AST/GenericEnvironment.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ namespace swift {
class ArchetypeType;
class ASTContext;
class GenericTypeParamType;
class OpaqueTypeDecl;
class OpenedArchetypeType;
class SILModule;
class SILType;

Expand All @@ -57,11 +59,28 @@ class QueryInterfaceTypeSubstitutions {
/// TypeBase::mapTypeOutOfContext().
///
class alignas(1 << DeclAlignInBits) GenericEnvironment final
: private llvm::TrailingObjects<GenericEnvironment, Type> {
GenericSignature Signature = GenericSignature();
: private llvm::TrailingObjects<
GenericEnvironment, OpaqueTypeDecl *, SubstitutionMap, Type> {
public:
enum class Kind {
/// A normal generic environment, determined only by its generic
/// signature.
Normal,
/// A generic environment describing an opened existential archetype.
OpenedExistential,
/// A generic environment describing an opaque type archetype.
Opaque,
};

private:
mutable llvm::PointerIntPair<GenericSignature, 2, Kind> SignatureAndKind{
GenericSignature(), Kind::Normal};

friend TrailingObjects;
friend OpaqueTypeArchetypeType;

size_t numTrailingObjects(OverloadToken<OpaqueTypeDecl *>) const;
size_t numTrailingObjects(OverloadToken<SubstitutionMap>) const;
size_t numTrailingObjects(OverloadToken<Type>) const;

/// Retrieve the array containing the context types associated with the
Expand All @@ -74,7 +93,9 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
/// generic signature.
ArrayRef<Type> getContextTypes() const;

explicit GenericEnvironment(GenericSignature signature);
explicit GenericEnvironment(GenericSignature signature, Kind kind);
explicit GenericEnvironment(
GenericSignature signature, OpaqueTypeDecl *opaque, SubstitutionMap subs);

friend ArchetypeType;
friend QueryInterfaceTypeSubstitutions;
Expand All @@ -86,18 +107,39 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
/// This is only useful when lazily populating a generic environment.
Optional<Type> getMappingIfPresent(GenericParamKey key) const;

/// Get the "raw" generic signature, without substituting into opaque
/// type's signature.
GenericSignature getRawGenericSignature() const;

public:
GenericSignature getGenericSignature() const {
return Signature;
}
GenericSignature getGenericSignature() const;

Kind getKind() const { return SignatureAndKind.getInt(); }

TypeArrayView<GenericTypeParamType> getGenericParams() const;

/// Retrieve the opaque type declaration for a generic environment describing
/// opaque types.
OpaqueTypeDecl *getOpaqueTypeDecl() const;

/// Retrieve the substitutions applied to an opaque type declaration to
/// create a generic environment.
SubstitutionMap getOpaqueSubstitutions() const;

/// Create a new, "incomplete" generic environment that will be populated
/// by calls to \c addMapping().
static
GenericEnvironment *getIncomplete(GenericSignature signature);

/// Create a new generic environment for an opened existential.
static GenericEnvironment *forOpenedExistential(
GenericSignature signature, const OpenedArchetypeType *type);

/// Create a new generic environment for an opaque type with the given set of
/// outer substitutions.
static GenericEnvironment *forOpaqueType(
OpaqueTypeDecl *opaque, SubstitutionMap subs, AllocationArena arena);

/// Add a mapping of a generic parameter to a specific type (which may be
/// an archetype)
void addMapping(GenericParamKey key, Type contextType);
Expand All @@ -112,6 +154,12 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
return Mem;
}

/// For an opaque archetype environment, apply the substitutions.
Type maybeApplyOpaqueTypeSubstitutions(Type type) const;

/// Compute the canonical interface type within this environment.
Type getCanonicalInterfaceType(Type interfaceType);

/// Map an interface type to a contextual type.
static Type mapTypeIntoContext(GenericEnvironment *genericEnv,
Type type);
Expand Down
63 changes: 27 additions & 36 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -5548,48 +5548,49 @@ END_CAN_TYPE_WRAPPER(PrimaryArchetypeType, ArchetypeType)

/// An archetype that represents an opaque type.
class OpaqueTypeArchetypeType final : public ArchetypeType,
public llvm::FoldingSetNode,
private ArchetypeTrailingObjects<OpaqueTypeArchetypeType>
{
friend TrailingObjects;
friend ArchetypeType;
friend GenericSignatureBuilder;

/// The declaration that defines the opaque type.
OpaqueTypeDecl *OpaqueDecl;
/// The substitutions into the interface signature of the opaque type.
SubstitutionMap Substitutions;

/// A GenericEnvironment with this opaque archetype bound to the interface
/// type of the output type from the OpaqueDecl.
GenericEnvironment *Environment;

GenericEnvironment *Environment = nullptr;

friend class GenericEnvironment;

static OpaqueTypeArchetypeType *getNew(
GenericEnvironment *environment, Type interfaceType,
ArrayRef<ProtocolDecl*> conformsTo, Type superclass,
LayoutConstraint layout);

public:
/// Get an opaque archetype representing the underlying type of the given
/// opaque type decl's opaque param with ordinal `ordinal`. For example, in
/// `(some P, some Q)`, `some P`'s type param would have ordinal 0 and `some
/// Q`'s type param would have ordinal 1.
static OpaqueTypeArchetypeType *get(OpaqueTypeDecl *Decl, unsigned ordinal,
SubstitutionMap Substitutions);
static Type get(OpaqueTypeDecl *decl, unsigned ordinal, SubstitutionMap subs);

/// Retrieve the opaque type declaration.
OpaqueTypeDecl *getDecl() const;

/// Retrieve the set of substitutions applied to the opaque type.
SubstitutionMap getSubstitutions() const;

OpaqueTypeDecl *getDecl() const {
return OpaqueDecl;
}
SubstitutionMap getSubstitutions() const {
return Substitutions;
}

/// Get the generic signature used to build out this archetype. This is
/// equivalent to the OpaqueTypeDecl's interface generic signature, with
/// all of the generic parameters aside from the opaque type's interface
/// type same-type-constrained to their substitutions for this type.
GenericSignature getBoundSignature() const;

/// Get a generic environment that has this opaque archetype bound within it.
GenericEnvironment *getGenericEnvironment() const {
return Environment;
}

GenericEnvironment *getGenericEnvironment() const;

/// Compute the canonical interface type within the environment of this
/// opaque type archetype.
CanType getCanonicalInterfaceType(Type interfaceType);

static bool classof(const TypeBase *T) {
return T->getKind() == TypeKind::OpaqueTypeArchetype;
}
Expand All @@ -5603,22 +5604,12 @@ class OpaqueTypeArchetypeType final : public ArchetypeType,
/// then the underlying type of `some P` would be ordinal 0, and `some Q` would be ordinal 1.
unsigned getOrdinal() const;

static void Profile(llvm::FoldingSetNodeID &ID,
OpaqueTypeDecl *OpaqueDecl,
unsigned ordinal,
SubstitutionMap Substitutions);

void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getDecl(), getOrdinal(), getSubstitutions());
};

private:
OpaqueTypeArchetypeType(OpaqueTypeDecl *OpaqueDecl,
SubstitutionMap Substitutions,
RecursiveTypeProperties Props,
Type InterfaceType,
ArrayRef<ProtocolDecl*> ConformsTo,
Type Superclass, LayoutConstraint Layout);
OpaqueTypeArchetypeType(GenericEnvironment *environment,
RecursiveTypeProperties properties,
Type interfaceType,
ArrayRef<ProtocolDecl*> conformsTo,
Type superclass, LayoutConstraint layout);
};
BEGIN_CAN_TYPE_WRAPPER(OpaqueTypeArchetypeType, ArchetypeType)
END_CAN_TYPE_WRAPPER(OpaqueTypeArchetypeType, ArchetypeType)
Expand Down
Loading