Skip to content

[region-isolation] Make fields of global actor guarded types that are non-Sendable be considered as actor isolated. #72196

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 12 additions & 37 deletions include/swift/AST/ExtInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -935,8 +935,7 @@ class SILExtInfoBuilder {
DifferentiabilityMask = 0x7 << DifferentiabilityMaskOffset,
UnimplementableMask = 1 << 12,
ErasedIsolationMask = 1 << 13,
TransferringResultMask = 1 << 14,
NumMaskBits = 15
NumMaskBits = 14
};

unsigned bits; // Naturally sized for speed.
Expand All @@ -957,17 +956,15 @@ class SILExtInfoBuilder {
bool isNoEscape, bool isSendable,
bool isAsync, bool isUnimplementable,
SILFunctionTypeIsolation isolation,
bool hasTransferringResult,
DifferentiabilityKind diffKind) {
return ((unsigned)rep) | (isPseudogeneric ? PseudogenericMask : 0) |
(isNoEscape ? NoEscapeMask : 0) | (isSendable ? SendableMask : 0) |
(isAsync ? AsyncMask : 0) |
(isUnimplementable ? UnimplementableMask : 0) |
(isolation == SILFunctionTypeIsolation::Erased
? ErasedIsolationMask : 0) |
(isolation == SILFunctionTypeIsolation::Erased ? ErasedIsolationMask
: 0) |
(((unsigned)diffKind << DifferentiabilityMaskOffset) &
DifferentiabilityMask) |
(hasTransferringResult ? TransferringResultMask : 0);
DifferentiabilityMask);
}

public:
Expand All @@ -976,19 +973,18 @@ class SILExtInfoBuilder {
SILExtInfoBuilder()
: SILExtInfoBuilder(makeBits(SILFunctionTypeRepresentation::Thick, false,
false, false, false, false,
SILFunctionTypeIsolation::Unknown, false,
SILFunctionTypeIsolation::Unknown,
DifferentiabilityKind::NonDifferentiable),
ClangTypeInfo(nullptr), LifetimeDependenceInfo()) {}

SILExtInfoBuilder(Representation rep, bool isPseudogeneric, bool isNoEscape,
bool isSendable, bool isAsync, bool isUnimplementable,
SILFunctionTypeIsolation isolation,
DifferentiabilityKind diffKind, const clang::Type *type,
LifetimeDependenceInfo lifetimeDependenceInfo,
bool hasTransferringResult)
LifetimeDependenceInfo lifetimeDependenceInfo)
: SILExtInfoBuilder(makeBits(rep, isPseudogeneric, isNoEscape, isSendable,
isAsync, isUnimplementable, isolation,
hasTransferringResult, diffKind),
diffKind),
ClangTypeInfo(type), lifetimeDependenceInfo) {}

