Skip to content

Commit 902892a

Browse files
committed
AST: Print opaque result types correctly in swiftinterfaces.
Fixes a bug where references to the opaque types of other decls were printed with the `some Type` syntax, breaking the interface. Only the opaque type introduced by a declaration should be printed with the `some Type` syntax; other opaque types must always be printed as a stable addresses instead. Resolves rdar://134582913.
1 parent 931614c commit 902892a

File tree

3 files changed

+58
-38
lines changed

3 files changed

+58
-38
lines changed

include/swift/AST/PrintOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,10 @@ struct PrintOptions {
366366
OpaqueReturnTypePrintingMode OpaqueReturnTypePrinting =
367367
OpaqueReturnTypePrintingMode::WithOpaqueKeyword;
368368

369+
/// If non-null, opaque types that have this naming decl should be printed as
370+
/// `some P1` instead of as a stable reference.
371+
const ValueDecl *OpaqueReturnTypeNamingDecl = nullptr;
372+
369373
/// Whether to print decl attributes that are only used internally,
370374
/// such as _silgen_name, transparent, etc.
371375
bool PrintUserInaccessibleAttrs = true;

lib/AST/ASTPrinter.cpp

Lines changed: 28 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -194,24 +194,6 @@ bool PrintOptions::excludeAttr(const DeclAttribute *DA) const {
194194
return false;
195195
}
196196

197-
/// Forces printing types with the `some` keyword, instead of the full stable
198-
/// reference.
199-
struct PrintWithOpaqueResultTypeKeywordRAII {
200-
PrintWithOpaqueResultTypeKeywordRAII(PrintOptions &Options)
201-
: Options(Options) {
202-
SavedMode = Options.OpaqueReturnTypePrinting;
203-
Options.OpaqueReturnTypePrinting =
204-
PrintOptions::OpaqueReturnTypePrintingMode::WithOpaqueKeyword;
205-
}
206-
~PrintWithOpaqueResultTypeKeywordRAII() {
207-
Options.OpaqueReturnTypePrinting = SavedMode;
208-
}
209-
210-
private:
211-
PrintOptions &Options;
212-
PrintOptions::OpaqueReturnTypePrintingMode SavedMode;
213-
};
214-
215197
PrintOptions PrintOptions::printSwiftInterfaceFile(ModuleDecl *ModuleToPrint,
216198
bool preferTypeRepr,
217199
bool printFullConvention,
@@ -969,10 +951,19 @@ class PrintAST : public ASTVisitor<PrintAST> {
969951
printTypeLocWithOptions(TL, Options, printBeforeType);
970952
}
971953

972-
void printTypeLocForImplicitlyUnwrappedOptional(TypeLoc TL, bool IUO) {
973-
PrintOptions options = Options;
974-
options.PrintOptionalAsImplicitlyUnwrapped = IUO;
975-
printTypeLocWithOptions(TL, options);
954+
void printTypeLocForImplicitlyUnwrappedOptional(
955+
TypeLoc TL, bool IUO, const ValueDecl *opaqueTypeNamingDecl) {
956+
auto savedIOU = Options.PrintOptionalAsImplicitlyUnwrapped;
957+
Options.PrintOptionalAsImplicitlyUnwrapped = IUO;
958+
959+
auto savedOpaqueTypeNamingDecl = Options.OpaqueReturnTypeNamingDecl;
960+
if (opaqueTypeNamingDecl)
961+
Options.OpaqueReturnTypeNamingDecl = opaqueTypeNamingDecl;
962+
963+
printTypeLocWithOptions(TL, Options);
964+
965+
Options.PrintOptionalAsImplicitlyUnwrapped = savedIOU;
966+
Options.OpaqueReturnTypeNamingDecl = savedOpaqueTypeNamingDecl;
976967
}
977968

978969
void printContextIfNeeded(const Decl *decl) {
@@ -1376,18 +1367,17 @@ void PrintAST::printTypedPattern(const TypedPattern *TP) {
13761367
printPattern(TP->getSubPattern());
13771368
Printer << ": ";
13781369

1379-
PrintWithOpaqueResultTypeKeywordRAII x(Options);
1380-
1381-
// Make sure to check if the underlying var decl is an implicitly unwrapped
1382-
// optional.
1383-
bool isIUO = false;
1370+
VarDecl *varDecl = nullptr;
13841371
if (auto *named = dyn_cast<NamedPattern>(TP->getSubPattern()))
13851372
if (auto decl = named->getDecl())
1386-
isIUO = decl->isImplicitlyUnwrappedOptional();
1373+
varDecl = decl;
13871374

13881375
const auto TyLoc = TypeLoc(TP->getTypeRepr(),
13891376
TP->hasType() ? TP->getType() : Type());
1390-
printTypeLocForImplicitlyUnwrappedOptional(TyLoc, isIUO);
1377+
1378+
printTypeLocForImplicitlyUnwrappedOptional(
1379+
TyLoc, varDecl ? varDecl->isImplicitlyUnwrappedOptional() : false,
1380+
varDecl);
13911381
}
13921382

13931383
/// Determines if we are required to print the name of a property declaration,
@@ -3882,9 +3872,8 @@ void PrintAST::visitVarDecl(VarDecl *decl) {
38823872
}
38833873
Printer.printDeclResultTypePre(decl, tyLoc);
38843874

3885-
PrintWithOpaqueResultTypeKeywordRAII x(Options);
38863875
printTypeLocForImplicitlyUnwrappedOptional(
3887-
tyLoc, decl->isImplicitlyUnwrappedOptional());
3876+
tyLoc, decl->isImplicitlyUnwrappedOptional(), decl);
38883877
}
38893878

38903879
printAccessors(decl);
@@ -3966,7 +3955,7 @@ void PrintAST::printOneParameter(const ParamDecl *param,
39663955
}
39673956

39683957
printTypeLocForImplicitlyUnwrappedOptional(
3969-
TheTypeLoc, param->isImplicitlyUnwrappedOptional());
3958+
TheTypeLoc, param->isImplicitlyUnwrappedOptional(), nullptr);
39703959
}
39713960

