Merge pull request #73348 from slavapestov/pack-expansion-closures-part-1

Preliminary steps towards support for closures that capture pack element environments
This commit is contained in:
Slava Pestov
2024-05-01 08:35:31 -04:00
committed by GitHub
17 changed files with 271 additions and 151 deletions

View File

@@ -75,13 +75,6 @@ public:
return TheFunction.get<AbstractClosureExpr *>()->getCaptureInfo();
}
bool hasType() const {
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>())
return AFD->hasInterfaceType();
return !TheFunction.get<AbstractClosureExpr *>()->getType().isNull();
}
ParameterList *getParameters() const {
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>())
return AFD->getParameters();
@@ -174,20 +167,8 @@ public:
return TheFunction.dyn_cast<AbstractClosureExpr*>();
}
/// Return true if this closure is passed as an argument to a function and is
/// known not to escape from that function. In this case, captures can be
/// more efficient.
bool isKnownNoEscape() const {
if (hasType() && !getType()->hasError())
return getType()->castTo<AnyFunctionType>()->isNoEscape();
return false;
}
/// Whether this function is @Sendable.
bool isSendable() const {
if (!hasType())
return false;
if (auto *fnType = getType()->getAs<AnyFunctionType>())
return fnType->isSendable();

View File

@@ -43,6 +43,7 @@ class ValueDecl;
class FuncDecl;
class OpaqueValueExpr;
class VarDecl;
class GenericEnvironment;
/// CapturedValue includes both the declaration being captured, along with flags
/// that indicate how it is captured.
@@ -140,19 +141,27 @@ class DynamicSelfType;
/// Stores information about captured variables.
class CaptureInfo {
class CaptureInfoStorage final
: public llvm::TrailingObjects<CaptureInfoStorage, CapturedValue> {
: public llvm::TrailingObjects<CaptureInfoStorage,
CapturedValue,
GenericEnvironment *> {
DynamicSelfType *DynamicSelf;
OpaqueValueExpr *OpaqueValue;
unsigned Count;
public:
explicit CaptureInfoStorage(unsigned count, DynamicSelfType *dynamicSelf,
OpaqueValueExpr *opaqueValue)
: DynamicSelf(dynamicSelf), OpaqueValue(opaqueValue), Count(count) { }
unsigned NumCapturedValues;
unsigned NumGenericEnvironments;
ArrayRef<CapturedValue> getCaptures() const {
return llvm::ArrayRef(this->getTrailingObjects<CapturedValue>(), Count);
}
public:
explicit CaptureInfoStorage(DynamicSelfType *dynamicSelf,
OpaqueValueExpr *opaqueValue,
unsigned numCapturedValues,
unsigned numGenericEnvironments)
: DynamicSelf(dynamicSelf), OpaqueValue(opaqueValue),
NumCapturedValues(numCapturedValues),
NumGenericEnvironments(numGenericEnvironments) { }
ArrayRef<CapturedValue> getCaptures() const;
ArrayRef<GenericEnvironment *> getGenericEnvironments() const;
DynamicSelfType *getDynamicSelfType() const {
return DynamicSelf;
@@ -161,6 +170,10 @@ class CaptureInfo {
OpaqueValueExpr *getOpaqueValue() const {
return OpaqueValue;
}
unsigned numTrailingObjects(OverloadToken<CapturedValue>) const {
return NumCapturedValues;
}
};
enum class Flags : unsigned {
@@ -173,9 +186,11 @@ class CaptureInfo {
public:
/// The default-constructed CaptureInfo is "not yet computed".
CaptureInfo() = default;
CaptureInfo(ASTContext &ctx, ArrayRef<CapturedValue> captures,
CaptureInfo(ASTContext &ctx,
ArrayRef<CapturedValue> captures,
DynamicSelfType *dynamicSelf, OpaqueValueExpr *opaqueValue,
bool genericParamCaptures);
bool genericParamCaptures,
ArrayRef<GenericEnvironment *> genericEnv=ArrayRef<GenericEnvironment*>());
/// A CaptureInfo representing no captures at all.
static CaptureInfo empty();
@@ -190,12 +205,20 @@ public:
!hasDynamicSelfCapture() && !hasOpaqueValueCapture();
}
/// Returns all captured values and opaque expressions.
ArrayRef<CapturedValue> getCaptures() const {
assert(hasBeenComputed());
return StorageAndFlags.getPointer()->getCaptures();
}
/// \returns true if the function captures any generic type parameters.
/// Returns all captured pack element environments.
ArrayRef<GenericEnvironment *> getGenericEnvironments() const {
assert(hasBeenComputed());
return StorageAndFlags.getPointer()->getGenericEnvironments();
}
/// \returns true if the function captures the primary generic environment
/// from its innermost declaration context.
bool hasGenericParamCaptures() const {
assert(hasBeenComputed());
return StorageAndFlags.getInt().contains(Flags::HasGenericParamCaptures);