Skip to content

Commit 9ba892c

Browse files
committed
[ASTPrinter] Fix issue printing Self resolved to a generic type
When printing a type in type through `ASTPrinter::printTransformedTypeWithOptions`, we are removing any contextual types by mapping the type out of context. However, when substituting `Self` (or any other type member) with their concrete type from `CurrentType`, we might re-introduce contextual types. To fix this, make sure that `CurrentType` is always an interface type that has all contextual types removed. Fixes rdar://76021569
1 parent 5cf19e4 commit 9ba892c

File tree

4 files changed

+51
-10
lines changed

4 files changed

+51
-10
lines changed

lib/AST/ASTPrinter.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,13 @@ class PrintAST : public ASTVisitor<PrintAST> {
535535
Decl *Current = nullptr;
536536
Type CurrentType;
537537

538+
void setCurrentType(Type NewCurrentType) {
539+
CurrentType = NewCurrentType;
540+
assert(CurrentType.isNull() ||
541+
!CurrentType->hasArchetype() &&
542+
"CurrentType should be an interface type");
543+
}
544+
538545
friend DeclVisitor<PrintAST>;
539546

540547
/// RAII object that increases the indentation level.
@@ -913,8 +920,13 @@ class PrintAST : public ASTVisitor<PrintAST> {
913920
public:
914921
PrintAST(ASTPrinter &Printer, const PrintOptions &Options)
915922
: Printer(Printer), Options(Options) {
916-
if (Options.TransformContext)
917-
CurrentType = Options.TransformContext->getBaseType();
923+
if (Options.TransformContext) {
924+
Type CurrentType = Options.TransformContext->getBaseType();
925+
if (CurrentType && CurrentType->hasArchetype()) {
926+
CurrentType = CurrentType->mapTypeOutOfContext();
927+
}
928+
setCurrentType(CurrentType);
929+
}
918930
}
919931

920932
using ASTVisitor::visit;
@@ -941,11 +953,11 @@ class PrintAST : public ASTVisitor<PrintAST> {
941953
if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
942954
auto Subs = CurrentType->getContextSubstitutionMap(
943955
Options.CurrentModule, NTD->getDeclContext());
944-
CurrentType = NTD->getDeclaredInterfaceType().subst(Subs);
956+
setCurrentType(NTD->getDeclaredInterfaceType().subst(Subs));
945957
}
946958
}
947959

948-
SWIFT_DEFER { CurrentType = OldType; };
960+
SWIFT_DEFER { setCurrentType(OldType); };
949961

950962
if (Synthesize) {
951963
Printer.setSynthesizedTarget(Options.TransformContext->getDecl());
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %empty-directory(%t.mod)
2+
// RUN: %swift -emit-module -o %t.mod/test.swiftmodule %s -parse-as-library -emit-module-doc-path %t.mod/test.swiftdoc
3+
// RUN: %sourcekitd-test -req=doc-info -module test -- -I %t.mod | %FileCheck %s
4+
5+
public protocol Proto {}
6+
7+
public struct AttributesSlice1<T> : Proto {}
8+
9+
public struct ListFormatStyle<Style, Base: Proto> {
10+
public enum Width {
11+
case standard
12+
case short
13+
case narrow
14+
}
15+
}
16+
17+
public extension Proto {
18+
// The tricky part about this test case is that when synthesizing this
19+
// extension for `AttributesSlice1`, we replace `Self` by
20+
// `AttributesSlice1<T>` but `S` remains an generic parameter. We thus
21+
// have a type that contains both an archetype (namely `T` as the generic
22+
// paramter of `AttributedSlice1<T>`) and an unbound generic paramters.
23+
// This used to cause issues when printing the type.
24+
func formatted<S>(width: ListFormatStyle<S, Self>.Width) -> String {
25+
// CHECK: func formatted<S>(width width: ListFormatStyle<S, AttributesSlice1<T>>.Width) -> String
26+
fatalError()
27+
}
28+
}
29+

test/SourceKit/DocSupport/doc_swift_module.swift.response

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,7 +1643,7 @@ func shouldPrintAnyAsKeyword(x x: Any)
16431643
{
16441644
key.kind: source.lang.swift.ref.generic_type_param,
16451645
key.name: "Wrapped",
1646-
key.usr: "s:4cake2S3VA2A2P6RzrlE7Wrappedxmfp",
1646+
key.usr: "s:4cake2S3V7Wrappedxmfp",
16471647
key.offset: 2041,
16481648
key.length: 7
16491649
},
@@ -2744,7 +2744,7 @@ func shouldPrintAnyAsKeyword(x x: Any)
27442744
key.original_usr: "s:4cake2P6PAAE4null7ElementQzSgvp",
27452745
key.offset: 2031,
27462746
key.length: 34,
2747-
key.fully_annotated_decl: "<decl.var.instance><syntaxtype.keyword>var</syntaxtype.keyword> <decl.name>null</decl.name>: <decl.var.type><ref.generic_type_param usr=\"s:4cake2S3VA2A2P6RzrlE7Wrappedxmfp\">Wrapped</ref.generic_type_param>.<ref.associatedtype usr=\"s:4cake2P5P7ElementQa\">Element</ref.associatedtype>?</decl.var.type> { <syntaxtype.keyword>get</syntaxtype.keyword> }</decl.var.instance>"
2747+
key.fully_annotated_decl: "<decl.var.instance><syntaxtype.keyword>var</syntaxtype.keyword> <decl.name>null</decl.name>: <decl.var.type><ref.generic_type_param usr=\"s:4cake2S3V7Wrappedxmfp\">Wrapped</ref.generic_type_param>.<ref.associatedtype usr=\"s:4cake2P5P7ElementQa\">Element</ref.associatedtype>?</decl.var.type> { <syntaxtype.keyword>get</syntaxtype.keyword> }</decl.var.instance>"
27482748
}
27492749
]
27502750
},