// Constructor for polymorphic type.
Expand All @@ -999,7 +995,6 @@ class SILExtInfoBuilder {
info.getIsolation().isErased()
? SILFunctionTypeIsolation::Erased
: SILFunctionTypeIsolation::Unknown,
/*has transferring result*/ false,
info.getDifferentiabilityKind()),
info.getClangTypeInfo(),
info.getLifetimeDependenceInfo()) {}
Expand Down Expand Up @@ -1029,10 +1024,6 @@ class SILExtInfoBuilder {

constexpr bool isAsync() const { return bits & AsyncMask; }

constexpr bool hasTransferringResult() const {
return bits & TransferringResultMask;
}

constexpr DifferentiabilityKind getDifferentiabilityKind() const {
return DifferentiabilityKind((bits & DifferentiabilityMask) >>
DifferentiabilityMaskOffset);
Expand Down Expand Up @@ -1166,14 +1157,6 @@ class SILExtInfoBuilder {
clangTypeInfo, lifetimeDependenceInfo);
}

[[nodiscard]] SILExtInfoBuilder
withTransferringResult(bool hasTransferringResult = true) const {
return SILExtInfoBuilder(hasTransferringResult
? (bits | TransferringResultMask)
: (bits & ~TransferringResultMask),
clangTypeInfo, lifetimeDependenceInfo);
}

[[nodiscard]]
SILExtInfoBuilder
withDifferentiabilityKind(DifferentiabilityKind differentiability) const {
Expand Down Expand Up @@ -1239,11 +1222,11 @@ class SILExtInfo {

/// A default ExtInfo but with a Thin convention.
static SILExtInfo getThin() {
return SILExtInfoBuilder(
SILExtInfoBuilder::Representation::Thin, false, false, false,
false, false, SILFunctionTypeIsolation::Unknown,
DifferentiabilityKind::NonDifferentiable, nullptr,
LifetimeDependenceInfo(), false /*transferring result*/)
return SILExtInfoBuilder(SILExtInfoBuilder::Representation::Thin, false,
false, false, false, false,
SILFunctionTypeIsolation::Unknown,
DifferentiabilityKind::NonDifferentiable, nullptr,
LifetimeDependenceInfo())
.build();
}

Expand Down Expand Up @@ -1281,10 +1264,6 @@ class SILExtInfo {
return builder.getIsolation();
}

constexpr bool hasTransferringResult() const {
return builder.hasTransferringResult();
}

constexpr DifferentiabilityKind getDifferentiabilityKind() const {
return builder.getDifferentiabilityKind();
}
Expand Down Expand Up @@ -1331,10 +1310,6 @@ class SILExtInfo {
return builder.withUnimplementable(isUnimplementable).build();
}

SILExtInfo withTransferringResult(bool hasTransferringResult = true) const {
return builder.withTransferringResult(hasTransferringResult).build();
}

SILExtInfo withLifetimeDependenceInfo(LifetimeDependenceInfo info) const {
return builder.withLifetimeDependenceInfo(info);
}
Expand Down
14 changes: 12 additions & 2 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ class alignas(1 << TypeAlignInBits) TypeBase

protected:
enum { NumAFTExtInfoBits = 15 };
enum { NumSILExtInfoBits = 15 };
enum { NumSILExtInfoBits = 14 };

// clang-format off
union { uint64_t OpaqueBits;
Expand Down Expand Up @@ -4462,6 +4462,11 @@ class SILResultInfo {
/// - The function type is `@differentiable`, the function is
/// differentiable with respect to this result.
NotDifferentiable = 0x1,

/// Set if a return type is transferring. This means that the returned value
/// must be disconnected and not in any strongly structured regions like an
/// actor or a task isolated variable.
IsTransferring = 0x2,
};

using Options = OptionSet<Flag>;
Expand Down Expand Up @@ -4906,8 +4911,13 @@ class SILFunctionType final
SILFunctionTypeIsolation getIsolation() const {
return getExtInfo().getIsolation();
}

/// Return true if all
bool hasTransferringResult() const {
return getExtInfo().hasTransferringResult();
// For now all functions either have all transferring results or no
// transferring results. This is validated with a SILVerifier check.
return getNumResults() &&
getResults().front().hasOption(SILResultInfo::IsTransferring);
}

/// Return the array of all the yields.
Expand Down
1 change: 1 addition & 0 deletions include/swift/Demangling/TypeDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ using ImplParameterInfoOptions = OptionSet<ImplParameterInfoFlags>;

enum class ImplResultInfoFlags : uint8_t {
NotDifferentiable = 0x1,
IsTransferring = 0x2,
};

using ImplResultInfoOptions = OptionSet<ImplResultInfoFlags>;
Expand Down
8 changes: 6 additions & 2 deletions lib/AST/ASTDemangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,11 @@ getResultOptions(ImplResultInfoOptions implOptions) {
result |= SILResultInfo::NotDifferentiable;
}

if (implOptions.contains(ImplResultInfoFlags::IsTransferring)) {
implOptions -= ImplResultInfoFlags::IsTransferring;
result |= SILResultInfo::IsTransferring;
}

// If we did not remove all of the options from implOptions, someone forgot to
// update this code for a new type of flag. Return none to signal error!
if (bool(implOptions))
Expand Down Expand Up @@ -664,8 +669,7 @@ Type ASTBuilder::createImplFunctionType(
auto einfo = SILFunctionType::ExtInfoBuilder(
representation, flags.isPseudogeneric(), !flags.isEscaping(),
flags.isSendable(), flags.isAsync(), unimplementable,
isolation, diffKind, clangFnType, LifetimeDependenceInfo(),
flags.hasTransferringResult())
isolation, diffKind, clangFnType, LifetimeDependenceInfo())
.build();

return SILFunctionType::get(genericSig, einfo, funcCoroutineKind,
Expand Down
9 changes: 5 additions & 4 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6740,10 +6740,6 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
}
sub->Printer << ") -> ";

if (T->hasTransferringResult()) {
sub->Printer << "transferring ";
}

auto lifetimeDependenceInfo = T->getLifetimeDependenceInfo();
if (!lifetimeDependenceInfo.empty()) {
sub->Printer << lifetimeDependenceInfo.getString() << " ";
Expand Down Expand Up @@ -7532,6 +7528,11 @@ void SILResultInfo::print(ASTPrinter &Printer, const PrintOptions &Opts) const {
Printer << "@noDerivative ";
}

if (options.contains(SILResultInfo::IsTransferring)) {
options -= SILResultInfo::IsTransferring;
Printer << "@sil_transferring ";
}

assert(!bool(options) && "ResultInfo has option that was not handled?!");

Printer << getStringForResultConvention(getConvention());
Expand Down
16 changes: 11 additions & 5 deletions lib/SIL/IR/SILFunctionType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1254,12 +1254,15 @@ class DestructureResults {
const Conventions &Convs;
SmallVectorImpl<SILResultInfo> &Results;
TypeExpansionContext context;
bool hasTransferringResult;

public:
DestructureResults(TypeExpansionContext context, TypeConverter &TC,
const Conventions &conventions,
SmallVectorImpl<SILResultInfo> &results)
: TC(TC), Convs(conventions), Results(results), context(context) {}
SmallVectorImpl<SILResultInfo> &results,
bool hasTransferringResult)
: TC(TC), Convs(conventions), Results(results), context(context),
hasTransferringResult(hasTransferringResult) {}

void destructure(AbstractionPattern origType, CanType substType) {
// Recur into tuples.
Expand Down Expand Up @@ -1290,6 +1293,8 @@ class DestructureResults {
SILPackType::ExtInfo extInfo(indirect);
auto packType = SILPackType::get(TC.Context, extInfo, packElts);
SILResultInfo result(packType, ResultConvention::Pack);
if (hasTransferringResult)
result = result.addingOption(SILResultInfo::IsTransferring);
Results.push_back(result);
});
return;
Expand Down Expand Up @@ -1331,6 +1336,8 @@ class DestructureResults {

SILResultInfo result(substResultTL.getLoweredType().getASTType(),
convention);
if (hasTransferringResult)
result = result.addingOption(SILResultInfo::IsTransferring);
Results.push_back(result);
}

Expand Down Expand Up @@ -2359,8 +2366,8 @@ static CanSILFunctionType getSILFunctionType(
// Destructure the result tuple type.
SmallVector<SILResultInfo, 8> results;
{
DestructureResults destructurer(expansionContext, TC, conventions,
results);
DestructureResults destructurer(expansionContext, TC, conventions, results,
hasTransferringResult);
destructurer.destructure(origResultType, substFormalResultType);
}

Expand Down Expand Up @@ -2405,7 +2412,6 @@ static CanSILFunctionType getSILFunctionType(
.withUnimplementable(unimplementable)
.withLifetimeDependenceInfo(
extInfoBuilder.getLifetimeDependenceInfo())
.withTransferringResult(hasTransferringResult)
.build();

return SILFunctionType::get(genericSig, silExtInfo, coroutineKind,
Expand Down
11 changes: 11 additions & 0 deletions lib/SIL/Verifier/SILVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6518,6 +6518,17 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
require(!FTy->hasErasedIsolation() ||
FTy->getRepresentation() == SILFunctionType::Representation::Thick,
"only thick function types can have erased isolation");

// If our function hasTransferringResult, then /all/ results must be
// transferring.
require(FTy->hasTransferringResult() ==
(FTy->getResults().size() &&
llvm::all_of(FTy->getResults(),
[](SILResultInfo result) {
return result.hasOption(
SILResultInfo::IsTransferring);
})),
"transferring result means all results are transferring");
}

struct VerifyFlowSensitiveRulesDetails {
Expand Down
Loading