Skip to content

Commit 290ec79

Browse files
committed
Respect @preconcurrency in the diagnostic for @Sendable methods of non-Sendable types
1 parent 94a2529 commit 290ec79

File tree

7 files changed

+34
-21
lines changed

7 files changed

+34
-21
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5520,8 +5520,8 @@ ERROR(sendable_isolated_sync_function,none,
55205520
"%0 synchronous %kind1 cannot be marked as '@Sendable'",
55215521
(ActorIsolation, const ValueDecl *))
55225522
ERROR(nonsendable_instance_method,none,
5523-
"instance methods of non-Sendable types cannot be marked as '@Sendable'",
5524-
())
5523+
"instance method of non-Sendable type %0 cannot be marked as '@Sendable'",
5524+
(Type))
55255525
ERROR(concurrent_access_of_local_capture,none,
55265526
"%select{mutation of|reference to}0 captured %kind1 in "
55275527
"concurrently-executing code",

lib/Sema/TypeCheckAttr.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6938,10 +6938,13 @@ void AttributeChecker::visitSendableAttr(SendableAttr *attr) {
69386938
// Prevent Sendable Attr from being added to methods of non-sendable types
69396939
if (auto *funcDecl = dyn_cast<AbstractFunctionDecl>(D)) {
69406940
if (auto selfDecl = funcDecl->getImplicitSelfDecl()) {
6941-
if (!selfDecl->getTypeInContext()->isSendableType()) {
6942-
diagnose(attr->getLocation(), diag::nonsendable_instance_method)
6943-
.warnUntilSwiftVersion(6);
6944-
}
6941+
diagnoseIfAnyNonSendableTypes(
6942+
selfDecl->getTypeInContext(),
6943+
SendableCheckContext(funcDecl),
6944+
Type(),
6945+
SourceLoc(),
6946+
attr->getLocation(),
6947+
diag::nonsendable_instance_method);
69456948
}
69466949
}
69476950
}

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,6 @@ static bool varIsSafeAcrossActors(const ModuleDecl *fromModule,
511511
return true;
512512

513513
if (!var->isLet()) {
514-
ASTContext &ctx = var->getASTContext();
515514
// A mutable storage of a value type accessed from within the module is
516515
// okay.
517516
if (dyn_cast_or_null<StructDecl>(var->getDeclContext()->getAsDecl()) &&

test/Concurrency/predates_concurrency_import.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,11 @@ let nonStrictGlobal = NonStrictClass() // no warning
3333

3434
let strictGlobal = StrictStruct() // expected-warning{{let 'strictGlobal' is not concurrency-safe because non-'Sendable' type 'StrictStruct' may have shared mutable state}}
3535
// expected-note@-1{{isolate 'strictGlobal' to a global actor, or conform 'StrictStruct' to 'Sendable'}}
36+
37+
extension NonStrictClass {
38+
@Sendable func f() { }
39+
}
40+
41+
extension StrictStruct {
42+
@Sendable func f() { } // expected-warning{{instance method of non-Sendable type 'StrictStruct' cannot be marked as '@Sendable'}}
43+
}

test/Concurrency/predates_concurrency_import_swift6.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,11 @@ func test(ss: StrictStruct, ns: NonStrictClass) {
1919
let nonStrictGlobal = NonStrictClass()
2020
let strictGlobal = StrictStruct() // expected-warning{{let 'strictGlobal' is not concurrency-safe because non-'Sendable' type 'StrictStruct' may have shared mutable state}}
2121
// expected-note@-1{{isolate 'strictGlobal' to a global actor, or conform 'StrictStruct' to 'Sendable'}}
22+
23+
extension NonStrictClass {
24+
@Sendable func f() { }
25+
}
26+
27+
extension StrictStruct {
28+
@Sendable func f() { } // expected-warning{{instance method of non-Sendable type 'StrictStruct' cannot be marked as '@Sendable'}}
29+
}

test/Concurrency/sendable_functions.swift

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
// RUN: %target-swift-frontend -emit-sil -o /dev/null -verify %s
2-
// RUN: %target-swift-frontend -emit-sil -o /dev/null -verify %s -strict-concurrency=targeted
1+
// RUN: %target-swift-frontend -emit-sil -o /dev/null -verify %s -strict-concurrency=complete
32
// RUN: %target-swift-frontend -emit-sil -o /dev/null -verify %s -strict-concurrency=complete
43
// RUN: %target-swift-frontend -emit-sil -o /dev/null -verify %s -strict-concurrency=complete -enable-upcoming-feature RegionBasedIsolation
54

@@ -23,18 +22,18 @@ actor A {
2322
}
2423
}
2524

26-
class NonSendableC {
25+
class NonSendableC { // expected-note{{class 'NonSendableC' does not conform to the 'Sendable' protocol}}
2726
var x: Int = 0
2827

29-
@Sendable func inc() { // expected-warning{{instance methods of non-Sendable types cannot be marked as '@Sendable'}}
28+
@Sendable func inc() { // expected-warning{{instance method of non-Sendable type 'NonSendableC' cannot be marked as '@Sendable'}}
3029
x += 1
3130
}
3231
}
3332

34-
struct S<T> {
33+
struct S<T> { // expected-note{{consider making generic parameter 'T' conform to the 'Sendable' protocol}}
3534
let t: T
3635

37-
@Sendable func test() {} // expected-warning{{instance methods of non-Sendable types cannot be marked as '@Sendable'}}
36+
@Sendable func test() {} // expected-warning{{instance method of non-Sendable type 'S<T>' cannot be marked as '@Sendable'}}
3837
}
3938

4039
extension S: Sendable where T: Sendable {

test/Concurrency/sendable_methods.swift

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %target-typecheck-verify-swift -enable-upcoming-feature InferSendableFromCaptures -disable-availability-checking
2-
// RUN: %target-swift-emit-silgen %s -verify -enable-upcoming-feature InferSendableFromCaptures -disable-availability-checking -module-name sendable_methods | %FileCheck %s
1+
// RUN: %target-typecheck-verify-swift -enable-upcoming-feature InferSendableFromCaptures -disable-availability-checking -strict-concurrency=complete
2+
// RUN: %target-swift-emit-silgen %s -verify -enable-upcoming-feature InferSendableFromCaptures -disable-availability-checking -module-name sendable_methods -strict-concurrency=complete | %FileCheck %s
33

44
// REQUIRES: concurrency
55
// REQUIRES: asserts
@@ -151,10 +151,10 @@ struct World {
151151

152152
let helloworld: @Sendable () -> Void = World.greet
153153

154-
class NonSendableC {
154+
class NonSendableC { // expected-note{{class 'NonSendableC' does not conform to the 'Sendable' protocol}}
155155
var x: Int = 0
156156

157-
@Sendable func inc() { // expected-warning {{instance methods of non-Sendable types cannot be marked as '@Sendable'; this is an error in the Swift 6 language mode}}
157+
@Sendable func inc() { // expected-warning {{instance method of non-Sendable type 'NonSendableC' cannot be marked as '@Sendable'}}
158158
x += 1
159159
}
160160
}
@@ -186,10 +186,6 @@ struct SomeGlobalActor {
186186
static var shared: TestActor { TestActor() }
187187
}
188188

189-
@SomeGlobalActor
190-
let globalValue: NonSendable = NonSendable()
191-
192-
193189
@SomeGlobalActor
194190
// CHECK-LABEL: sil hidden [ossa] @$s16sendable_methods8generic3yyxYalF : $@convention(thin) @async <T> (@in_guaranteed T) -> ()
195191
//

0 commit comments

Comments
 (0)