Skip to content

Commit f39041d

Browse files
authored
Merge pull request #74068 from gottesmm/release/6.0-rdar129045783
[6.0][sending] Fix a bunch of issues around suppressing sending
2 parents 39951b0 + 0cdabb4 commit f39041d

File tree

3 files changed

+191
-10
lines changed

3 files changed

+191
-10
lines changed

lib/AST/ASTPrinter.cpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
#include "clang/Lex/MacroInfo.h"
6363
#include "llvm/ADT/STLExtras.h"
6464
#include "llvm/ADT/StringSwitch.h"
65+
#include "llvm/Support/CommandLine.h"
6566
#include "llvm/Support/Compiler.h"
6667
#include "llvm/Support/ConvertUTF.h"
6768
#include "llvm/Support/SaveAndRestore.h"
@@ -71,6 +72,15 @@
7172

7273
using namespace swift;
7374

75+
#ifndef NDEBUG
76+
static llvm::cl::opt<bool> NumberSuppressionChecks(
77+
"swift-ast-printer-number-suppression-checks",
78+
llvm::cl::desc("Used to number suppression checks in swift interface files "
79+
"to make it easier to FileCheck them. Only available with "
80+
"asserts enabled and intended for compiler tests."),
81+
llvm::cl::init(false), llvm::cl::Hidden);
82+
#endif
83+
7484
// Defined here to avoid repeatedly paying the price of template instantiation.
7585
const std::function<bool(const ExtensionDecl *)>
7686
PrintOptions::defaultPrintExtensionContentAsMembers
@@ -3205,6 +3215,15 @@ static void printCompatibilityCheckIf(ASTPrinter &printer, bool isElseIf,
32053215
}
32063216
printer << "$" << getFeatureName(feature);
32073217
}
3218+
3219+
#ifndef NDEBUG
3220+
if (NumberSuppressionChecks) {
3221+
static unsigned totalSuppressionChecks = 0;
3222+
printer << " // Suppression Count: " << totalSuppressionChecks;
3223+
++totalSuppressionChecks;
3224+
}
3225+
#endif
3226+
32083227
printer.printNewline();
32093228
}
32103229

