Skip to content

Commit c34376b

Browse files
committed
Use generic signature instead of ASTContext to warn about sending on Sendable type
Follow PR review comments and extend the warnings about sending on sendable types to cover types with a type parameter, and use generic signature instead of ASTContext to check conformance to Sendable. Additionally, use different warning messages based on whether the sending on Sendable is used on a function parameter or function result.
1 parent 2b3e26d commit c34376b

File tree

8 files changed

+70
-44
lines changed

8 files changed

+70
-44
lines changed

include/swift/AST/DiagnosticsSema.def

+4-1
Original file line numberDiff line numberDiff line change
@@ -7952,9 +7952,12 @@ ERROR(sending_unsupported_param_specifier, none,
79527952
"'%0' cannot be applied to a 'sending' parameter", (StringRef))
79537953
ERROR(sending_only_on_parameters_and_results, none,
79547954
"'sending' may only be used on parameters and results", ())
7955-
WARNING(sending_applied_to_sendable, none,
7955+
WARNING(sending_applied_to_sendable_parameter, none,
79567956
"'sending' has no effect on Sendable parameter %0",
79577957
(Type))
7958+
WARNING(sending_applied_to_sendable_result, none,
7959+
"'sending' has no effect on Sendable function result type %0",
7960+
(Type))
79587961
ERROR(sending_cannot_be_applied_to_tuple_elt, none,
79597962
"'sending' cannot be applied to tuple elements", ())
79607963
ERROR(sending_function_wrong_sending,none,

lib/Sema/TypeCheckType.cpp

+15-16
Original file line numberDiff line numberDiff line change
@@ -4977,23 +4977,22 @@ TypeResolver::resolveSendingTypeRepr(SendingTypeRepr *repr,
49774977
}
49784978

49794979
NeverNullType resolvedType = resolveType(repr->getBase(), options);
4980-
4980+
49814981
// If resolved type is Sendable, warn about unnecessary 'sending' annotation.
4982-
if (options.is(TypeResolverContext::FunctionInput)) {
4983-
if(!resolvedType->hasTypeParameter()) {
4984-
if (resolvedType->isSendableType()) {
4985-
diagnose(repr->getSpecifierLoc(),
4986-
diag::sending_applied_to_sendable,
4987-
resolvedType.get())
4988-
.fixItRemove(repr->getSpecifierLoc());
4989-
}
4990-
} else {
4991-
if (resolvedType->getASTContext().getProtocol(KnownProtocolKind::Sendable)) {
4992-
diagnose(repr->getSpecifierLoc(),
4993-
diag::sending_applied_to_sendable,
4994-
resolvedType.get())
4995-
.fixItRemove(repr->getSpecifierLoc());
4996-
};
4982+
bool isFunctionParam = options.is(TypeResolverContext::FunctionInput);
4983+
bool isFunctionResult = options.is(TypeResolverContext::FunctionResult);
4984+
if (inStage(TypeResolutionStage::Interface)
4985+
&& (isFunctionParam || isFunctionResult)) {
4986+
auto contextTy = GenericEnvironment::mapTypeIntoContext(
4987+
resolution.getGenericSignature().getGenericEnvironment(),
4988+
resolvedType);
4989+
if (contextTy->isSendableType()) {
4990+
diagnose(repr->getSpecifierLoc(),
4991+
isFunctionParam
4992+
? diag::sending_applied_to_sendable_parameter
4993+
: diag::sending_applied_to_sendable_result,
4994+
resolvedType.get())
4995+
.fixItRemove(repr->getSpecifierLoc());
49974996
}
49984997
}
49994998

test/Parse/parameter_specifier_before_param_name.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ func foo(isolated x b: MyActor) {} // expected-warning {{'isolated' before a par
2020
func foo(_const x b: MyClass) {} // expected-warning {{'_const' before a parameter name is not allowed, place it before the parameter type instead; this is an error in the Swift 6 language mode}}
2121

2222
@available(SwiftStdlib 5.1, *)
23-
func foo(sending x b: MyActor) {} // expected-warning {{'sending' before a parameter name is not allowed, place it before the parameter type instead}}
23+
func foo(sending x b: MyClass) {} // expected-warning {{'sending' before a parameter name is not allowed, place it before the parameter type instead}}

test/Parse/sending.swift

+15-11
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,36 @@
22

33
// REQUIRES: asserts
44

5-
func testArg(_ x: sending String) {
5+
class NonSendable {
6+
init(){}
67
}
78

8-
func testResult() -> sending String {
9-
""
9+
func testArg(_ x: sending NonSendable) {
1010
}
1111

12-
func testArgResult(_ x: sending String) -> sending String {
12+
func testResult() -> sending NonSendable {
13+
return NonSendable()
14+
}
15+
16+
func testArgResult(_ x: sending NonSendable) -> sending NonSendable {
1317
}
1418

1519
func testVarDeclDoesntWork() {
16-
var x: sending String // expected-error {{'sending' may only be used on parameter}}
20+
var x: sending NonSendable // expected-error {{'sending' may only be used on parameter}}
1721
}
1822

19-
func testVarDeclTupleElt() -> (sending String, String) {} // expected-error {{'sending' cannot be applied to tuple elements}}
23+
func testVarDeclTupleElt() -> (sending NonSendable, NonSendable) {} // expected-error {{'sending' cannot be applied to tuple elements}}
2024

21-
func testVarDeclTuple2(_ x: (sending String)) {}
22-
func testVarDeclTuple2(_ x: (sending String, String)) {} // expected-error {{'sending' cannot be applied to tuple elements}}
25+
func testVarDeclTuple2(_ x: (sending NonSendable)) {}
26+
func testVarDeclTuple2(_ x: (sending NonSendable, NonSendable)) {} // expected-error {{'sending' cannot be applied to tuple elements}}
2327

24-
func testArgWithConsumingWrongOrder(_ x: sending consuming String, _ y: sending inout String) {}
28+
func testArgWithConsumingWrongOrder(_ x: sending consuming NonSendable, _ y: sending inout NonSendable) {}
2529
// expected-error @-1 {{'sending' must be placed after specifier 'consuming'}}
2630
// expected-error @-2 {{'sending' must be placed after specifier 'inout'}}
2731

28-
func testArgWithConsumingWrongOrderType(_ x: (sending consuming String, sending inout String) -> ()) {}
32+
func testArgWithConsumingWrongOrderType(_ x: (sending consuming NonSendable, sending inout NonSendable) -> ()) {}
2933
// expected-error @-1 {{'sending' must be placed after specifier 'consuming'}}
3034
// expected-error @-2 {{'sending' must be placed after specifier 'inout'}}
3135

32-
func testBorrowSending(_ x: borrowing sending String) {}
36+
func testBorrowSending(_ x: borrowing sending NonSendable) {}
3337
// expected-error @-1 {{'sending' cannot be used together with 'borrowing'}}

test/Sema/consume_operator_noop_warning.swift

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ func proofOfUseAfterConsume() -> Int {
4343
func moreProofs(_ share: __shared Int,
4444
_ own: __owned Int,
4545
_ snd: sending Int, // expected-error {{'snd' used after consume}}
46+
// expected-warning @-1 {{'sending' has no effect on Sendable parameter}}
4647
_ ino: inout Int, // expected-error {{'ino' used after consume}}
4748
_ brw: borrowing Int, // expected-error {{'brw' is borrowed and cannot be consumed}}
4849
_ csm: consuming Int // expected-error {{'csm' consumed more than once}}

test/Sema/sending.swift

+10-6
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,23 @@
66
// README: This test makes sure that we error when sending is placed in the
77
// wrong place with respect to ownership modifiers.
88

9-
func test_good(_ x: sending Int) {}
9+
class NonSendable {
10+
init(){}
11+
}
1012

11-
func test_consuming_after_sending(_ x: sending consuming Int) {} // expected-error {{'sending' must be placed after specifier 'consuming'}}
13+
func test_good(_ x: sending NonSendable) {}
1214

13-
func test_inout_after_sending(_ x: sending inout Int) {} // expected-error {{'sending' must be placed after specifier 'inout'}}
15+
func test_consuming_after_sending(_ x: sending consuming NonSendable) {} // expected-error {{'sending' must be placed after specifier 'consuming'}}
1416

15-
func test_repeated_sending(_ x: sending sending Int) {} // expected-error {{parameter may have at most one 'sending' specifier}}
17+
func test_inout_after_sending(_ x: sending inout NonSendable) {} // expected-error {{'sending' must be placed after specifier 'inout'}}
1618

17-
func test_repeated_sending_mixed(_ x: sending consuming sending inout Int) {}
19+
func test_repeated_sending(_ x: sending sending NonSendable) {} // expected-error {{parameter may have at most one 'sending' specifier}}
20+
21+
func test_repeated_sending_mixed(_ x: sending consuming sending inout NonSendable) {}
1822
// expected-error @-1 {{'sending' must be placed after specifier 'consuming'}}
1923
// expected-error @-2 {{parameter may have at most one 'sending' specifier}}
2024
// expected-error @-3 {{parameter may have at most one of the 'inout', 'borrowing', or 'consuming' specifiers}}
2125

2226
// Just until we get the results setup.
23-
func test_sending_result_in_tuple() -> (sending Int, Int) {}
27+
func test_sending_result_in_tuple() -> (sending NonSendable, NonSendable) {}
2428
// expected-error @-1 {{'sending' cannot be applied to tuple elements}}
+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11

22
public func testSending(_ x: sending String) -> sending String { x }
3+
// expected-warning @-1 {{'sending' has no effect on Sendable parameter}}
34
public func testSendingFunc(_ x: (sending String) -> ()) { fatalError() }
5+
// expected-warning @-1 {{'sending' has no effect on Sendable parameter}}
46
public func testSendingResultFunc(_ x: () -> sending String) { fatalError() }
7+
// expected-warning @-1 {{'sending' has no effect on Sendable parameter}}
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,32 @@
11
// RUN: %target-swift-frontend -module-name TestModule -typecheck -verify %s
22

33
struct SendableType {}
4-
class NonSendableType {}
4+
class NonSendableType {
5+
init() {}
6+
}
7+
struct SendableTypeWithTypeParam<SendableType> {}
58

6-
func testSendingOnNonSendable(input: sending NonSendableType) {
7-
// okay
9+
func testSendingOnNonSendable(input: sending NonSendableType) -> sending NonSendableType {
10+
return NonSendableType() // okay
811
}
912

10-
func testSendingOnSendable(input: sending SendableType) {
11-
// expected-warning@-1{{'sending' has no effect}}{{35-43=}}
13+
func testSendingOnSendableParam(input: sending SendableType) {
14+
// expected-warning@-1{{'sending' has no effect}}{{40-48=}}
1215
}
1316

14-
func testSendingOnSendable(input: sending some Sendable) {
17+
func testSendingOnSendable(input: sending SendableTypeWithTypeParam<SendableType>) {
1518
// expected-warning@-1{{'sending' has no effect}}{{35-43=}}
1619
}
1720

18-
func testSendingOnSendable(input: sending any Sendable) {
19-
// expected-warning@-1{{'sending' has no effect}}{{35-43=}}
20-
}
21+
func testSendingOnSendableParam(input: sending some Sendable) {
22+
// expected-warning@-1{{'sending' has no effect}}{{40-48=}}
23+
}
24+
25+
func testSendingOnSendableParam(input: sending any Sendable) {
26+
// expected-warning@-1{{'sending' has no effect}}{{40-48=}}
27+
}
28+
29+
func testSendingOnSendableResult() -> sending SendableType {
30+
// expected-warning@-1{{'sending' has no effect}}{{39-47=}}
31+
return SendableType()
32+
}

0 commit comments

Comments
 (0)