Skip to content

Commit 8055583

Browse files
committed
[IDE] Print opaque result type as protocol composition
rdar://problem/49354663
1 parent 7078862 commit 8055583

File tree

4 files changed

+81
-16
lines changed

4 files changed

+81
-16
lines changed

include/swift/AST/PrintOptions.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,20 @@ struct PrintOptions {
260260
/// Whether to skip keywords with a prefix of underscore such as __consuming.
261261
bool SkipUnderscoredKeywords = false;
262262

263-
/// Whether to print declarations with opaque return types with a stable,
264-
/// parsable internal syntax.
265-
bool PrintStableReferencesToOpaqueReturnTypes = false;
263+
/// How to print opaque return types.
264+
enum class OpaqueReturnTypePrintingMode {
265+
/// 'some P1 & P2'.
266+
WithOpaqueKeyword,
267+
/// 'P1 & P2'.
268+
WithoutOpaqueKeyword,
269+
/// Stable parsable internal syntax.
270+
StableReference,
271+
/// Description suitable for debugging.
272+
Description
273+
};
274+
275+
OpaqueReturnTypePrintingMode OpaqueReturnTypePrinting =
276+
OpaqueReturnTypePrintingMode::WithOpaqueKeyword;
266277

267278
/// Whether to print decl attributes that are only used internally,
268279
/// such as _silgen_name, transparent, etc.
@@ -521,7 +532,8 @@ struct PrintOptions {
521532
result.PrintInSILBody = true;
522533
result.PreferTypeRepr = false;
523534
result.PrintIfConfig = false;
524-
result.PrintStableReferencesToOpaqueReturnTypes = true;
535+
result.OpaqueReturnTypePrinting =
536+
OpaqueReturnTypePrintingMode::StableReference;
525537
return result;
526538
}
527539

lib/AST/ASTPrinter.cpp

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ PrintOptions PrintOptions::printParseableInterfaceFile() {
107107
result.FunctionDefinitions = true;
108108
result.CollapseSingleGetterProperty = false;
109109
result.VarInitializers = true;
110-
result.PrintStableReferencesToOpaqueReturnTypes = true;
110+
result.OpaqueReturnTypePrinting =
111+
OpaqueReturnTypePrintingMode::StableReference;
111112

112113
// We should print __consuming, __owned, etc for the module interface file.
113114
result.SkipUnderscoredKeywords = false;
@@ -3402,7 +3403,27 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
34023403
return;
34033404
}
34043405

3405-
if (T->hasSimpleTypeRepr()) {
3406+
bool isSimple = T->hasSimpleTypeRepr();
3407+
if (isSimple && T->is<OpaqueTypeArchetypeType>()) {
3408+
auto opaqueTy = T->castTo<OpaqueTypeArchetypeType>();
3409+
auto opaqueDecl = opaqueTy->getDecl();
3410+
if (!opaqueDecl->hasName()) {
3411+
switch (Options.OpaqueReturnTypePrinting) {
3412+
case PrintOptions::OpaqueReturnTypePrintingMode::StableReference:
3413+
case PrintOptions::OpaqueReturnTypePrintingMode::Description:
3414+
isSimple = true;
3415+
break;
3416+
case PrintOptions::OpaqueReturnTypePrintingMode::WithOpaqueKeyword:
3417+
isSimple = false;
3418+
break;
3419+
case PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword: {
3420+
isSimple = opaqueTy->getConformsTo().size() < 2;
3421+
}
3422+
}
3423+
}
3424+
}
3425+
3426+
if (isSimple) {
34063427
visit(T);
34073428
} else {
34083429
Printer << "(";
@@ -4165,7 +4186,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
41654186
}
41664187

41674188
void visitNestedArchetypeType(NestedArchetypeType *T) {
4168-
visit(T->getParent());
4189+
printWithParensIfNotSimple(T->getParent());
41694190
Printer << ".";
41704191
printArchetypeCommon(T);
41714192
}
@@ -4175,16 +4196,28 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
41754196
}
41764197

41774198
void visitOpaqueTypeArchetypeType(OpaqueTypeArchetypeType *T) {
4178-
// Print the type by referencing the opaque decl's synthetic name, if we
4179-
// were asked to.
4180-
OpaqueTypeDecl *decl = T->getDecl();
4181-
4182-
if (Options.PrintStableReferencesToOpaqueReturnTypes) {
4199+
switch (Options.OpaqueReturnTypePrinting) {
4200+
case PrintOptions::OpaqueReturnTypePrintingMode::WithOpaqueKeyword:
4201+
Printer << "some ";
4202+
LLVM_FALLTHROUGH;
4203+
case PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword: {
4204+
SmallVector<Type, 2> types;
4205+
for (auto proto : T->getConformsTo())
4206+
types.push_back(proto->TypeDecl::getDeclaredInterfaceType());
4207+
4208+
// Create and visit temporary ProtocolCompositionType.
4209+
auto composition =
4210+
ProtocolCompositionType::get(T->getASTContext(), types, false);
4211+
visit(composition);
4212+
return;
4213+
}
4214+
case PrintOptions::OpaqueReturnTypePrintingMode::StableReference: {
41834215
// Print the source of the opaque return type as a mangled name.
41844216
// We'll use type reconstruction while parsing the attribute to
41854217
// turn this back into a reference to the naming decl for the opaque
41864218
// type.
41874219
Printer << "@_opaqueReturnTypeOf(";
4220+
OpaqueTypeDecl *decl = T->getDecl();
41884221

41894222
Printer.printEscapedStringLiteral(
41904223
decl->getOpaqueReturnTypeIdentifier().str());
@@ -4195,7 +4228,9 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
41954228

41964229
Printer << u8") \U0001F9B8";
41974230
printGenericArgs(T->getSubstitutions().getReplacementTypes());
4198-
} else {
4231+
return;
4232+
}
4233+
case PrintOptions::OpaqueReturnTypePrintingMode::Description: {
41994234
// TODO(opaque): present opaque types with user-facing syntax. we should
42004235
// probably print this as `some P` and record the fact that we printed that
42014236
// so that diagnostics can add followup notes.
@@ -4209,6 +4244,8 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
42094244
[&] { Printer << ", "; });
42104245
Printer << '>';
42114246
}
4247+
return;
4248+
}
42124249
}
42134250
}
42144251

