Files
swift-mirror/include/swift/AST/GenericEnvironment.h

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