Skip to content

Commit bc07058

Browse files
committed
[sending] Look through the sending type error when printing the type of a function result using the type repr fallback path.
When we print types in the AST printer if for some reason we cannot find the appropriate type to print, we fall back and use a type repr instead. This behavior is a fallback case that is hit rarely (or we would have seen this behavior earlier). This behavior causes a problem due to the implementation of sending results using a sending type repr to communicate that the relevant Function has a sending result, but we actually do not use the sending type repr from that point on. So as a result, in this fallback case, we put in one too many sending on the result. Previously, it was pretty hard to test this codepath, so I added a small option that is available only in asserts builds that turns on the type repr behavior all the time. rdar://135594964
1 parent a58fac7 commit bc07058

File tree

4 files changed

+65
-1
lines changed

4 files changed

+65
-1
lines changed

include/swift/AST/PrintOptions.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,13 @@ struct PrintOptions {
345345
/// Whether to print the \c{/*not inherited*/} comment on factory initializers.
346346
bool PrintFactoryInitializerComment = true;
347347

348+
/// If set to true this is for a function result.
349+
///
350+
/// In practice, this causes us to look through "sending type reprs" when
351+
/// printing functions along the type repr backup path that is used if we are
352+
/// printing a function result type that is null.
353+
bool IsForFunctionResult = false;
354+
348355
/// How to print opaque return types.
349356
enum class OpaqueReturnTypePrintingMode {
350357
/// 'some P1 & P2'.

lib/AST/ASTPrinter.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -933,8 +933,17 @@ class PrintAST : public ASTVisitor<PrintAST> {
933933
// Print a TypeRepr if instructed to do so by options, or if the type
934934
// is null.
935935
if (willUseTypeReprPrinting(TL, CurrentType, options)) {
936-
if (auto repr = TL.getTypeRepr())
936+
if (auto repr = TL.getTypeRepr()) {
937+
if (Options.IsForFunctionResult) {
938+
// If we are printing a sending result... and we found that we have to
939+
// use type repr printing, look through sending type repr. Sending was
940+
// already applied in our caller.
941+
if (auto *sendingRepr = dyn_cast<SendingTypeRepr>(repr)) {
942+
repr = sendingRepr->getBase();
943+
}
944+
}
937945
repr->print(Printer, options);
946+
}
938947
return;
939948
}
940949

@@ -4037,6 +4046,23 @@ void PrintAST::visitAccessorDecl(AccessorDecl *decl) {
40374046
printBodyIfNecessary(decl);
40384047
}
40394048

4049+
/// Forces printing types with the `some` keyword, instead of the full stable
4050+
/// reference.
4051+
struct PrintForFunctionResultRAII {
4052+
PrintForFunctionResultRAII(PrintOptions &Options)
4053+
: Options(Options) {
4054+
SavedMode = Options.IsForFunctionResult;
4055+
Options.IsForFunctionResult = true;
4056+
}
4057+
~PrintForFunctionResultRAII() {
4058+
Options.IsForFunctionResult = SavedMode;
4059+
}
4060+
4061+
private:
4062+
PrintOptions &Options;
4063+
bool SavedMode;
4064+
};
4065+
40404066
void PrintAST::visitFuncDecl(FuncDecl *decl) {
40414067
ASTContext &Ctx = decl->getASTContext();
40424068

@@ -4139,6 +4165,8 @@ void PrintAST::visitFuncDecl(FuncDecl *decl) {
41394165
}
41404166

41414167
PrintWithOpaqueResultTypeKeywordRAII x(Options);
4168+
PrintForFunctionResultRAII assumingFunctionResult(Options);
4169+
41424170
printTypeLocForImplicitlyUnwrappedOptional(
41434171
ResultTyLoc, decl->isImplicitlyUnwrappedOptional());
41444172
Printer.printStructurePost(PrintStructureKind::FunctionReturnType);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
// CHECK: #if compiler(>=5.3) && $SendingArgsAndResults
3+
// CHECK-NEXT: public func test() -> sending NonSendableKlass
4+
// CHECK-NEXT: #else
5+
// CHECK-NEXT: public func test() -> NonSendableKlass
6+
// CHECK-NEXT: #endif
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend %s -typecheck -enable-library-evolution -parse-as-library -emit-module-interface-path - -module-name MyFile -swift-version 6 | %FileCheck -DFILE_PREFIX=MyFile %s
3+
// RUN: %target-swift-frontend %s -typecheck -enable-library-evolution -parse-as-library -emit-module-interface-path - -module-name MyFile -swift-version 6 -Xllvm --swift-ast-printer-force-printing-types-as-type-reprs | %FileCheck %S/Inputs/sending_interfacefile_printing_repr_filecheck
4+
5+
// The force printing type reprs option is only available in asserts builds.
6+
// REQUIRES: asserts
7+
8+
// This test validates that when we produce interface files we produce the
9+
// correct interface file for sending when printing normally or with type reprs
10+
// enabled.
11+
12+
public class NonSendableKlass {}
13+
14+
// The two possible outputs are MyFile.NonSendableKlass and NonSendableKlass.
15+
//
16+
// So we just check for an optional M
17+
// CHECK: #if compiler(>=5.3) && $SendingArgsAndResults
18+
// CHECK-NEXT: public func test() -> sending MyFile.NonSendableKlass
19+
// CHECK-NEXT: #else
20+
// CHECK-NEXT: public func test() -> MyFile.NonSendableKlass
21+
// CHECK-NEXT: #endif
22+
23+
public func test() -> sending NonSendableKlass { NonSendableKlass() }

0 commit comments

Comments
 (0)