Skip to content

Commit 0205969

Browse files
authored
Merge pull request #82961 from gottesmm/pr-b3685ba26b885701787f7b6087dc7d9d873aa500
[rbi] Teach SendNonSendable how to more aggressively suppress sending errors around obfuscated Sendable functions
2 parents bfaafee + 73e34f0 commit 0205969

11 files changed

+43
-79
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8701,14 +8701,6 @@ ERROR(inherit_actor_context_only_on_async_or_isolation_erased_params,none,
87018701
"asynchronous function types",
87028702
(DeclAttribute))
87038703

8704-
ERROR(inherit_actor_context_with_concurrent,none,
8705-
"'@_inheritActorContext' attribute cannot be used together with %0",
8706-
(const TypeAttribute *))
8707-
8708-
ERROR(inherit_actor_context_with_nonisolated_nonsending,none,
8709-
"'@_inheritActorContext' attribute cannot be used together with %0",
8710-
(TypeRepr *))
8711-
87128704
//===----------------------------------------------------------------------===//
87138705
// MARK: @concurrent and nonisolated(nonsending) attributes
87148706
//===----------------------------------------------------------------------===//

include/swift/SILOptimizer/Utils/PartitionUtils.h

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,9 +1601,32 @@ struct PartitionOpEvaluator {
16011601
}
16021602