39723961
if (param->isDefaultArgument() && Options.PrintDefaultArgumentValue) {
@@ -4256,8 +4245,6 @@ void PrintAST::visitFuncDecl(FuncDecl *decl) {
42564245
}
42574246
}
42584247

4259-
PrintWithOpaqueResultTypeKeywordRAII x(Options);
4260-
42614248
// Check if we would go down the type repr path... in such a case, see if
42624249
// we can find a type repr and if that type has a sending type repr. In
42634250
// such a case, look through the sending type repr since we handle it here
@@ -4284,7 +4271,7 @@ void PrintAST::visitFuncDecl(FuncDecl *decl) {
42844271
// If we printed using type repr printing, do not print again.
42854272
if (!usedTypeReprPrinting) {
42864273
printTypeLocForImplicitlyUnwrappedOptional(
4287-
ResultTyLoc, decl->isImplicitlyUnwrappedOptional());
4274+
ResultTyLoc, decl->isImplicitlyUnwrappedOptional(), decl);
42884275
}
42894276
Printer.printStructurePost(PrintStructureKind::FunctionReturnType);
42904277
}
@@ -4433,9 +4420,8 @@ void PrintAST::visitSubscriptDecl(SubscriptDecl *decl) {
44334420
Printer.printDeclResultTypePre(decl, elementTy);
44344421
Printer.callPrintStructurePre(PrintStructureKind::FunctionReturnType);
44354422

4436-
PrintWithOpaqueResultTypeKeywordRAII x(Options);
44374423
printTypeLocForImplicitlyUnwrappedOptional(
4438-
elementTy, decl->isImplicitlyUnwrappedOptional());
4424+
elementTy, decl->isImplicitlyUnwrappedOptional(), decl);
44394425
Printer.printStructurePost(PrintStructureKind::FunctionReturnType);
44404426
}
44414427

@@ -7241,7 +7227,11 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
72417227
auto genericSig = namingDecl->getInnermostDeclContext()
72427228
->getGenericSignatureOfContext();
72437229

7244-
switch (Options.OpaqueReturnTypePrinting) {
7230+
auto mode = Options.OpaqueReturnTypePrinting;
7231+
if (Options.OpaqueReturnTypeNamingDecl == T->getDecl()->getNamingDecl())
7232+
mode = PrintOptions::OpaqueReturnTypePrintingMode::WithOpaqueKeyword;
7233+
7234+
switch (mode) {
72457235
case PrintOptions::OpaqueReturnTypePrintingMode::WithOpaqueKeyword:
72467236
if (printNamedOpaque())
72477237
return;

test/ModuleInterface/opaque-result-types.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ public protocol AssocTypeInference {
5050
subscript() -> AssocSubscript { get }
5151
}
5252

53+
// CHECK-LABEL: public struct Bar<T> : OpaqueResultTypes.AssocTypeInference
5354
@available(SwiftStdlib 5.1, *)
5455
public struct Bar<T>: AssocTypeInference {
5556
public init() {}
@@ -259,3 +260,28 @@ public struct Zim: AssocTypeInference {
259260
return 123
260261
}
261262
}
263+
264+
public protocol PrimaryAssociatedTypeInference<Assoc> {
265+
associatedtype Assoc
266+
267+
func foo(_: Int) -> Assoc
268+
}
269+
270+
// CHECK-LABEL: public struct Baz : OpaqueResultTypes.PrimaryAssociatedTypeInference
271+
272+
public struct Baz: PrimaryAssociatedTypeInference {
273+
// CHECK-LABEL: public func foo(_: Swift.Int) -> some OpaqueResultTypes.Foo
274+
public func foo(_: Int) -> some Foo {
275+
return 123
276+
}
277+
278+
// CHECK-LABEL: public func callsFoo() -> @_opaqueReturnTypeOf("$s17OpaqueResultTypes3BazV3fooyQrSiF", 0) __
279+
public func callsFoo() -> Assoc {
280+
return foo(123)
281+
}
282+
283+
// CHECK-LABEL: public func identity() -> some OpaqueResultTypes.PrimaryAssociatedTypeInference<@_opaqueReturnTypeOf("$s17OpaqueResultTypes3BazV3fooyQrSiF", 0) __>
284+
public func identity() -> some PrimaryAssociatedTypeInference<Assoc> {
285+
return self
286+
}
287+
}

0 commit comments

Comments
 (0)