Files
swift-mirror/include/swift/AST/InFlightSubstitution.h
2025-08-20 12:26:38 -04:00

192 lines
6.8 KiB
C++

//===--- InFlightSubstitution.h - In-flight substitution data ---*- 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 InFlightSubstitution structure, which captures
// all the information about a type substitution that's currently in
// progress. For now, this is meant to be an internal implementation
// detail of the substitution system, and other systems should not use
// it (unless they are part of the extended substitution system, such as
// the SIL type substituter)
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_AST_INFLIGHTSUBSTITUTION_H
#define SWIFT_AST_INFLIGHTSUBSTITUTION_H
#include "swift/AST/SubstitutionMap.h"
#include "llvm/ADT/DenseMap.h"
namespace swift {
class SubstitutionMap;
class InFlightSubstitution {
friend class SubstitutionMap;
TypeSubstitutionFn BaselineSubstType;
LookupConformanceFn BaselineLookupConformance;
SubstOptions Options;
RecursiveTypeProperties Props;
unsigned RemainingCount : 31;
unsigned InitLimit : 1;
unsigned RemainingDepth : 31;
unsigned LimitReached : 1;
struct ActivePackExpansion {
bool isSubstExpansion = false;
unsigned expansionIndex = 0;
};
llvm::SmallVector<ActivePackExpansion, 4> ActivePackExpansions;
llvm::SmallDenseMap<SubstitutionMap, SubstitutionMap, 2> SubMaps;
Type projectLaneFromPackType(
Type substType, unsigned level);
ProtocolConformanceRef projectLaneFromPackConformance(
PackConformance *substPackConf, unsigned level);
bool checkLimits(Type ty);
public:
InFlightSubstitution(TypeSubstitutionFn substType,
LookupConformanceFn lookupConformance,
SubstOptions options);
InFlightSubstitution(const InFlightSubstitution &) = delete;
InFlightSubstitution &operator=(const InFlightSubstitution &) = delete;
/// Perform primitive substitution on the given type. Returns Type()
/// if the type should not be substituted as a whole.
Type substType(SubstitutableType *origType, unsigned level);
/// Perform primitive conformance lookup on the given type.
ProtocolConformanceRef lookupConformance(Type dependentType,
ProtocolDecl *conformedProtocol,
unsigned level);
/// Given the shape type of a pack expansion, invoke the given callback
/// for each expanded component of it. If the substituted component
/// is an expansion component, the desired shape of that expansion
/// is passed as the argument; otherwise, the argument is Type().
/// In either case, an active expansion is entered on this IFS for
/// the duration of the call to handleComponent, and subsequent
/// pack-element type references will substitute to the corresponding
/// element of the substitution of the pack.
void expandPackExpansionShape(Type origShape,
llvm::function_ref<void(Type substComponentShape)> handleComponent);
/// Call the given function for each expanded component type of the
/// given pack expansion type. The function will be invoked with the
/// active expansion still active.
void expandPackExpansionType(PackExpansionType *origExpansionType,
llvm::function_ref<void(Type substType)> handleComponentType) {
expandPackExpansionShape(origExpansionType->getCountType(),
[&](Type substComponentShape) {
auto origPatternType = origExpansionType->getPatternType();
auto substEltType = origPatternType.subst(*this);
auto substComponentType =
(substComponentShape
? PackExpansionType::get(substEltType, substComponentShape)
: substEltType);
handleComponentType(substComponentType);
});
}
/// Return a list of component types that the pack expansion expands to.
SmallVector<Type, 8>
expandPackExpansionType(PackExpansionType *origExpansionType) {
SmallVector<Type, 8> substComponentTypes;
expandPackExpansionType(origExpansionType, substComponentTypes);
return substComponentTypes;
}
/// Expand the list of component types that the pack expansion expands
/// to into the given array.
void expandPackExpansionType(PackExpansionType *origExpansionType,
SmallVectorImpl<Type> &substComponentTypes) {
expandPackExpansionType(origExpansionType, [&](Type substComponentType) {
substComponentTypes.push_back(substComponentType);
});
}
class OptionsAdjustmentScope {
InFlightSubstitution &IFS;
SubstOptions SavedOptions;
public:
OptionsAdjustmentScope(InFlightSubstitution &IFS, SubstOptions newOptions)
: IFS(IFS), SavedOptions(IFS.Options) {
IFS.Options = newOptions;
}
OptionsAdjustmentScope(const OptionsAdjustmentScope &) = delete;
OptionsAdjustmentScope &operator=(const OptionsAdjustmentScope &) = delete;
~OptionsAdjustmentScope() {
IFS.Options = SavedOptions;
}
};
template <class Fn>
auto withNewOptions(SubstOptions options, Fn &&fn)
-> decltype(std::forward<Fn>(fn)()) {
OptionsAdjustmentScope scope(*this, options);
return std::forward<Fn>(fn)();
}
SubstOptions getOptions() const {
return Options;
}
bool shouldSubstitutePrimaryArchetypes() const {
return Options.contains(SubstFlags::SubstitutePrimaryArchetypes);
}
bool shouldSubstituteOpaqueArchetypes() const {
return Options.contains(SubstFlags::SubstituteOpaqueArchetypes);
}
bool shouldSubstituteLocalArchetypes() const {
return Options.contains(SubstFlags::SubstituteLocalArchetypes);
}
/// Is the given type invariant to substitution?
bool isInvariant(Type type) const;
bool wasLimitReached() const {
return LimitReached;
}
};
/// A helper classes that provides stable storage for the query
/// functions against a SubstitutionMap.
struct InFlightSubstitutionViaSubMapHelper {
QuerySubstitutionMap QueryType;
LookUpConformanceInSubstitutionMap QueryConformance;
InFlightSubstitutionViaSubMapHelper(SubstitutionMap subMap)
: QueryType{subMap}, QueryConformance(subMap) {}
};
class InFlightSubstitutionViaSubMap :
private InFlightSubstitutionViaSubMapHelper,
public InFlightSubstitution {
public:
InFlightSubstitutionViaSubMap(SubstitutionMap subMap,
SubstOptions options)
: InFlightSubstitutionViaSubMapHelper(subMap),
InFlightSubstitution(QueryType, QueryConformance, options) {}
};
} // end namespace swift
#endif