test/SourceKit/DocSupport/doc_system_module_underscored.swift.response

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -897,7 +897,7 @@ protocol Other1 {
897897
{
898898
key.kind: source.lang.swift.ref.generic_type_param,
899899
key.name: "T",
900-
key.usr: "s:16UnderscoredProto1DVAASQRzrlE1Txmfp",
900+
key.usr: "s:16UnderscoredProto1DV1Txmfp",
901901
key.offset: 1472,
902902
key.length: 1
903903
},
@@ -945,7 +945,7 @@ protocol Other1 {
945945
{
946946
key.kind: source.lang.swift.ref.generic_type_param,
947947
key.name: "T",
948-
key.usr: "s:16UnderscoredProto1DVAASQRzrlE1Txmfp",
948+
key.usr: "s:16UnderscoredProto1DV1Txmfp",
949949
key.offset: 1585,
950950
key.length: 1
951951
},
@@ -1570,7 +1570,7 @@ protocol Other1 {
15701570
],
15711571
key.offset: 1454,
15721572
key.length: 135,
1573-
key.fully_annotated_decl: "<syntaxtype.keyword>extension</syntaxtype.keyword> <ref.struct usr=\"s:16UnderscoredProto1DV\">D</ref.struct> <syntaxtype.keyword>where</syntaxtype.keyword> <decl.generic_type_requirement><ref.generic_type_param usr=\"s:16UnderscoredProto1DVAASQRzrlE1Txmfp\">T</ref.generic_type_param> : <ref.protocol usr=\"s:16UnderscoredProto6Other1P\">Other1</ref.protocol></decl.generic_type_requirement>, <decl.generic_type_requirement><ref.generic_type_param usr=\"s:16UnderscoredProto1DVAASQRzrlE1Txmfp\">T</ref.generic_type_param> : <ref.protocol usr=\"s:SQ\">Equatable</ref.protocol></decl.generic_type_requirement>",
1573+
key.fully_annotated_decl: "<syntaxtype.keyword>extension</syntaxtype.keyword> <ref.struct usr=\"s:16UnderscoredProto1DV\">D</ref.struct> <syntaxtype.keyword>where</syntaxtype.keyword> <decl.generic_type_requirement><ref.generic_type_param usr=\"s:16UnderscoredProto1DV1Txmfp\">T</ref.generic_type_param> : <ref.protocol usr=\"s:16UnderscoredProto6Other1P\">Other1</ref.protocol></decl.generic_type_requirement>, <decl.generic_type_requirement><ref.generic_type_param usr=\"s:16UnderscoredProto1DVAASQRzrlE1Txmfp\">T</ref.generic_type_param> : <ref.protocol usr=\"s:SQ\">Equatable</ref.protocol></decl.generic_type_requirement>",
15741574
key.extends: {
15751575
key.kind: source.lang.swift.ref.struct,
15761576
key.name: "D",
@@ -1584,7 +1584,7 @@ protocol Other1 {
15841584
key.original_usr: "s:16UnderscoredProto05_SomeB0PA2A6Other14ItemRpzrlE04fromcB24ExtensionSplitConditions05takese2IfD0yAF_tF",
15851585
key.offset: 1505,
15861586
key.length: 82,
1587-
key.fully_annotated_decl: "<decl.function.method.instance><syntaxtype.keyword>func</syntaxtype.keyword> <decl.name>fromSomeProtoExtensionSplitConditions</decl.name>(<decl.var.parameter><decl.var.parameter.argument_label>takesItemIfOther1</decl.var.parameter.argument_label>: <decl.var.parameter.type><ref.generic_type_param usr=\"s:16UnderscoredProto1DVAASQRzrlE1Txmfp\">T</ref.generic_type_param></decl.var.parameter.type></decl.var.parameter>)</decl.function.method.instance>",
1587+
key.fully_annotated_decl: "<decl.function.method.instance><syntaxtype.keyword>func</syntaxtype.keyword> <decl.name>fromSomeProtoExtensionSplitConditions</decl.name>(<decl.var.parameter><decl.var.parameter.argument_label>takesItemIfOther1</decl.var.parameter.argument_label>: <decl.var.parameter.type><ref.generic_type_param usr=\"s:16UnderscoredProto1DV1Txmfp\">T</ref.generic_type_param></decl.var.parameter.type></decl.var.parameter>)</decl.function.method.instance>",
15881588
key.entities: [
15891589
{
15901590
key.kind: source.lang.swift.decl.var.local,

0 commit comments

Comments
 (0)