| //===--- SubstitutionMap.h - Swift Substitution Map ASTs --------*- 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 SubstitutionMap class. |
| // |
| // This is a data structure type describing the mapping of abstract types to |
| // replacement types, together with associated conformances to use for deriving |
| // nested types. |
| // |
| // Depending on how the SubstitutionMap is constructed, the abstract types are |
| // either archetypes or interface types. Care must be exercised to only look up |
| // one or the other. |
| // |
| // SubstitutionMaps are constructed by calling the getSubstitutionMap() method |
| // on a GenericSignature or GenericEnvironment. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_AST_SUBSTITUTION_MAP_H |
| #define SWIFT_AST_SUBSTITUTION_MAP_H |
| |
| #include "swift/AST/ProtocolConformanceRef.h" |
| #include "swift/AST/Type.h" |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/ADT/DenseMap.h" |
| #include "llvm/ADT/Optional.h" |
| #include "llvm/ADT/SmallPtrSet.h" |
| #include "llvm/ADT/SmallVector.h" |
| |
| namespace swift { |
| |
| class GenericSignature; |
| class GenericEnvironment; |
| class SubstitutableType; |
| |
| template<class Type> class CanTypeWrapper; |
| typedef CanTypeWrapper<SubstitutableType> CanSubstitutableType; |
| |
| class SubstitutionMap { |
| using ParentType = std::pair<CanType, AssociatedTypeDecl *>; |
| |
| // FIXME: Switch to a more efficient representation. |
| llvm::DenseMap<SubstitutableType *, Type> subMap; |
| llvm::DenseMap<TypeBase *, SmallVector<ProtocolConformanceRef, 1>> |
| conformanceMap; |
| llvm::DenseMap<TypeBase *, SmallVector<ParentType, 1>> parentMap; |
| |
| // Call the given function for each parent of the given type. The |
| // function \c fn should return an \c Optional<T>. \c forEachParent() will |
| // return the first non-empty \C Optional<T> returned by \c fn. |
| template<typename T> |
| Optional<T> forEachParent( |
| CanType type, |
| llvm::SmallPtrSetImpl<CanType> &visitedParents, |
| llvm::function_ref<Optional<T>(CanType, |
| AssociatedTypeDecl *)> fn) const; |
| |
| // Call the given function for each conformance of the given type. The |
| // function \c fn should return an \c Optional<T>. \c forEachConformance() |
| // will return the first non-empty \C Optional<T> returned by \c fn. |
| template<typename T> |
| Optional<T> forEachConformance( |
| CanType type, |
| llvm::SmallPtrSetImpl<CanType> &visitedParents, |
| llvm::function_ref<Optional<T>(ProtocolConformanceRef)> fn) |
| const; |
| |
| public: |
| Optional<ProtocolConformanceRef> |
| lookupConformance( |
| CanType type, ProtocolDecl *proto, |
| llvm::SmallPtrSetImpl<CanType> *visitedParents = nullptr) const; |
| |
| /// Retrieve the conformances for the given type. |
| ArrayRef<ProtocolConformanceRef> getConformances(CanType type) const; |
| |
| bool empty() const { |
| return subMap.empty(); |
| } |
| |
| /// Query whether any replacement types in the map contain archetypes. |
| bool hasArchetypes() const; |
| |
| /// Query whether any replacement type sin the map contain dynamic Self. |
| bool hasDynamicSelf() const; |
| |
| /// Create a substitution map for a protocol conformance. |
| static SubstitutionMap |
| getProtocolSubstitutions(ProtocolDecl *protocol, |
| Type selfType, |
| ProtocolConformanceRef conformance); |
| |
| /// Given that 'derivedDecl' is an override of 'baseDecl' in a subclass, |
| /// and 'derivedSubs' is a set of substitutions written in terms of the |
| /// generic signature of 'derivedDecl', produce a set of substitutions |
| /// written in terms of the generic signature of 'baseDecl'. |
| static SubstitutionMap |
| getOverrideSubstitutions(const ValueDecl *baseDecl, |
| const ValueDecl *derivedDecl, |
| Optional<SubstitutionMap> derivedSubs, |
| LazyResolver *resolver); |
| |
| /// Variant of the above for when we have the generic signatures but not |
| /// the decls for 'derived' and 'base'. |
| static SubstitutionMap |
| getOverrideSubstitutions(const ClassDecl *baseClass, |
| const ClassDecl *derivedClass, |
| GenericSignature *baseSig, |
| GenericSignature *derivedSig, |
| Optional<SubstitutionMap> derivedSubs, |
| LazyResolver *resolver); |
| |
| /// Combine two substitution maps as follows. |
| /// |
| /// The result is written in terms of the generic parameters of 'baseSig'. |
| /// |
| /// Generic parameters with a depth less than 'baseDepth' come from |
| /// 'baseSubs'. |
| /// |
| /// Generic parameters with a depth greater than 'baseDepth' come from |
| /// 'origSubs', but are looked up starting with a depth of 'origDepth'. |
| static SubstitutionMap |
| combineSubstitutionMaps(const SubstitutionMap &baseSubMap, |
| const SubstitutionMap &origSubMap, |
| unsigned baseDepth, |
| unsigned origDepth, |
| GenericSignature *baseSig); |
| |
| /// Dump the contents of this substitution map for debugging purposes. |
| void dump(llvm::raw_ostream &out) const; |
| |
| LLVM_ATTRIBUTE_DEPRECATED(void dump() const, "only for use in the debugger"); |
| |
| private: |
| friend class GenericSignature; |
| friend class GenericEnvironment; |
| friend struct QuerySubstitutionMap; |
| |
| /// Look up the replacement for the given type parameter or interface type. |
| /// Note that this only finds replacements for maps that are directly |
| /// stored inside the map. In most cases, you should call Type::subst() |
| /// instead, since that will resolve member types also. |
| Type lookupSubstitution(CanSubstitutableType type) const; |
| |
| // You should not need to call these directly to build SubstitutionMaps; |
| // instead, use GenericSignature::getSubstitutionMap() or |
| // GenericEnvironment::getSubstitutionMap(). |
| |
| void addSubstitution(CanSubstitutableType type, Type replacement); |
| void addConformance(CanType type, ProtocolConformanceRef conformance); |
| void addParent(CanType type, CanType parent, |
| AssociatedTypeDecl *assocType); |
| }; |
| |
| } // end namespace swift |
| |
| #endif |