lib/IDE/CodeCompletion.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1874,10 +1874,14 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
18741874

18751875
void addTypeAnnotation(CodeCompletionResultBuilder &Builder, Type T) {
18761876
T = T->getReferenceStorageReferent();
1877-
if (T->isVoid())
1877+
if (T->isVoid()) {
18781878
Builder.addTypeAnnotation("Void");
1879-
else
1880-
Builder.addTypeAnnotation(T.getString());
1879+
} else {
1880+
PrintOptions PO;
1881+
PO.OpaqueReturnTypePrinting =
1882+
PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword;
1883+
Builder.addTypeAnnotation(T.getString(PO));
1884+
}
18811885
}
18821886

18831887
void addTypeAnnotationForImplicitlyUnwrappedOptional(
@@ -1895,6 +1899,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
18951899
T = T->getReferenceStorageReferent();
18961900
PrintOptions PO;
18971901
PO.PrintOptionalAsImplicitlyUnwrapped = true;
1902+
PO.OpaqueReturnTypePrinting =
1903+
PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword;
18981904
Builder.addTypeAnnotation(T.getString(PO) + suffix);
18991905
}
19001906

@@ -1931,6 +1937,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
19311937
// FIXME: Code completion should only deal with one or the other,
19321938
// and not both.
19331939
if (auto *archetypeType = t->getAs<ArchetypeType>()) {
1940+
// Don't erase opaque archetype.
1941+
if (isa<OpaqueTypeArchetypeType>(archetypeType))
1942+
return t;
1943+
19341944
auto protos = archetypeType->getConformsTo();
19351945
if (!protos.empty())
19361946
return buildProtocolComposition(protos);
@@ -2474,6 +2484,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
24742484
FD->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
24752485

24762486
PrintOptions PO;
2487+
PO.OpaqueReturnTypePrinting =
2488+
PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword;
24772489
PO.PrintOptionalAsImplicitlyUnwrapped = IsIUO;
24782490
ResultType.print(OS, PO);
24792491
}

lib/IDE/CodeCompletionResultBuilder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,8 @@ class CodeCompletionResultBuilder {
373373
PrintOptions PO;
374374
PO.SkipAttributes = true;
375375
PO.PrintOptionalAsImplicitlyUnwrapped = IsIUO;
376+
PO.OpaqueReturnTypePrinting =
377+
PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword;
376378
std::string TypeName = Ty->getString(PO);
377379
addChunkWithText(CodeCompletionString::Chunk::ChunkKind::CallParameterType,
378380
TypeName);
@@ -385,6 +387,8 @@ class CodeCompletionResultBuilder {
385387
PrintOptions PO;
386388
PO.PrintFunctionRepresentationAttrs = false;
387389
PO.SkipAttributes = true;
390+
PO.OpaqueReturnTypePrinting =
391+
PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword;
388392
addChunkWithText(
389393
CodeCompletionString::Chunk::ChunkKind::CallParameterClosureType,
390394
AFT->getString(PO));

0 commit comments

Comments
 (0)