mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Diagnose captured of non-sendable metatypes crossing isolation boundaries
Keep track of all of the type parameters and archetypes that are captured by a local function or closure. Use that information to diagnose cases where a non-Sendable metatype crosses an isolation boundary.
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
#include "swift/Basic/LLVM.h"
|
||||
#include "swift/Basic/OptionSet.h"
|
||||
#include "swift/Basic/SourceLoc.h"
|
||||
#include "swift/AST/Type.h"
|
||||
#include "swift/AST/TypeAlignments.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
@@ -129,6 +130,18 @@ public:
|
||||
unsigned getFlags() const { return Value.getInt(); }
|
||||
};
|
||||
|
||||
/// Describes a type that has been captured by a closure or local function.
|
||||
class CapturedType {
|
||||
Type type;
|
||||
SourceLoc loc;
|
||||
|
||||
public:
|
||||
CapturedType(Type type, SourceLoc loc) : type(type), loc(loc) { }
|
||||
|
||||
Type getType() const { return type; }
|
||||
SourceLoc getLoc() const { return loc; }
|
||||
};
|
||||
|
||||
} // end swift namespace
|
||||
|
||||
namespace swift {
|
||||
@@ -140,26 +153,32 @@ class CaptureInfo {
|
||||
class CaptureInfoStorage final
|
||||
: public llvm::TrailingObjects<CaptureInfoStorage,
|
||||
CapturedValue,
|
||||
GenericEnvironment *> {
|
||||
GenericEnvironment *,
|
||||
CapturedType> {
|
||||
|
||||
DynamicSelfType *DynamicSelf;
|
||||
OpaqueValueExpr *OpaqueValue;
|
||||
unsigned NumCapturedValues;
|
||||
unsigned NumGenericEnvironments;
|
||||
unsigned NumCapturedTypes;
|
||||
|
||||
public:
|
||||
explicit CaptureInfoStorage(DynamicSelfType *dynamicSelf,
|
||||
OpaqueValueExpr *opaqueValue,
|
||||
unsigned numCapturedValues,
|
||||
unsigned numGenericEnvironments)
|
||||
unsigned numGenericEnvironments,
|
||||
unsigned numCapturedTypes)
|
||||
: DynamicSelf(dynamicSelf), OpaqueValue(opaqueValue),
|
||||
NumCapturedValues(numCapturedValues),
|
||||
NumGenericEnvironments(numGenericEnvironments) { }
|
||||
NumGenericEnvironments(numGenericEnvironments),
|
||||
NumCapturedTypes(numCapturedTypes) { }
|
||||
|
||||
ArrayRef<CapturedValue> getCaptures() const;
|
||||
|
||||
ArrayRef<GenericEnvironment *> getGenericEnvironments() const;
|
||||
|
||||
ArrayRef<CapturedType> getCapturedTypes() const;
|
||||
|
||||
DynamicSelfType *getDynamicSelfType() const {
|
||||
return DynamicSelf;
|
||||
}
|
||||
@@ -171,6 +190,14 @@ class CaptureInfo {
|
||||
unsigned numTrailingObjects(OverloadToken<CapturedValue>) const {
|
||||
return NumCapturedValues;
|
||||
}
|
||||
|
||||
unsigned numTrailingObjects(OverloadToken<GenericEnvironment *>) const {
|
||||
return NumGenericEnvironments;
|
||||
}
|
||||
|
||||
unsigned numTrailingObjects(OverloadToken<CapturedType>) const {
|
||||
return NumCapturedTypes;
|
||||
}
|
||||
};
|
||||
|
||||
enum class Flags : unsigned {
|
||||
@@ -187,7 +214,8 @@ public:
|
||||
ArrayRef<CapturedValue> captures,
|
||||
DynamicSelfType *dynamicSelf, OpaqueValueExpr *opaqueValue,
|
||||
bool genericParamCaptures,
|
||||
ArrayRef<GenericEnvironment *> genericEnv=ArrayRef<GenericEnvironment*>());
|
||||
ArrayRef<GenericEnvironment *> genericEnv=ArrayRef<GenericEnvironment*>(),
|
||||
ArrayRef<CapturedType> capturedTypes = ArrayRef<CapturedType>());
|
||||
|
||||
/// A CaptureInfo representing no captures at all.
|
||||
static CaptureInfo empty();
|
||||
@@ -196,11 +224,7 @@ public:
|
||||
return StorageAndFlags.getPointer();
|
||||
}
|
||||
|
||||
bool isTrivial() const {
|
||||
assert(hasBeenComputed());
|
||||
return getCaptures().empty() && !hasGenericParamCaptures() &&
|
||||
!hasDynamicSelfCapture() && !hasOpaqueValueCapture();
|
||||
}
|
||||
bool isTrivial() const;
|
||||
|
||||
/// Returns all captured values and opaque expressions.
|
||||
ArrayRef<CapturedValue> getCaptures() const {
|
||||
@@ -214,6 +238,12 @@ public:
|
||||
return StorageAndFlags.getPointer()->getGenericEnvironments();
|
||||
}
|
||||
|
||||
/// Returns all captured values and opaque expressions.
|
||||
ArrayRef<CapturedType> getCapturedTypes() const {
|
||||
assert(hasBeenComputed());
|
||||
return StorageAndFlags.getPointer()->getCapturedTypes();
|
||||
}
|
||||
|
||||
/// \returns true if the function captures the primary generic environment
|
||||
/// from its innermost declaration context.
|
||||
bool hasGenericParamCaptures() const {
|
||||
|
||||
@@ -5607,6 +5607,10 @@ ERROR(non_sendable_isolated_capture,none,
|
||||
"capture of %1 with non-sendable type %0 in an isolated "
|
||||
"%select{local function|closure}2",
|
||||
(Type, DeclName, bool))
|
||||
ERROR(non_sendable_metatype_capture,none,
|
||||
"capture of non-sendable type %0 in an isolated "
|
||||
"%select{local function|closure}1",
|
||||
(Type, bool))
|
||||
ERROR(self_capture_deinit_task,none,
|
||||
"capture of 'self' in a closure that outlives deinit",
|
||||
())
|
||||
|
||||
Reference in New Issue
Block a user