mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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
This commit is contained in:
@@ -535,6 +535,13 @@ class PrintAST : public ASTVisitor<PrintAST> {
|
||||
Decl *Current = nullptr;
|
||||
Type CurrentType;
|
||||
|
||||
void setCurrentType(Type NewCurrentType) {
|
||||
CurrentType = NewCurrentType;
|
||||
assert(CurrentType.isNull() ||
|
||||
!CurrentType->hasArchetype() &&
|
||||
"CurrentType should be an interface type");
|
||||
}
|
||||
|
||||
friend DeclVisitor<PrintAST>;
|
||||
|
||||
/// RAII object that increases the indentation level.
|
||||
@@ -913,8 +920,13 @@ private:
|
||||
public:
|
||||
PrintAST(ASTPrinter &Printer, const PrintOptions &Options)
|
||||
: Printer(Printer), Options(Options) {
|
||||
if (Options.TransformContext)
|
||||
CurrentType = Options.TransformContext->getBaseType();
|
||||
if (Options.TransformContext) {
|
||||
Type CurrentType = Options.TransformContext->getBaseType();
|
||||
if (CurrentType && CurrentType->hasArchetype()) {
|
||||
CurrentType = CurrentType->mapTypeOutOfContext();
|
||||
}
|
||||
setCurrentType(CurrentType);
|
||||
}
|
||||
}
|
||||
|
||||
using ASTVisitor::visit;
|
||||
@@ -941,11 +953,11 @@ public:
|
||||
if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
|
||||
auto Subs = CurrentType->getContextSubstitutionMap(
|
||||
Options.CurrentModule, NTD->getDeclContext());
|
||||
CurrentType = NTD->getDeclaredInterfaceType().subst(Subs);
|
||||
setCurrentType(NTD->getDeclaredInterfaceType().subst(Subs));
|
||||
}
|
||||
}
|
||||
|
||||
SWIFT_DEFER { CurrentType = OldType; };
|
||||
SWIFT_DEFER { setCurrentType(OldType); };
|
||||
|
||||
if (Synthesize) {
|
||||
Printer.setSynthesizedTarget(Options.TransformContext->getDecl());
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// RUN: %empty-directory(%t.mod)
|
||||
// RUN: %swift -emit-module -o %t.mod/test.swiftmodule %s -parse-as-library -emit-module-doc-path %t.mod/test.swiftdoc
|
||||
// RUN: %sourcekitd-test -req=doc-info -module test -- -I %t.mod | %FileCheck %s
|
||||
|
||||
public protocol Proto {}
|
||||
|
||||
public struct AttributesSlice1<T> : Proto {}
|
||||
|
||||
public struct ListFormatStyle<Style, Base: Proto> {
|
||||
public enum Width {
|
||||
case standard
|
||||
case short
|
||||
case narrow
|
||||
}
|
||||
}
|
||||
|
||||
public extension Proto {
|
||||
// The tricky part about this test case is that when synthesizing this
|
||||
// extension for `AttributesSlice1`, we replace `Self` by
|
||||
// `AttributesSlice1<T>` but `S` remains an generic parameter. We thus
|
||||
// have a type that contains both an archetype (namely `T` as the generic
|
||||
// paramter of `AttributedSlice1<T>`) and an unbound generic paramters.
|
||||
// This used to cause issues when printing the type.
|
||||
func formatted<S>(width: ListFormatStyle<S, Self>.Width) -> String {
|
||||
// CHECK: func formatted<S>(width width: ListFormatStyle<S, AttributesSlice1<T>>.Width) -> String
|
||||
fatalError()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1643,7 +1643,7 @@ func shouldPrintAnyAsKeyword(x x: Any)
|
||||
{
|
||||
key.kind: source.lang.swift.ref.generic_type_param,
|
||||
key.name: "Wrapped",
|
||||
key.usr: "s:4cake2S3VA2A2P6RzrlE7Wrappedxmfp",
|
||||
key.usr: "s:4cake2S3V7Wrappedxmfp",
|
||||
key.offset: 2041,
|
||||
key.length: 7
|
||||
},
|
||||
@@ -2744,7 +2744,7 @@ func shouldPrintAnyAsKeyword(x x: Any)
|
||||
key.original_usr: "s:4cake2P6PAAE4null7ElementQzSgvp",
|
||||
key.offset: 2031,
|
||||
key.length: 34,
|
||||
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>"
|
||||
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>"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -897,7 +897,7 @@ protocol Other1 {
|
||||
{
|
||||
key.kind: source.lang.swift.ref.generic_type_param,
|
||||
key.name: "T",
|
||||
key.usr: "s:16UnderscoredProto1DVAASQRzrlE1Txmfp",
|
||||
key.usr: "s:16UnderscoredProto1DV1Txmfp",
|
||||
key.offset: 1472,
|
||||
key.length: 1
|
||||
},
|
||||
@@ -945,7 +945,7 @@ protocol Other1 {
|
||||
{
|
||||
key.kind: source.lang.swift.ref.generic_type_param,
|
||||
key.name: "T",
|
||||
key.usr: "s:16UnderscoredProto1DVAASQRzrlE1Txmfp",
|
||||
key.usr: "s:16UnderscoredProto1DV1Txmfp",
|
||||
key.offset: 1585,
|
||||
key.length: 1
|
||||
},
|
||||
@@ -1570,7 +1570,7 @@ protocol Other1 {
|
||||
],
|
||||
key.offset: 1454,
|
||||
key.length: 135,
|
||||
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>",
|
||||
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>",
|
||||
key.extends: {
|
||||
key.kind: source.lang.swift.ref.struct,
|
||||
key.name: "D",
|
||||
@@ -1584,7 +1584,7 @@ protocol Other1 {
|
||||
key.original_usr: "s:16UnderscoredProto05_SomeB0PA2A6Other14ItemRpzrlE04fromcB24ExtensionSplitConditions05takese2IfD0yAF_tF",
|
||||
key.offset: 1505,
|
||||
key.length: 82,
|
||||
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>",
|
||||
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>",
|
||||
key.entities: [
|
||||
{
|
||||
key.kind: source.lang.swift.decl.var.local,
|
||||
|
||||
Reference in New Issue
Block a user