Skip to content

Commit c8d9e18

Browse files
committed
[sending] Make the protocol errors only occur in swift 6.
For now, just turn off the error in swift 5 mode. I wanted to make this an error but right now I do not have all of the time to do it so this is good in the short term so that people can adopt sending on protocols without breaking people using their framework in executables still compiling in swift 5.
1 parent 16d0194 commit c8d9e18

File tree

2 files changed

+117
-6
lines changed

2 files changed

+117
-6
lines changed

lib/Sema/TypeCheckProtocol.cpp

+10-6
Original file line numberDiff line numberDiff line change
@@ -746,9 +746,11 @@ RequirementMatch swift::matchWitness(
746746
// If our requirement says that it has a sending result, then our witness
747747
// must also have a sending result since otherwise, in generic contexts,
748748
// we would be returning non-disconnected values as disconnected.
749-
if (reqFnType->hasExtInfo() && reqFnType->hasSendingResult() &&
750-
(!witnessFnType->hasExtInfo() || !witnessFnType->hasSendingResult()))
751-
return RequirementMatch(witness, MatchKind::TypeConflict, witnessType);
749+
if (dc->getASTContext().LangOpts.isSwiftVersionAtLeast(6)) {
750+
if (reqFnType->hasExtInfo() && reqFnType->hasSendingResult() &&
751+
(!witnessFnType->hasExtInfo() || !witnessFnType->hasSendingResult()))
752+
return RequirementMatch(witness, MatchKind::TypeConflict, witnessType);
753+
}
752754

753755
if (auto result = matchTypes(std::get<0>(types), std::get<1>(types))) {
754756
return std::move(result.value());
@@ -784,9 +786,11 @@ RequirementMatch swift::matchWitness(
784786

785787
// If we have a requirement without sending and our witness expects a
786788
// sending parameter, error.
787-
if (!reqParams[i].getParameterFlags().isSending() &&
788-
witnessParams[i].getParameterFlags().isSending())
789-
return RequirementMatch(witness, MatchKind::TypeConflict, witnessType);
789+
if (dc->getASTContext().isSwiftVersionAtLeast(6)) {
790+
if (!reqParams[i].getParameterFlags().isSending() &&
791+
witnessParams[i].getParameterFlags().isSending())
792+
return RequirementMatch(witness, MatchKind::TypeConflict, witnessType);
793+
}
790794

791795
auto reqParamDecl = reqParamList->get(i);
792796
auto witnessParamDecl = witnessParamList->get(i);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// RUN: %target-typecheck-verify-swift -swift-version 5
2+
3+
// READ THIS! This file only contains tests that validate how the relevant
4+
// function subtyping rules for sending work in swift 5 mode
5+
// specifically. Please do not put other tests in the file!
6+
//
7+
// We expect today that protocol mismatch errors are elided and function
8+
// mismatch errors are warnings.
9+
10+
// REQUIRES: concurrency
11+
// REQUIRES: asserts
12+
13+
////////////////////////
14+
// MARK: Declarations //
15+
////////////////////////
16+
17+
class NonSendableKlass {}
18+
19+
protocol ProtocolWithSendingReqs {
20+
func sendingResult() -> sending NonSendableKlass
21+
func nonSendingParam(_ x: NonSendableKlass)
22+
}
23+
24+
protocol ProtocolWithMixedReqs {
25+
func nonSendingParamAndSendingResult(_ x: NonSendableKlass) -> sending NonSendableKlass
26+
}
27+
28+
/////////////////////////////////
29+
// MARK: Normal Function Tests //
30+
/////////////////////////////////
31+
32+
func functionWithSendingResult() -> sending NonSendableKlass { fatalError() }
33+
func functionWithoutSendingResult() -> NonSendableKlass { fatalError() }
34+
func functionWithSendingParameter(_ x: sending NonSendableKlass) { fatalError() }
35+
func functionWithoutSendingParameter(_ x: NonSendableKlass) { fatalError() }
36+
37+
func takeFnWithSendingResult(_ fn: () -> sending NonSendableKlass) {}
38+
func takeFnWithoutSendingResult(_ fn: () -> NonSendableKlass) {}
39+
func takeFnWithSendingParam(_ fn: (sending NonSendableKlass) -> ()) {}
40+
func takeFnWithoutSendingParam(_ fn: (NonSendableKlass) -> ()) {}
41+
42+
func testFunctionMatching() {
43+
let _: (NonSendableKlass) -> () = functionWithSendingParameter
44+
// expected-warning @-1 {{converting a value of type '(sending NonSendableKlass) -> ()' to type '(NonSendableKlass) -> ()' risks causing data races}}
45+
// expected-note @-2 {{converting a function typed value with a sending parameter to one without risks allowing actor-isolated values to escape their isolation domain as an argument to an invocation of value}}
46+
let _: (sending NonSendableKlass) -> () = functionWithSendingParameter
47+
48+
let _: (NonSendableKlass) -> () = functionWithoutSendingParameter
49+
let _: (sending NonSendableKlass) -> () = functionWithoutSendingParameter
50+
51+
takeFnWithSendingParam(functionWithSendingParameter)
52+
takeFnWithoutSendingParam(functionWithSendingParameter)
53+
// expected-warning @-1 {{converting a value of type '(sending NonSendableKlass) -> ()' to type '(NonSendableKlass) -> ()' risks causing data races}}
54+
// expected-note @-2 {{converting a function typed value with a sending parameter to one without risks allowing actor-isolated values to escape their isolation domain as an argument to an invocation of value}}
55+
takeFnWithSendingParam(functionWithoutSendingParameter)
56+
takeFnWithoutSendingParam(functionWithoutSendingParameter)
57+
}
58+
59+
func testReturnValueMatching() {
60+
let _: () -> NonSendableKlass = functionWithSendingResult
61+
let _: () -> sending NonSendableKlass = functionWithSendingResult
62+
let _: () -> NonSendableKlass = functionWithoutSendingResult
63+
let _: () -> sending NonSendableKlass = functionWithoutSendingResult
64+
// expected-warning @-1 {{converting a value of type '() -> NonSendableKlass' to type '() -> sending NonSendableKlass' risks causing data races}}
65+
// expected-note @-2 {{converting a function typed value without a sending result as one with risks allowing actor-isolated values to escape their isolation domain through a result of an invocation of value}}
66+
67+
takeFnWithSendingResult(functionWithSendingResult)
68+
takeFnWithSendingResult(functionWithoutSendingResult)
69+
// expected-warning @-1 {{converting a value of type '() -> NonSendableKlass' to type '() -> sending NonSendableKlass' risks causing data races}}
70+
// expected-note @-2 {{converting a function typed value without a sending result as one with risks allowing actor-isolated values to escape their isolation domain through a result of an invocation of value}}
71+
let x: () -> NonSendableKlass = { fatalError() }
72+
takeFnWithSendingResult(x)
73+
// expected-warning @-1 {{converting a value of type '() -> NonSendableKlass' to type '() -> sending NonSendableKlass' risks causing data races}}
74+
// expected-note @-2 {{converting a function typed value without a sending result as one with risks allowing actor-isolated values to escape their isolation domain through a result of an invocation of value}}
75+
76+
takeFnWithoutSendingResult(functionWithSendingResult)
77+
takeFnWithoutSendingResult(functionWithoutSendingResult)
78+
takeFnWithoutSendingResult(x)
79+
}
80+
81+
//////////////////////////
82+
// MARK: Protocol Tests //
83+
//////////////////////////
84+
85+
struct MatchSuccess : ProtocolWithSendingReqs, ProtocolWithMixedReqs {
86+
func sendingResult() -> sending NonSendableKlass { fatalError() }
87+
func nonSendingParam(_ x: NonSendableKlass) -> () { fatalError() }
88+
func nonSendingParamAndSendingResult(_ x: NonSendableKlass) -> sending NonSendableKlass { fatalError() }
89+
}
90+
91+
struct FailToMatch : ProtocolWithSendingReqs, ProtocolWithMixedReqs {
92+
func sendingResult() -> NonSendableKlass { fatalError() }
93+
func nonSendingParam(_ x: sending NonSendableKlass) -> () { fatalError() }
94+
func nonSendingParamAndSendingResult(_ x: sending NonSendableKlass) -> NonSendableKlass { fatalError() }
95+
}
96+
97+
struct FailToMatch2 : ProtocolWithMixedReqs {
98+
func nonSendingParamAndSendingResult(_ x: sending NonSendableKlass) -> NonSendableKlass { fatalError() }
99+
}
100+
101+
struct FailToMatch3 : ProtocolWithMixedReqs {
102+
func nonSendingParamAndSendingResult(_ x: NonSendableKlass) -> NonSendableKlass { fatalError() }
103+
}
104+
105+
struct FailToMatch4 : ProtocolWithMixedReqs {
106+
func nonSendingParamAndSendingResult(_ x: sending NonSendableKlass) -> sending NonSendableKlass { fatalError() }
107+
}

0 commit comments

Comments
 (0)