@@ -3295,10 +3314,13 @@ void swift::printWithCompatibilityFeatureChecks(ASTPrinter &printer,
32953314
// features, or else just print the body.
32963315
if (features.hasAnySuppressible()) {
32973316
auto generator = features.generateSuppressibleFeatures();
3317+
3318+
// NOTE: We emit the compiler check here as well since that also implicitly
3319+
// ensures that we ignore parsing errors in the if block. It is harmless
3320+
// otherwise.
32983321
printWithSuppressibleFeatureChecks(printer, options,
3299-
/*first*/ true,
3300-
/*compiler check*/ !hasRequiredFeatures,
3301-
generator,
3322+
/*first*/ true,
3323+
/*compiler check*/ true, generator,
33023324
printBody);
33033325
} else {
33043326
printBody();

lib/AST/FeatureSet.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -643,8 +643,7 @@ UNINTERESTING_FEATURE(GroupActorErrors)
643643

644644
UNINTERESTING_FEATURE(TransferringArgsAndResults)
645645
static bool usesFeatureSendingArgsAndResults(Decl *decl) {
646-
auto functionTypeUsesSending = [](Decl *decl) {
647-
return usesTypeMatching(decl, [](Type type) {
646+
auto isFunctionTypeWithSending = [](Type type) {
648647
auto fnType = type->getAs<AnyFunctionType>();
649648
if (!fnType)
650649
return false;
@@ -656,28 +655,40 @@ static bool usesFeatureSendingArgsAndResults(Decl *decl) {
656655
[](AnyFunctionType::Param param) {
657656
return param.getParameterFlags().isSending();
658657
});
659-
});
658+
};
659+
auto declUsesFunctionTypesThatUseSending = [&](Decl *decl) {
660+
return usesTypeMatching(decl, isFunctionTypeWithSending);
660661
};
661662

662663
if (auto *pd = dyn_cast<ParamDecl>(decl)) {
663664
if (pd->isSending()) {
664665
return true;
665666
}
666667

667-
if (functionTypeUsesSending(pd))
668+
if (declUsesFunctionTypesThatUseSending(pd))
668669
return true;
669670
}
670671

671-
if (auto *fDecl = dyn_cast<FuncDecl>(decl)) {
672+
if (auto *fDecl = dyn_cast<AbstractFunctionDecl>(decl)) {
672673
// First check for param decl results.
673674
if (llvm::any_of(fDecl->getParameters()->getArray(), [](ParamDecl *pd) {
674675
return usesFeatureSendingArgsAndResults(pd);
675676
}))
676677
return true;
677-
if (functionTypeUsesSending(decl))
678+
if (declUsesFunctionTypesThatUseSending(decl))
678679
return true;
679680
}
680681

682+
// Check if we have a pattern binding decl for a function that has sending
683+
// parameters and results.
684+
if (auto *pbd = dyn_cast<PatternBindingDecl>(decl)) {
685+
for (auto index : range(pbd->getNumPatternEntries())) {
686+
auto *pattern = pbd->getPattern(index);
687+
if (pattern->hasType() && isFunctionTypeWithSending(pattern->getType()))
688+
return true;
689+
}
690+
}
691+
681692
return false;
682693
}
683694

test/Concurrency/sending_conditional_suppression.swift

Lines changed: 149 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// RUN: %empty-directory(%t)
22

3-
// RUN: %target-swift-frontend -enable-upcoming-feature SendingArgsAndResults -swift-version 5 -enable-library-evolution -module-name test -emit-module -o %t/test.swiftmodule -emit-module-interface-path - %s | %FileCheck %s
3+
// RUN: %target-swift-frontend -enable-upcoming-feature SendingArgsAndResults -swift-version 5 -enable-library-evolution -module-name test -emit-module -o %t/test.swiftmodule -emit-module-interface-path - -disable-availability-checking -Xllvm -swift-ast-printer-number-suppression-checks %s | %FileCheck %s
4+
5+
// REQUIRES: asserts
46

57
public class NonSendableKlass {}
68

@@ -90,4 +92,150 @@ public struct TestInStruct {
9092
// CHECK-NEXT: public func testKlassArgAndResult(_ x: test.NonSendableKlass, _ y: test.NonSendableKlass, z: test.NonSendableKlass) -> test.NonSendableKlass
9193
// CHECK-NEXT: #endif
9294
public func testKlassArgAndResult(_ x: NonSendableKlass, _ y: sending NonSendableKlass, z: NonSendableKlass) -> sending NonSendableKlass { fatalError() }
95+
96+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
97+
// CHECK-NEXT: public func testFunctionArg(_ x: () -> sending test.NonSendableKlass)
98+
// CHECK-NEXT: #else
99+
// CHECK-NEXT: public func testFunctionArg(_ x: () -> test.NonSendableKlass)
100+
// CHECK-NEXT: #endif
101+
public func testFunctionArg(_ x: () -> sending NonSendableKlass) { fatalError() }
102+
103+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
104+
// CHECK-NEXT: public func testFunctionResult() -> (() -> sending test.NonSendableKlass)
105+
// CHECK-NEXT: #else
106+
// CHECK-NEXT: public func testFunctionResult() -> (() -> test.NonSendableKlass)
107+
// CHECK-NEXT: #endif
108+
public func testFunctionResult() -> (() -> sending NonSendableKlass) { fatalError() }
109+
110+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
111+
// CHECK-NEXT: @usableFromInline
112+
// CHECK-NEXT: internal func testUsableFromInlineKlassArg(_ x: sending test.NonSendableKlass)
113+
// CHECK-NEXT: #else
114+
// CHECK-NEXT: @usableFromInline
115+
// CHECK-NEXT: internal func testUsableFromInlineKlassArg(_ x: test.NonSendableKlass)
116+
// CHECK-NEXT: #endif
117+
@usableFromInline func testUsableFromInlineKlassArg(_ x: sending NonSendableKlass) { fatalError() }
118+
119+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
120+
// CHECK-NEXT: @usableFromInline
121+
// CHECK-NEXT: internal func testUsableFromInlineKlassResult() -> sending test.NonSendableKlass
122+
// CHECK-NEXT: #else
123+
// CHECK-NEXT: @usableFromInline
124+
// CHECK-NEXT: internal func testUsableFromInlineKlassResult() -> test.NonSendableKlass
125+
// CHECK-NEXT: #endif
126+
@usableFromInline
127+
func testUsableFromInlineKlassResult() -> sending NonSendableKlass { fatalError() }
128+
129+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
130+
// CHECK-NEXT: @usableFromInline
131+
// CHECK-NEXT: internal func testUsableFromInlineKlassArgAndResult(_ x: test.NonSendableKlass, _ y: sending test.NonSendableKlass, z: test.NonSendableKlass) -> sending test.NonSendableKlass
132+
// CHECK-NEXT: #else
133+
// CHECK-NEXT: @usableFromInline
134+
// CHECK-NEXT: internal func testUsableFromInlineKlassArgAndResult(_ x: test.NonSendableKlass, _ y: test.NonSendableKlass, z: test.NonSendableKlass) -> test.NonSendableKlass
135+
// CHECK-NEXT: #endif
136+
@usableFromInline
137+
func testUsableFromInlineKlassArgAndResult(_ x: NonSendableKlass, _ y: sending NonSendableKlass, z: NonSendableKlass) -> sending NonSendableKlass { fatalError() }
138+
139+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
140+
// CHECK-NEXT: @usableFromInline
141+
// CHECK-NEXT: internal func testUsableFromInlineFunctionArg(_ x: () -> sending test.NonSendableKlass)
142+
// CHECK-NEXT: #else
143+
// CHECK-NEXT: @usableFromInline
144+
// CHECK-NEXT: internal func testUsableFromInlineFunctionArg(_ x: () -> test.NonSendableKlass)
145+
// CHECK-NEXT: #endif
146+
@usableFromInline
147+
func testUsableFromInlineFunctionArg(_ x: () -> sending NonSendableKlass) { fatalError() }
148+
149+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
150+
// CHECK-NEXT: @usableFromInline
151+
// CHECK-NEXT: internal func testUsableFromInlineFunctionResult() -> (() -> sending test.NonSendableKlass)
152+
// CHECK-NEXT: #else
153+
// CHECK-NEXT: @usableFromInline
154+
// CHECK-NEXT: internal func testUsableFromInlineFunctionResult() -> (() -> test.NonSendableKlass)
155+
// CHECK-NEXT: #endif
156+
@usableFromInline
157+
func testUsableFromInlineFunctionResult() -> (() -> sending NonSendableKlass) { fatalError() }
158+
159+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
160+
// CHECK-NEXT: public var publicVarFieldFunctionArg: (sending test.NonSendableKlass) -> ()
161+
// CHECK-NEXT: #else
162+
// CHECK-NEXT: public var publicVarFieldFunctionArg: (test.NonSendableKlass) -> ()
163+
// CHECK-NEXT: #endif
164+
public var publicVarFieldFunctionArg: (sending NonSendableKlass) -> ()
165+
166+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
167+
// CHECK-NEXT: @usableFromInline
168+
// CHECK-NEXT: internal var internalVarFieldFunctionArg: (sending test.NonSendableKlass) -> ()
169+
// CHECK-NEXT: #else
170+
// CHECK-NEXT: @usableFromInline
171+
// CHECK-NEXT: internal var internalVarFieldFunctionArg: (test.NonSendableKlass) -> ()
172+
// CHECK-NEXT: #endif
173+
@usableFromInline
174+
var internalVarFieldFunctionArg: (sending NonSendableKlass) -> ()
175+
176+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
177+
// CHECK-NEXT: public let publicLetFieldFunctionArg: (sending test.NonSendableKlass) -> ()
178+
// CHECK-NEXT: #else
179+
// CHECK-NEXT: public let publicLetFieldFunctionArg: (test.NonSendableKlass) -> ()
180+
// CHECK-NEXT: #endif
181+
public let publicLetFieldFunctionArg: (sending NonSendableKlass) -> ()
182+
183+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
184+
// CHECK-NEXT: @usableFromInline
185+
// CHECK-NEXT: internal let internalLetFieldFunctionArg: (sending test.NonSendableKlass) -> ()
186+
// CHECK-NEXT: #else
187+
// CHECK-NEXT: @usableFromInline
188+
// CHECK-NEXT: internal let internalLetFieldFunctionArg: (test.NonSendableKlass) -> ()
189+
// CHECK-NEXT: #endif
190+
@usableFromInline
191+
let internalLetFieldFunctionArg: (sending NonSendableKlass) -> ()
192+
193+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults
194+
// CHECK-NEXT: @usableFromInline
195+
// CHECK-NEXT: internal init(_ x: Swift.Int, transformWithResult: @escaping () async throws -> sending test.NonSendableKlass)
196+
// CHECK-NEXT: #else
197+
// CHECK-NEXT: @usableFromInline
198+
// CHECK-NEXT: internal init(_ x: Swift.Int, transformWithResult: @escaping () async throws -> test.NonSendableKlass)
199+
// CHECK-NEXT: #endif
200+
@usableFromInline
201+
internal init(_ x: Int, transformWithResult: @escaping () async throws -> sending NonSendableKlass) { fatalError() }
93202
}
203+
204+
// Make sure that we emit compiler(>= 5.3) when emitting the suppressing check
205+
// to make sure we do not fail if we fail to parse sending in the if block.
206+
207+
// CHECK-LABEL: #if compiler(>=5.3) && $OptionalIsolatedParameters && $ExpressionMacroDefaultArguments // Suppression Count: 24
208+
// CHECK-NEXT: #if compiler(>=5.3) && $SendingArgsAndResults // Suppression Count: 25
209+
// CHECK-NEXT: @inlinable public func withCheckedContinuation<T>(isolation: isolated (any _Concurrency.Actor)? = #isolation, function: Swift.String = #function, _ body: (_Concurrency.CheckedContinuation<T, Swift.Never>) -> Swift.Void) async -> sending T {
210+
// CHECK-NEXT: fatalError()
211+
// CHECK-NEXT: }
212+
// CHECK-NEXT: #else
213+
// CHECK-NEXT: @inlinable public func withCheckedContinuation<T>(isolation: isolated (any _Concurrency.Actor)? = #isolation, function: Swift.String = #function, _ body: (_Concurrency.CheckedContinuation<T, Swift.Never>) -> Swift.Void) async -> T {
214+
// CHECK-NEXT: fatalError()
215+
// CHECK-NEXT: }
216+
// CHECK-NEXT: #endif
217+
// CHECK-NEXT: #endif
218+
@inlinable public func withCheckedContinuation<T>(
219+
isolation: isolated (any _Concurrency.Actor)? = #isolation,
220+
function: String = #function,
221+
_ body: (_Concurrency.CheckedContinuation<T, Swift.Never>) -> Swift.Void
222+
) async -> sending T {
223+
fatalError()
224+
}
225+
226+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults // Suppression Count: 26
227+
// CHECK-NEXT: public var publicGlobal: (sending test.NonSendableKlass) -> ()
228+
// CHECK-NEXT: #else
229+
// CHECK-NEXT: public var publicGlobal: (test.NonSendableKlass) -> ()
230+
// CHECK-NEXT: #endif
231+
public var publicGlobal: (sending NonSendableKlass) -> () = { x in fatalError() }
232+
233+
// CHECK-LABEL: #if compiler(>=5.3) && $SendingArgsAndResults // Suppression Count: 27
234+
// CHECK-NEXT: @usableFromInline
235+
// CHECK-NEXT: internal var usableFromInlineGlobal: (sending test.NonSendableKlass) -> ()
236+
// CHECK-NEXT: #else
237+
// CHECK-NEXT: @usableFromInline
238+
// CHECK-NEXT: internal var usableFromInlineGlobal: (test.NonSendableKlass) -> ()
239+
// CHECK-NEXT: #endif
240+
@usableFromInline
241+
internal var usableFromInlineGlobal: (sending NonSendableKlass) -> () = { x in fatalError() }

0 commit comments

Comments
 (0)