Skip to content

Commit 5c5b7b7

Browse files
committed
[IDE] Print opaque result type as protocol composition
rdar://problem/49354663 (cherry picked from commit 8055583)
1 parent cb7ad6a commit 5c5b7b7

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
@@ -263,9 +263,20 @@ struct PrintOptions {
263263
/// Whether to skip keywords with a prefix of underscore such as __consuming.
264264
bool SkipUnderscoredKeywords = false;
265265

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

270281
/// Whether to print decl attributes that are only used internally,
271282
/// such as _silgen_name, transparent, etc.
@@ -524,7 +535,8 @@ struct PrintOptions {
524535
result.PrintInSILBody = true;
525536
result.PreferTypeRepr = false;
526537
result.PrintIfConfig = false;
527-
result.PrintStableReferencesToOpaqueReturnTypes = true;
538+
result.OpaqueReturnTypePrinting =
539+
OpaqueReturnTypePrintingMode::StableReference;
528540
return result;
529541
}
530542

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;
@@ -3394,7 +3395,27 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
33943395
return;
33953396
}
33963397

3397-
if (T->hasSimpleTypeRepr()) {
3398+
bool isSimple = T->hasSimpleTypeRepr();
3399+
if (isSimple && T->is<OpaqueTypeArchetypeType>()) {
3400+
auto opaqueTy = T->castTo<OpaqueTypeArchetypeType>();
3401+
auto opaqueDecl = opaqueTy->getDecl();
3402+
if (!opaqueDecl->hasName()) {
3403+
switch (Options.OpaqueReturnTypePrinting) {
3404+
case PrintOptions::OpaqueReturnTypePrintingMode::StableReference:
3405+
case PrintOptions::OpaqueReturnTypePrintingMode::Description:
3406+
isSimple = true;
3407+
break;
3408+
case PrintOptions::OpaqueReturnTypePrintingMode::WithOpaqueKeyword:
3409+
isSimple = false;
3410+
break;
3411+
case PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword: {
3412+
isSimple = opaqueTy->getConformsTo().size() < 2;
3413+
}
3414+
}
3415+
}
3416+
}
3417+
3418+
if (isSimple) {
33983419
visit(T);
33993420
} else {
34003421
Printer << "(";
@@ -4157,7 +4178,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
41574178
}
41584179

41594180
void visitNestedArchetypeType(NestedArchetypeType *T) {
4160-
visit(T->getParent());
4181+
printWithParensIfNotSimple(T->getParent());
41614182
Printer << ".";
41624183
printArchetypeCommon(T);
41634184
}
@@ -4167,16 +4188,28 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
41674188
}
41684189

41694190
void visitOpaqueTypeArchetypeType(OpaqueTypeArchetypeType *T) {
4170-
// Print the type by referencing the opaque decl's synthetic name, if we
4171-
// were asked to.
4172-
OpaqueTypeDecl *decl = T->getDecl();
4173-
4174-
if (Options.PrintStableReferencesToOpaqueReturnTypes) {
4191+
switch (Options.OpaqueReturnTypePrinting) {
4192+
case PrintOptions::OpaqueReturnTypePrintingMode::WithOpaqueKeyword:
4193+
Printer << "some ";
4194+
LLVM_FALLTHROUGH;
4195+
case PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword: {
4196+
SmallVector<Type, 2> types;
4197+
for (auto proto : T->getConformsTo())
4198+
types.push_back(proto->TypeDecl::getDeclaredInterfaceType());
4199+
4200+
// Create and visit temporary ProtocolCompositionType.
4201+
auto composition =
4202+
ProtocolCompositionType::get(T->getASTContext(), types, false);
4203+
visit(composition);
4204+
return;
4205+
}
4206+
case PrintOptions::OpaqueReturnTypePrintingMode::StableReference: {
41754207
// Print the source of the opaque return type as a mangled name.
41764208
// We'll use type reconstruction while parsing the attribute to
41774209
// turn this back into a reference to the naming decl for the opaque
41784210
// type.
41794211
Printer << "@_opaqueReturnTypeOf(";
4212+
OpaqueTypeDecl *decl = T->getDecl();
41804213

41814214
Printer.printEscapedStringLiteral(
41824215
decl->getOpaqueReturnTypeIdentifier().str());
@@ -4187,7 +4220,9 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
41874220

41884221
Printer << u8") \U0001F9B8";
41894222
printGenericArgs(T->getSubstitutions().getReplacementTypes());
4190-
} else {
4223+
return;
4224+
}
4225+
case PrintOptions::OpaqueReturnTypePrintingMode::Description: {
41914226
// TODO(opaque): present opaque types with user-facing syntax. we should
41924227
// probably print this as `some P` and record the fact that we printed that
41934228
// so that diagnostics can add followup notes.
@@ -4201,6 +4236,8 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
42014236
[&] { Printer << ", "; });
42024237
Printer << '>';
42034238
}
4239+
return;
4240+
}
42044241
}
42054242
}
42064243

lib/IDE/CodeCompletion.cpp

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

18771877
void addTypeAnnotation(CodeCompletionResultBuilder &Builder, Type T) {
18781878
T = T->getReferenceStorageReferent();
1879-
if (T->isVoid())
1879+
if (T->isVoid()) {
18801880
Builder.addTypeAnnotation("Void");
1881-
else
1882-
Builder.addTypeAnnotation(T.getString());
1881+
} else {
1882+
PrintOptions PO;
1883+
PO.OpaqueReturnTypePrinting =
1884+
PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword;
1885+
Builder.addTypeAnnotation(T.getString(PO));
1886+
}
18831887
}
18841888

18851889
void addTypeAnnotationForImplicitlyUnwrappedOptional(
@@ -1897,6 +1901,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
18971901
T = T->getReferenceStorageReferent();
18981902
PrintOptions PO;
18991903
PO.PrintOptionalAsImplicitlyUnwrapped = true;
1904+
PO.OpaqueReturnTypePrinting =
1905+
PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword;
19001906
Builder.addTypeAnnotation(T.getString(PO) + suffix);
19011907
}
19021908

@@ -1933,6 +1939,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
19331939
// FIXME: Code completion should only deal with one or the other,
19341940
// and not both.
19351941
if (auto *archetypeType = t->getAs<ArchetypeType>()) {
1942+
// Don't erase opaque archetype.
1943+
if (isa<OpaqueTypeArchetypeType>(archetypeType))
1944+
return t;
1945+
19361946
auto protos = archetypeType->getConformsTo();
19371947
if (!protos.empty())
19381948
return buildProtocolComposition(protos);
@@ -2476,6 +2486,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
24762486
FD->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
24772487

24782488
PrintOptions PO;
2489+
PO.OpaqueReturnTypePrinting =
2490+
PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword;
24792491
PO.PrintOptionalAsImplicitlyUnwrapped = IsIUO;
24802492
ResultType.print(OS, PO);
24812493
}

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)