Skip to content

Commit 1e92156

Browse files
authored
Merge pull request #80905 from gottesmm/pr-f326796c380c34ae29d23b894814045aa06390d8
[sil-isolation-info] When determining isolation of a function arg, use its VarDecl.
2 parents 6c1f58b + 0ece31e commit 1e92156

File tree

7 files changed

+133
-9
lines changed

7 files changed

+133
-9
lines changed

include/swift/AST/ActorIsolation.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ class ActorIsolation {
217217
}
218218
}
219219

220+
/// In the debugger return the index for the stored actorInstance pointer
221+
/// union index. Asserts if not an actor instance.
222+
SWIFT_DEBUG_HELPER(unsigned getActorInstanceUnionIndex() const);
223+
220224
NominalTypeDecl *getActor() const;
221225

222226
VarDecl *getActorInstance() const;

include/swift/SILOptimizer/Utils/SILIsolationInfo.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,14 @@ class ActorInstance {
7171
ActorInstance() : ActorInstance(SILValue(), Kind::Value) {}
7272

7373
static ActorInstance getForValue(SILValue value) {
74+
if (!value)
75+
return ActorInstance();
7476
value = lookThroughInsts(value);
77+
if (!value->getType()
78+
.getASTType()
79+
->lookThroughAllOptionalTypes()
80+
->isAnyActorType())
81+
return ActorInstance();
7582
return ActorInstance(value, Kind::Value);
7683
}
7784

@@ -96,7 +103,7 @@ class ActorInstance {
96103
return value.getPointer();
97104
}
98105

99-
SILValue maybeGetValue() const {
106+
LLVM_ATTRIBUTE_USED SILValue maybeGetValue() const {
100107
if (getKind() != Kind::Value)
101108
return SILValue();
102109
return getValue();
@@ -132,6 +139,10 @@ class ActorInstance {
132139
bool operator!=(const ActorInstance &other) const {
133140
return !(*this == other);
134141
}
142+
143+
void print(llvm::raw_ostream &os) const;
144+
145+
SWIFT_DEBUG_DUMP { print(llvm::dbgs()); }
135146
};
136147

137148
/// The isolation info inferred for a specific SILValue. Use
@@ -372,6 +383,21 @@ class SILIsolationInfo {
372383
ActorIsolation::forActorInstanceSelf(typeDecl)};
373384
}
374385

386+
static SILIsolationInfo
387+
getActorInstanceIsolated(SILValue isolatedValue,
388+
const SILFunctionArgument *actorInstance) {
389+
assert(actorInstance);
390+
auto *varDecl =
391+
llvm::dyn_cast_if_present<VarDecl>(actorInstance->getDecl());
392+
if (!varDecl)
393+
return {};
394+
return {isolatedValue, actorInstance,
395+
actorInstance->isSelf()
396+
? ActorIsolation::forActorInstanceSelf(varDecl)
397+
: ActorIsolation::forActorInstanceParameter(
398+
varDecl, actorInstance->getIndex())};
399+
}
400+
375401
static SILIsolationInfo getActorInstanceIsolated(SILValue isolatedValue,
376402
ActorInstance actorInstance,
377403
NominalTypeDecl *typeDecl) {

lib/AST/TypeCheckRequests.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2022,6 +2022,17 @@ void ActorIsolation::dumpForDiagnostics() const {
20222022
llvm::dbgs() << '\n';
20232023
}
20242024

2025+
unsigned ActorIsolation::getActorInstanceUnionIndex() const {
2026+
assert(isActorInstanceIsolated());
2027+
if (actorInstance.is<NominalTypeDecl *>())
2028+
return 0;
2029+
if (actorInstance.is<VarDecl *>())
2030+
return 1;
2031+
if (actorInstance.is<Expr *>())
2032+
return 2;
2033+
llvm_unreachable("Unhandled");
2034+
}
2035+
20252036
void swift::simple_display(
20262037
llvm::raw_ostream &out, const ActorIsolation &state) {
20272038
if (state.preconcurrency())

lib/SILOptimizer/Utils/SILIsolationInfo.cpp

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,12 @@ SILIsolationInfo SILIsolationInfo::get(SILInstruction *inst) {
415415
return SILIsolationInfo::getGlobalActorIsolated(SILValue(), selfASTType);
416416
}
417417

418+
if (auto *fArg = dyn_cast<SILFunctionArgument>(actualIsolatedValue)) {
419+
if (auto info =
420+
SILIsolationInfo::getActorInstanceIsolated(fArg, fArg))
421+
return info;
422+
}
423+
418424
// TODO: We really should be doing this based off of an Operand. Then
419425
// we would get the SILValue() for the first element. Today this can
420426
// only mess up isolation history.
@@ -449,7 +455,21 @@ SILIsolationInfo SILIsolationInfo::get(SILInstruction *inst) {
449455
}
450456
}
451457

458+
// Ok, we found an actor instance. Look for our actual isolated value.
452459
if (actorInstance) {
460+
if (auto actualIsolatedValue =
461+
ActorInstance::getForValue(actorInstance)) {
462+
// See if we have a function parameter. In that case, we want to see
463+
// if we have a function argument. In such a case, we need to use
464+
// the right parameter and the var decl.
465+
if (auto *fArg = dyn_cast<SILFunctionArgument>(
466+
actualIsolatedValue.getValue())) {
467+
if (auto info =
468+
SILIsolationInfo::getActorInstanceIsolated(pai, fArg))
469+
return info;
470+
}
471+
}
472+
453473
return SILIsolationInfo::getActorInstanceIsolated(
454474
pai, actorInstance, actorIsolation.getActor());
455475
}
@@ -480,6 +500,14 @@ SILIsolationInfo SILIsolationInfo::get(SILInstruction *inst) {
480500
if (auto *rei = dyn_cast<RefElementAddrInst>(inst)) {
481501
auto varIsolation = swift::getActorIsolation(rei->getField());
482502

503+
if (auto instance = ActorInstance::getForValue(rei->getOperand())) {
504+
if (auto *fArg = llvm::dyn_cast_or_null<SILFunctionArgument>(
505+
instance.maybeGetValue())) {
506+
if (auto info = SILIsolationInfo::getActorInstanceIsolated(rei, fArg))
507+
return info.withUnsafeNonIsolated(varIsolation.isNonisolatedUnsafe());
508+
}
509+
}
510+
483511
auto *nomDecl =
484512
rei->getOperand()->getType().getNominalOrBoundGenericNominal();
485513

@@ -868,11 +896,11 @@ SILIsolationInfo SILIsolationInfo::get(SILArgument *arg) {
868896

869897
// Before we do anything further, see if we have an isolated parameter. This
870898
// handles isolated self and specifically marked isolated.
871-
if (auto *isolatedArg = fArg->getFunction()->maybeGetIsolatedArgument()) {
899+
if (auto *isolatedArg = llvm::cast_or_null<SILFunctionArgument>(
900+
fArg->getFunction()->maybeGetIsolatedArgument())) {
872901
auto astType = isolatedArg->getType().getASTType();
873902
if (auto *nomDecl = astType->lookThroughAllOptionalTypes()->getAnyActor()) {
874-
return SILIsolationInfo::getActorInstanceIsolated(fArg, isolatedArg,
875-
nomDecl);
903+
return SILIsolationInfo::getActorInstanceIsolated(fArg, isolatedArg);
876904
}
877905
}
878906

@@ -1017,10 +1045,10 @@ void SILIsolationInfo::print(llvm::raw_ostream &os) const {
10171045
}
10181046
}
10191047

1020-
bool SILIsolationInfo::hasSameIsolation(ActorIsolation actorIsolation) const {
1048+
bool SILIsolationInfo::hasSameIsolation(ActorIsolation other) const {
10211049
if (getKind() != Kind::Actor)
10221050
return false;
1023-
return getActorIsolation() == actorIsolation;
1051+
return getActorIsolation() == other;
10241052
}
10251053

10261054
bool SILIsolationInfo::hasSameIsolation(const SILIsolationInfo &other) const {
@@ -1362,6 +1390,25 @@ SILDynamicMergedIsolationInfo::merge(SILIsolationInfo other) const {
13621390
return {other};
13631391
}
13641392

1393+
void ActorInstance::print(llvm::raw_ostream &os) const {
1394+
os << "Actor Instance. Kind: ";
1395+
switch (getKind()) {
1396+
case Kind::Value:
1397+
os << "Value.";
1398+
break;
1399+
case Kind::ActorAccessorInit:
1400+
os << "ActorAccessorInit.";
1401+
break;
1402+
case Kind::CapturedActorSelf:
1403+
os << "CapturedActorSelf.";
1404+
break;
1405+
}
1406+
1407+
if (auto value = maybeGetValue()) {
1408+
os << " Value: " << value;
1409+
};
1410+
}
1411+
13651412
//===----------------------------------------------------------------------===//
13661413
// MARK: Tests
13671414
//===----------------------------------------------------------------------===//

test/Concurrency/async_task_locals_basic_warnings_bug_isolation.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ actor Test {
1313
func withTaskLocal(isolation: isolated (any Actor)? = #isolation,
1414
_ body: (consuming NonSendableValue, isolated (any Actor)?) -> Void) async {
1515
Self.$local.withValue(12) {
16-
// Unexpected errors here:
17-
// error: unexpected warning produced: sending 'body' risks causing data races; this is an error in the Swift 6 language mode
18-
// error: unexpected note produced: actor-isolated 'body' is captured by a actor-isolated closure. actor-isolated uses in closure may race against later nonisolated uses
1916
body(NonSendableValue(), isolation)
2017
}
2118
}

test/Concurrency/silisolationinfo_inference.sil

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,3 +876,22 @@ bb2(%10 : @owned $any Error):
876876
dealloc_stack %2 : $*T
877877
throw %10 : $any Error
878878
}
879+
880+
// CHECK-LABEL: begin running test 1 of 1 on optional_test: sil_isolation_info_inference with: @trace[0]
881+
// CHECK-NEXT: Input Value: %5 = ref_element_addr %4 : $MyActor, #MyActor.ns
882+
// CHECK-NEXT: Isolation: 'argument'-isolated
883+
// CHECK-NEXT: end running test 1 of 1 on optional_test: sil_isolation_info_inference with: @trace[0]
884+
sil [ossa] @optional_test : $@convention(thin) (@sil_isolated @guaranteed Optional<MyActor>) -> () {
885+
bb0(%0 : @guaranteed $Optional<MyActor>):
886+
specify_test "sil_isolation_info_inference @trace[0]"
887+
debug_value %0 : $Optional<MyActor>, let, name "argument"
888+
%1a = copy_value %0 : $Optional<MyActor>
889+
%1b = begin_borrow %1a
890+
%1c = unchecked_enum_data %1b : $Optional<MyActor>, #Optional.some!enumelt
891+
%1d = ref_element_addr %1c : $MyActor, #MyActor.ns
892+
debug_value [trace] %1d
893+
end_borrow %1b
894+
destroy_value %1a
895+
%9999 = tuple ()
896+
return %9999 : $()
897+
}

test/Concurrency/transfernonsendable.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2007,3 +2007,23 @@ nonisolated func localCaptureDataRace4() {
20072007

20082008
x = 2 // expected-tns-note {{access can happen concurrently}}
20092009
}
2010+
2011+
// We shouldn't error here since every time around, we are using the same
2012+
// isolation.
2013+
func testIsolatedParamInference() {
2014+
class S : @unchecked Sendable {}
2015+
2016+
final class B {
2017+
var s = S()
2018+
var b: Bool = false
2019+
2020+
func foo(isolation: isolated Actor = #isolation) async {
2021+
while !b {
2022+
await withTaskGroup(of: Int.self) { group in
2023+
_ = isolation
2024+
self.s = S()
2025+
}
2026+
}
2027+
}
2028+
}
2029+
}

0 commit comments

Comments
 (0)