16031603
private:
1604-
bool isConvertFunctionFromSendableType(SILValue equivalenceClassRep) const {
1604+
/// To work around not having isolation in interface types, the type checker
1605+
/// inserts casts and other AST nodes that are used to enrich the AST with
1606+
/// isolation information. This results in Sendable functions being
1607+
/// wrapped/converted/etc in ways that hide the Sendability. This helper looks
1608+
/// through these conversions/wrappers/thunks to see if the original
1609+
/// underlying function is Sendable.
1610+
///
1611+
/// The two ways this can happen is that we either get an actual function_ref
1612+
/// that is Sendable or we get a convert function with a Sendable operand.
1613+
bool isHiddenSendableFunctionType(SILValue equivalenceClassRep) const {
16051614
SILValue valueToTest = equivalenceClassRep;
16061615
while (true) {
1616+
if (auto *pai = dyn_cast<PartialApplyInst>(valueToTest)) {
1617+
if (auto *calleeFunction = pai->getCalleeFunction()) {
1618+
if (pai->getNumArguments() >= 1 &&
1619+
pai->getArgument(0)->getType().isFunction() &&
1620+
calleeFunction->isThunk()) {
1621+
valueToTest = pai->getArgument(0);
1622+
continue;
1623+
}
1624+
1625+
if (calleeFunction->getLoweredFunctionType()->isSendable())
1626+
return true;
1627+
}
1628+
}
1629+
16071630
if (auto *i = dyn_cast<ThinToThickFunctionInst>(valueToTest)) {
16081631
valueToTest = i->getOperand();
16091632
continue;
@@ -1615,6 +1638,9 @@ struct PartitionOpEvaluator {
16151638
break;
16161639
}
16171640

1641+
if (auto *fn = dyn_cast<FunctionRefInst>(valueToTest))
1642+
return fn->getReferencedFunction()->getLoweredFunctionType()->isSendable();
1643+
16181644
auto *cvi = dyn_cast<ConvertFunctionInst>(valueToTest);
16191645
if (!cvi)
16201646
return false;
@@ -1647,7 +1673,7 @@ struct PartitionOpEvaluator {
16471673

16481674
// See if we have a convert function from a `@Sendable` type. In this
16491675
// case, we want to squelch the error.
1650-
if (isConvertFunctionFromSendableType(equivalenceClassRep))
1676+
if (isHiddenSendableFunctionType(equivalenceClassRep))
16511677
return;
16521678
}
16531679

@@ -1692,7 +1718,7 @@ struct PartitionOpEvaluator {
16921718

16931719
// See if we have a convert function from a `@Sendable` type. In this
16941720
// case, we want to squelch the error.
1695-
if (isConvertFunctionFromSendableType(equivalenceClassRep))
1721+
if (isHiddenSendableFunctionType(equivalenceClassRep))
16961722
return;
16971723
}
16981724
}

lib/Sema/TypeCheckAttr.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7856,9 +7856,6 @@ void AttributeChecker::visitInheritActorContextAttr(
78567856
return;
78577857

78587858
auto paramTy = P->getInterfaceType();
7859-
if (paramTy->hasError())
7860-
return;
7861-
78627859
auto *funcTy =
78637860
paramTy->lookThroughAllOptionalTypes()->getAs<AnyFunctionType>();
78647861
if (!funcTy) {

lib/Sema/TypeCheckDecl.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2337,9 +2337,6 @@ static Type validateParameterType(ParamDecl *decl) {
23372337
if (dc->isInSpecializeExtensionContext())
23382338
options |= TypeResolutionFlags::AllowUsableFromInline;
23392339

2340-
if (decl->getAttrs().hasAttribute<InheritActorContextAttr>())
2341-
options |= TypeResolutionFlags::InheritsActorContext;
2342-
23432340
Type Ty;
23442341

23452342
auto *nestedRepr = decl->getTypeRepr();

lib/Sema/TypeCheckType.cpp

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4217,11 +4217,6 @@ NeverNullType TypeResolver::resolveASTFunctionType(
42174217
attr->getAttrName());
42184218
}
42194219

4220-
if (options.contains(TypeResolutionFlags::InheritsActorContext)) {
4221-
diagnoseInvalid(repr, attr->getAttrLoc(),
4222-
diag::inherit_actor_context_with_concurrent, attr);
4223-
}
4224-
42254220
switch (isolation.getKind()) {
42264221
case FunctionTypeIsolation::Kind::NonIsolated:
42274222
break;
@@ -4268,20 +4263,18 @@ NeverNullType TypeResolver::resolveASTFunctionType(
42684263
if (!repr->isInvalid())
42694264
isolation = FunctionTypeIsolation::forNonIsolated();
42704265
} else if (!getWithoutClaiming<CallerIsolatedTypeRepr>(attrs)) {
4271-
if (!options.contains(TypeResolutionFlags::InheritsActorContext)) {
4272-
// Infer async function type as `nonisolated(nonsending)` if there is
4273-
// no `@concurrent` or `nonisolated(nonsending)` attribute and isolation
4274-
// is nonisolated.
4275-
if (ctx.LangOpts.hasFeature(Feature::NonisolatedNonsendingByDefault) &&
4276-
repr->isAsync() && isolation.isNonIsolated()) {
4277-
isolation = FunctionTypeIsolation::forNonIsolatedCaller();
4278-
} else if (ctx.LangOpts
4279-
.getFeatureState(Feature::NonisolatedNonsendingByDefault)
4280-
.isEnabledForMigration()) {
4281-
// Diagnose only in the interface stage, which is run once.
4282-
if (inStage(TypeResolutionStage::Interface)) {
4283-
warnAboutNewNonisolatedAsyncExecutionBehavior(ctx, repr, isolation);
4284-
}
4266+
// Infer async function type as `nonisolated(nonsending)` if there is
4267+
// no `@concurrent` or `nonisolated(nonsending)` attribute and isolation
4268+
// is nonisolated.
4269+
if (ctx.LangOpts.hasFeature(Feature::NonisolatedNonsendingByDefault) &&
4270+
repr->isAsync() && isolation.isNonIsolated()) {
4271+
isolation = FunctionTypeIsolation::forNonIsolatedCaller();
4272+
} else if (ctx.LangOpts
4273+
.getFeatureState(Feature::NonisolatedNonsendingByDefault)
4274+
.isEnabledForMigration()) {
4275+
// Diagnose only in the interface stage, which is run once.
4276+
if (inStage(TypeResolutionStage::Interface)) {
4277+
warnAboutNewNonisolatedAsyncExecutionBehavior(ctx, repr, isolation);
42854278
}
42864279
}
42874280
}
@@ -5331,12 +5324,6 @@ TypeResolver::resolveCallerIsolatedTypeRepr(CallerIsolatedTypeRepr *repr,
53315324
return ErrorType::get(getASTContext());
53325325
}
53335326

5334-
if (options.contains(TypeResolutionFlags::InheritsActorContext)) {
5335-
diagnoseInvalid(repr, repr->getLoc(),
5336-
diag::inherit_actor_context_with_nonisolated_nonsending,
5337-
repr);
5338-
}
5339-
53405327
if (!fnType->isAsync()) {
53415328
diagnoseInvalid(repr, repr->getStartLoc(),
53425329
diag::nonisolated_nonsending_only_on_async, repr);

lib/Sema/TypeCheckType.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,6 @@ enum class TypeResolutionFlags : uint16_t {
8787

8888
/// Whether the immediate context has an @escaping attribute.
8989
DirectEscaping = 1 << 14,
90-
91-
/// We are in a `@_inheritActorContext` parameter declaration.
92-
InheritsActorContext = 1 << 15,
9390
};
9491

9592
/// Type resolution contexts that require special handling.

test/Concurrency/attr_execution/attr_execution.swift

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,3 @@ func testClosure() {
8080
takesClosure {
8181
}
8282
}
83-
84-
// CHECK-LABEL: // testInheritsActor(fn:)
85-
// CHECK: Isolation: global_actor. type: MainActor
86-
// CHECK: sil hidden [ossa] @$s14attr_execution17testInheritsActor2fnyyyYaYbXE_tYaF : $@convention(thin) @async (@guaranteed @noescape @Sendable @async @callee_guaranteed () -> ()) -> ()
87-
// CHECK: bb0([[FN:%.*]] : @guaranteed $@noescape @Sendable @async @callee_guaranteed () -> ()):
88-
// CHECK: [[FN_COPY:%.*]] = copy_value [[FN]]
89-
// CHECK: [[BORROWED_FN_COPY:%.*]] = begin_borrow [[FN_COPY]]
90-
// CHECK: apply [[BORROWED_FN_COPY]]() : $@noescape @Sendable @async @callee_guaranteed () -> ()
91-
// CHECK: } // end sil function '$s14attr_execution17testInheritsActor2fnyyyYaYbXE_tYaF'
92-
@MainActor
93-
func testInheritsActor(@_inheritActorContext(always) fn: @Sendable () async -> Void) async {
94-
await fn()
95-
}

test/Concurrency/attr_execution/migration_mode.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -393,9 +393,3 @@ do {
393393
}
394394
}
395395
}
396-
397-
// @_inheritActorContext prevents `nonisolated(nonsending)` inference.
398-
do {
399-
func testInherit1(@_inheritActorContext _: @Sendable () async -> Void) {}
400-
func testInherit2(@_inheritActorContext(always) _: (@Sendable () async -> Void)?) {}
401-
}

test/Concurrency/attr_execution/nonisolated_nonsending_by_default.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,3 @@ func testCasts() {
88
// expected-error@-1 {{cannot convert value of type '(nonisolated(nonsending) () async -> ()).Type' to type '(() async -> ()).Type' in coercion}}
99
_ = defaultedType as (nonisolated(nonsending) () async -> ()).Type // Ok
1010
}
11-
12-
func test(@_inheritActorContext fn: @Sendable () async -> Void) {
13-
let _: Int = fn
14-
// expected-error@-1 {{cannot convert value of type '@Sendable () async -> Void' to specified type 'Int'}}
15-
}

test/Concurrency/transfernonsendable_global_actor_sending.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,8 @@ func useValue<T>(_ t: T) {}
3434
@MainActor func testGlobalFakeInit() {
3535
let ns = NonSendableKlass()
3636

37-
// Will be resolved once @MainActor is @Sendable.
38-
Task.fakeInit { @MainActor in // expected-error {{passing closure as a 'sending' parameter risks causing data races between main actor-isolated code and concurrent execution of the closure}}
39-
print(ns) // expected-note {{closure captures 'ns' which is accessible to main actor-isolated code}}
37+
Task.fakeInit { @MainActor in
38+
print(ns)
4039
}
4140

4241
useValue(ns)

0 commit comments

Comments
 (0)