mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
362 lines
13 KiB
C++
362 lines
13 KiB
C++
//===--- GenericEnvironment.h - Generic Environment AST ---------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the GenericEnvironment class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_AST_GENERIC_ENVIRONMENT_H
|
|
#define SWIFT_AST_GENERIC_ENVIRONMENT_H
|
|
|
|
#include "swift/AST/SubstitutionMap.h"
|
|
#include "swift/AST/GenericParamKey.h"
|
|
#include "swift/AST/GenericParamList.h"
|
|
#include "swift/AST/GenericSignature.h"
|
|
#include "swift/Basic/Compiler.h"
|
|
#include "swift/Basic/Debug.h"
|
|
#include "swift/Basic/UUID.h"
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/TrailingObjects.h"
|
|
#include <utility>
|
|
|
|
namespace swift {
|
|
|
|
class ArchetypeType;
|
|
class ASTContext;
|
|
class GenericTypeParamType;
|
|
class OpaqueTypeDecl;
|
|
class ElementArchetypeType;
|
|
class ExistentialArchetypeType;
|
|
class PackArchetypeType;
|
|
class PackExpansionType;
|
|
class SILModule;
|
|
class SILType;
|
|
template <class> class CanTypeWrapper;
|
|
|
|
/// Query function suitable for use as a \c TypeSubstitutionFn that queries
|
|
/// the mapping of interface types to archetypes.
|
|
class QueryInterfaceTypeSubstitutions {
|
|
const GenericEnvironment *self;
|
|
|
|
public:
|
|
QueryInterfaceTypeSubstitutions(const GenericEnvironment *self)
|
|
: self(self) { }
|
|
|
|
Type operator()(SubstitutableType *type) const;
|
|
};
|
|
|
|
/// Extra data in a generic environment for an opaque type.
|
|
struct OpaqueEnvironmentData {
|
|
OpaqueTypeDecl *decl;
|
|
};
|
|
|
|
/// Extra data in a generic environment for an opened existential.
|
|
struct ExistentialEnvironmentData {
|
|
Type existential;
|
|
UUID uuid;
|
|
};
|
|
|
|
/// Extra data in a generic environment for an opened pack element.
|
|
struct ElementEnvironmentData {
|
|
UUID uuid;
|
|
CanGenericTypeParamType shapeClass;
|
|
};
|
|
|
|
/// Describes the mapping between archetypes and interface types for the
|
|
/// generic parameters of a DeclContext.
|
|
///
|
|
/// The most frequently used method here is mapTypeIntoEnvironment(), which
|
|
/// maps an interface type to a type written in terms of the generic
|
|
/// environment's archetypes; to go in the other direction, use
|
|
/// TypeBase::mapTypeOutOfEnvironment().
|
|
///
|
|
class alignas(1 << DeclAlignInBits) GenericEnvironment final
|
|
: private llvm::TrailingObjects<
|
|
GenericEnvironment,
|
|
SubstitutionMap,
|
|
OpaqueEnvironmentData,
|
|
ExistentialEnvironmentData,
|
|
ElementEnvironmentData,
|
|
Type> {
|
|
public:
|
|
enum class Kind: uint8_t {
|
|
/// A normal generic environment, determined only by its generic
|
|
/// signature.
|
|
Primary,
|
|
/// A generic environment describing an opaque type archetype.
|
|
Opaque,
|
|
/// A generic environment describing an opened existential archetype.
|
|
Existential,
|
|
/// A generic environment describing an opened element type of a
|
|
/// pack archetype inside a pack expansion expression.
|
|
Element,
|
|
};
|
|
|
|
class NestedTypeStorage;
|
|
|
|
private:
|
|
GenericSignature sig;
|
|
NestedTypeStorage *nestedTypeStorage = nullptr;
|
|
Kind kind;
|
|
bool canonical;
|
|
|
|
friend TrailingObjects;
|
|
friend OpaqueTypeArchetypeType;
|
|
|
|
size_t numTrailingObjects(OverloadToken<SubstitutionMap>) const;
|
|
size_t numTrailingObjects(OverloadToken<OpaqueEnvironmentData>) const;
|
|
size_t numTrailingObjects(OverloadToken<ExistentialEnvironmentData>) const;
|
|
size_t numTrailingObjects(OverloadToken<ElementEnvironmentData>) const;
|
|
size_t numTrailingObjects(OverloadToken<Type>) const;
|
|
|
|
/// Retrieve the array containing the context types associated with the
|
|
/// generic parameters, stored in parallel with the generic parameters of the
|
|
/// generic signature.
|
|
MutableArrayRef<Type> getContextTypes();
|
|
|
|
/// Retrieve the array containing the context types associated with the
|
|
/// generic parameters, stored in parallel with the generic parameters of the
|
|
/// generic signature.
|
|
ArrayRef<Type> getContextTypes() const;
|
|
|
|
/// Retrieve the array of opened pack parameters for this opened-element
|
|
/// environment. This is parallel to the array of element parameters,
|
|
/// i.e. the innermost generic context.
|
|
MutableArrayRef<Type> getOpenedPackParams();
|
|
ArrayRef<Type> getOpenedPackParams() const;
|
|
|
|
/// Get the nested type storage, allocating it if required.
|
|
NestedTypeStorage &getOrCreateNestedTypeStorage();
|
|
|
|
/// Private constructor for primary environments.
|
|
explicit GenericEnvironment(GenericSignature signature);
|
|
|
|
/// Private constructor for opaque type environments.
|
|
explicit GenericEnvironment(
|
|
GenericSignature signature, OpaqueTypeDecl *opaque, SubstitutionMap subs);
|
|
|
|
/// Private constructor for opened existential environments.
|
|
explicit GenericEnvironment(
|
|
GenericSignature signature, Type existential, SubstitutionMap subs, UUID uuid);
|
|
|
|
/// Private constructor for opened element environments.
|
|
explicit GenericEnvironment(GenericSignature signature,
|
|
UUID uuid,
|
|
CanGenericTypeParamType shapeClass,
|
|
SubstitutionMap outerSubs);
|
|
|
|
friend ArchetypeType;
|
|
friend QueryInterfaceTypeSubstitutions;
|
|
|
|
/// Add a mapping of a type parameter to a contextual type, usually
|
|
/// an archetype.
|
|
void addMapping(CanType depType, Type contextType);
|
|
|
|
/// Retrieve the mapping for the given type parameter, if present.
|
|
///
|
|
/// This is only useful when lazily populating a generic environment.
|
|
Type getMappingIfPresent(CanType depType) const;
|
|
|
|
public:
|
|
GenericSignature getGenericSignature() const {
|
|
return sig;
|
|
}
|
|
|
|
Kind getKind() const { return kind; }
|
|
|
|
/// Returns if the archetypes from this environment are canonical types.
|
|
bool isCanonical() const { return canonical; }
|
|
|
|
ArrayRef<GenericTypeParamType *> getGenericParams() const;
|
|
|
|
/// Retrieve the existential type for an opened existential environment.
|
|
Type getOpenedExistentialType() const;
|
|
|
|
/// Retrieve the UUID for an opened existential environment.
|
|
UUID getOpenedExistentialUUID() const;
|
|
|
|
/// Retrieve the opaque type declaration for a generic environment describing
|
|
/// opaque types.
|
|
OpaqueTypeDecl *getOpaqueTypeDecl() const;
|
|
|
|
/// Retrieve the outer substitutions for an opaque or local environment.
|
|
///
|
|
/// Applying a substitution map to a local or opaque archetype outputs
|
|
/// an archetype with the same interface type, and composed outer
|
|
/// substitutions.
|
|
SubstitutionMap getOuterSubstitutions() const;
|
|
|
|
/// Retrieve the shape equivalence class for an opened element environment.
|
|
/// This is always a pack parameter.
|
|
CanGenericTypeParamType getOpenedElementShapeClass() const;
|
|
|
|
/// Retrieve the UUID for an opened element environment.
|
|
UUID getOpenedElementUUID() const;
|
|
|
|
/// Return the number of opened pack parameters.
|
|
unsigned getNumOpenedPackParams() const;
|
|
|
|
void forEachPackElementArchetype(
|
|
llvm::function_ref<void(ElementArchetypeType*)> function) const;
|
|
|
|
void forEachPackElementGenericTypeParam(
|
|
llvm::function_ref<void(GenericTypeParamType *)> function) const;
|
|
|
|
using PackElementBindingCallback =
|
|
llvm::function_ref<void(ElementArchetypeType *elementType,
|
|
PackType *packSubstitution)>;
|
|
|
|
/// Given that this is an opened element environment, iterate the
|
|
/// opened pack element bindings: the pack archetype that's been opened
|
|
/// (which may not be meaningful in the surrounding context), the element
|
|
/// archetype that it has been opened as, and the pack type whose elements
|
|
/// are opened.
|
|
void forEachPackElementBinding(PackElementBindingCallback function) const;
|
|
|
|
/// Create a new, primary generic environment.
|
|
static GenericEnvironment *forPrimary(GenericSignature signature);
|
|
|
|
/// Create a new generic environment for an opaque type with the given set of
|
|
/// outer substitutions.
|
|
static GenericEnvironment *forOpaqueType(
|
|
OpaqueTypeDecl *opaque, SubstitutionMap subs);
|
|
|
|
/// Create a new generic environment for an opened existential.
|
|
///
|
|
/// \param existential The subject existential type
|
|
/// \param uuid The unique identifier for this opened existential
|
|
static GenericEnvironment *
|
|
forOpenedExistential(Type existential, UUID uuid);
|
|
|
|
/// Create a new generic environment for an opened existential.
|
|
///
|
|
/// \param signature The opened existential signature
|
|
/// \param existential The generalized existential type
|
|
/// \param outerSubs The substitution map containing archetypes from the
|
|
/// outer generic context
|
|
/// \param uuid The unique identifier for this opened existential
|
|
static GenericEnvironment *
|
|
forOpenedExistential(GenericSignature signature,
|
|
Type existential, SubstitutionMap outerSubs,
|
|
UUID uuid);
|
|
|
|
/// Create a new generic environment for an opened element.
|
|
///
|
|
/// \param signature The opened element signature, which is the same as the
|
|
/// signature of the context whose element type is being opened, but with
|
|
/// the pack parameter bit erased from one or more generic parameters
|
|
/// \param uuid The unique identifier for this opened element
|
|
/// \param shapeClass The shape equivalence class for the originating packs
|
|
/// \param outerSubs The substitution map containing archetypes from the
|
|
/// outer generic context
|
|
static GenericEnvironment *
|
|
forOpenedElement(GenericSignature signature,
|
|
UUID uuid, CanGenericTypeParamType shapeClass,
|
|
SubstitutionMap outerSubs);
|
|
|
|
/// Make vanilla new/delete illegal.
|
|
void *operator new(size_t Bytes) = delete;
|
|
void operator delete(void *Data) = delete;
|
|
|
|
/// Only allow placement new.
|
|
void *operator new(size_t Bytes, void *Mem) {
|
|
assert(Mem);
|
|
return Mem;
|
|
}
|
|
|
|
/// For an opaque or pack element archetype environment, apply the
|
|
/// substitutions.
|
|
Type maybeApplyOuterContextSubstitutions(Type type) const;
|
|
|
|
/// Map an interface type to a contextual type.
|
|
static Type mapTypeIntoEnvironment(GenericEnvironment *genericEnv,
|
|
Type type);
|
|
|
|
/// Map an interface type to a contextual type.
|
|
Type mapTypeIntoEnvironment(Type type) const;
|
|
|
|
/// Map a generic parameter type to a contextual type.
|
|
Type mapTypeIntoEnvironment(GenericTypeParamType *type) const;
|
|
|
|
/// Map a type parameter type to a contextual type.
|
|
Type getOrCreateArchetypeFromInterfaceType(Type depType);
|
|
|
|
/// Map an interface type containing parameter packs to a contextual
|
|
/// type in the opened element generic context.
|
|
Type mapPackTypeIntoElementContext(Type type) const;
|
|
|
|
/// Map a contextual type containing parameter packs to a contextual
|
|
/// type in the opened element generic context.
|
|
///
|
|
/// This operation only makes sense if the generic environment that the
|
|
/// pack archetypes are contextual in matches the generic signature
|
|
/// of this environment. That will be true for opened element
|
|
/// environments coming straight out of the type checker, such as
|
|
/// the one in a PackExpansionExpr, or opened element environments
|
|
/// created directly from the current environment. It is not
|
|
/// reliable for opened element environments in arbitrary SIL functions.
|
|
Type mapContextualPackTypeIntoElementContext(Type type) const;
|
|
|
|
/// Map a contextual type containing parameter packs to a contextual
|
|
/// type in the opened element generic context.
|
|
///
|
|
/// This operation only makes sense if the generic environment that the
|
|
/// pack archetypes are contextual in matches the generic signature
|
|
/// of this environment. That will be true for opened element
|
|
/// environments coming straight out of the type checker, such as
|
|
/// the one in a PackExpansionExpr, or opened element environments
|
|
/// created directly from the current environment. It is not
|
|
/// reliable for opened element environments in arbitrary SIL functions.
|
|
CanType mapContextualPackTypeIntoElementContext(CanType type) const;
|
|
|
|
/// Map a type containing pack element type parameters to a contextual
|
|
/// type in the pack generic context.
|
|
Type mapElementTypeIntoPackContext(Type type) const;
|
|
|
|
/// Map the given SIL interface type to a contextual type.
|
|
///
|
|
/// This operation will also reabstract dependent types according to the
|
|
/// abstraction level of their associated type requirements.
|
|
SILType mapTypeIntoEnvironment(SILModule &M, SILType type) const;
|
|
|
|
/// Returns a substitution map that sends every generic parameter to its
|
|
/// corresponding archetype in this generic environment.
|
|
SubstitutionMap getForwardingSubstitutionMap() const;
|
|
|
|
void dump(raw_ostream &os) const;
|
|
|
|
SWIFT_DEBUG_DUMP;
|
|
};
|
|
|
|
/// A pair of an opened-element generic signature and an opened-element
|
|
/// generic environment.
|
|
struct OpenedElementContext {
|
|
/// The opened-element environment for this expansion.
|
|
GenericEnvironment *environment;
|
|
|
|
/// The opened-element signature for this expansion.
|
|
CanGenericSignature signature;
|
|
|
|
/// Create a fresh opened element context from a contextual pack
|
|
/// expansion type. This is useful when writing code that needs to
|
|
/// break down the components of a pack expansion.
|
|
static OpenedElementContext
|
|
createForContextualExpansion(ASTContext &ctx,
|
|
CanTypeWrapper<PackExpansionType> expansionType);
|
|
};
|
|
|
|
} // end namespace swift
|
|
|
|
#endif // SWIFT_AST_GENERIC_ENVIRONMENT_H
|
|
|