Skip to content

Commit 214f480

Browse files
author
willtunnels
authored
Merge pull request swiftlang#38041 from willtunnels/general-opaque-return-types
[Frontend][Parse] Parse new named opaque return type syntax
2 parents 6d7c4e5 + c5e307d commit 214f480

18 files changed

+280
-118
lines changed

include/swift/AST/GenericParamList.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,6 @@ class RequirementRepr {
8181
: SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false),
8282
FirstType(FirstType), SecondLayout(SecondLayout) { }
8383

84-
void printImpl(ASTPrinter &OS) const;
85-
8684
public:
8785
/// Construct a new type-constraint requirement.
8886
///
@@ -339,14 +337,15 @@ class GenericParamList final :
339337
/// to the given DeclContext.
340338
GenericParamList *clone(DeclContext *dc) const;
341339

342-
void print(raw_ostream &OS) const;
343-
SWIFT_DEBUG_DUMP;
344-
345340
bool walk(ASTWalker &walker);
346341

347342
/// Finds a generic parameter declaration by name. This should only
348343
/// be used from the SIL parser.
349344
GenericTypeParamDecl *lookUpGenericParam(Identifier name) const;
345+
346+
SWIFT_DEBUG_DUMP;
347+
void print(raw_ostream &OS, const PrintOptions &PO = PrintOptions()) const;
348+
void print(ASTPrinter &Printer, const PrintOptions &PO) const;
350349
};
351350

352351
/// A trailing where clause.

include/swift/AST/TypeRepr.h

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,13 +1061,13 @@ class SILBoxTypeReprField {
10611061
TypeRepr *getFieldType() const { return FieldTypeAndMutable.getPointer(); }
10621062
bool isMutable() const { return FieldTypeAndMutable.getInt(); }
10631063
};
1064-
1065-
/// TypeRepr for opaque return types.
1064+
1065+
/// A TypeRepr for anonymous opaque return types.
10661066
///
1067-
/// This can occur in the return position of a function declaration, or the
1068-
/// top-level type of a property, to specify that the concrete return type
1069-
/// should be abstracted from callers, given a set of generic constraints that
1070-
/// the concrete return type satisfies:
1067+
/// This can occur in the return type of a function declaration, or the type of
1068+
/// a property, to specify that the concrete return type should be abstracted
1069+
/// from callers, given a set of generic constraints that the concrete return
1070+
/// type satisfies:
10711071
///
10721072
/// func foo() -> some Collection { return [1,2,3] }
10731073
/// var bar: some SignedInteger = 1
@@ -1101,6 +1101,41 @@ class OpaqueReturnTypeRepr : public TypeRepr {
11011101
friend class TypeRepr;
11021102
};
11031103

1104+
/// A TypeRepr for a type with a generic parameter list of named opaque return
1105+
/// types.
1106+
///
1107+
/// This can occur only as the return type of a function declaration, to specify
1108+
/// subtypes which should be abstracted from callers, given a set of generic
1109+
/// constraints that the concrete types satisfy:
1110+
///
1111+
/// func foo() -> <T: Collection> T { return [1] }
1112+
class NamedOpaqueReturnTypeRepr : public TypeRepr {
1113+
TypeRepr *Base;
1114+
GenericParamList *GenericParams;
1115+
1116+
public:
1117+
NamedOpaqueReturnTypeRepr(TypeRepr *Base, GenericParamList *GenericParams)
1118+
: TypeRepr(TypeReprKind::NamedOpaqueReturn), Base(Base),
1119+
GenericParams(GenericParams) {
1120+
assert(Base && GenericParams);
1121+
}
1122+
1123+
TypeRepr *getBase() const { return Base; }
1124+
GenericParamList *getGenericParams() const { return GenericParams; }
1125+
1126+
static bool classof(const TypeRepr *T) {
1127+
return T->getKind() == TypeReprKind::NamedOpaqueReturn;
1128+
}
1129+
static bool classof(const NamedOpaqueReturnTypeRepr *T) { return true; }
1130+
1131+
private:
1132+
SourceLoc getStartLocImpl() const;
1133+
SourceLoc getEndLocImpl() const;
1134+
SourceLoc getLocImpl() const;
1135+
void printImpl(ASTPrinter &Printer, const PrintOptions &Opts) const;
1136+
friend class TypeRepr;
1137+
};
1138+
11041139
/// TypeRepr for a user-specified placeholder (essentially, a user-facing
11051140
/// representation of an anonymous type variable.
11061141
///
@@ -1227,6 +1262,7 @@ inline bool TypeRepr::isSimple() const {
12271262
case TypeReprKind::InOut:
12281263
case TypeReprKind::Composition:
12291264
case TypeReprKind::OpaqueReturn:
1265+
case TypeReprKind::NamedOpaqueReturn:
12301266
return false;
12311267
case TypeReprKind::SimpleIdent:
12321268
case TypeReprKind::GenericIdent:

include/swift/AST/TypeReprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ TYPEREPR(Composition, TypeRepr)
5454
TYPEREPR(Metatype, TypeRepr)
5555
TYPEREPR(Protocol, TypeRepr)
5656
TYPEREPR(OpaqueReturn, TypeRepr)
57+
TYPEREPR(NamedOpaqueReturn, TypeRepr)
5758
TYPEREPR(Placeholder, TypeRepr)
5859
ABSTRACT_TYPEREPR(Specifier, TypeRepr)
5960
TYPEREPR(InOut, SpecifierTypeRepr)

include/swift/Basic/LangOptions.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,11 @@ namespace swift {
286286
/// Enable experimental concurrency model.
287287
bool EnableExperimentalConcurrency = false;
288288

289+
/// Enable experimental support for additional opaque return type features,
290+
/// i.e. named opaque return types (with 'where' clause support), and opaque
291+
/// types in nested position within the function return type.
292+
bool EnableExperimentalOpaqueReturnTypes = false;
293+
289294
/// Enable experimental flow-sensitive concurrent captures.
290295
bool EnableExperimentalFlowSensitiveConcurrentCaptures = false;
291296

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,10 @@ def enable_experimental_static_assert :
437437
Flag<["-"], "enable-experimental-static-assert">,
438438
HelpText<"Enable experimental #assert">;
439439

440+
def enable_experimental_opaque_return_types :
441+
Flag<["-"], "enable-experimental-opaque-return-types">,
442+
HelpText<"Enable experimental extensions to opaque return type support">;
443+
440444
def enable_deserialization_recovery :
441445
Flag<["-"], "enable-deserialization-recovery">,
442446
HelpText<"Attempt to recover from missing xrefs (etc) in swiftmodules">;

include/swift/Parse/Parser.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,6 +1232,13 @@ class Parser {
12321232
Diag<> MessageID,
12331233
ParseTypeReason reason = ParseTypeReason::Unspecified);
12341234

1235+
/// Parse a type optionally prefixed by a list of named opaque parameters. If
1236+
/// no params present, return 'type'. Otherwise, return 'type-named-opaque'.
1237+
///
1238+
/// type-named-opaque:
1239+
/// generic-params type
1240+
ParserResult<TypeRepr> parseTypeWithOpaqueParams(Diag<> MessageID);
1241+
12351242
ParserResult<TypeRepr>
12361243
parseTypeSimpleOrComposition(Diag<> MessageID, ParseTypeReason reason);
12371244

lib/AST/ASTDumper.cpp

Lines changed: 6 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#include "swift/AST/ForeignAsyncConvention.h"
2222
#include "swift/AST/ForeignErrorConvention.h"
2323
#include "swift/AST/GenericEnvironment.h"
24-
#include "swift/AST/GenericParamList.h"
2524
#include "swift/AST/Initializer.h"
2625
#include "swift/AST/ParameterList.h"
2726
#include "swift/AST/ProtocolConformance.h"
@@ -114,107 +113,6 @@ namespace {
114113
};
115114
} // end anonymous namespace
116115

117-
//===----------------------------------------------------------------------===//
118-
// Generic param list printing.
119-
//===----------------------------------------------------------------------===//
120-
121-
void RequirementRepr::dump() const {
122-
print(llvm::errs());
123-
llvm::errs() << "\n";
124-
}
125-
126-
void RequirementRepr::printImpl(ASTPrinter &out) const {
127-
auto printLayoutConstraint =
128-
[&](const LayoutConstraintLoc &LayoutConstraintLoc) {
129-
LayoutConstraintLoc.getLayoutConstraint()->print(out, PrintOptions());
130-
};
131-
132-
switch (getKind()) {
133-
case RequirementReprKind::LayoutConstraint:
134-
if (auto *repr = getSubjectRepr()) {
135-
repr->print(out, PrintOptions());
136-
}
137-
out << " : ";
138-
printLayoutConstraint(getLayoutConstraintLoc());
139-
break;
140-
141-
case RequirementReprKind::TypeConstraint:
142-
if (auto *repr = getSubjectRepr()) {
143-
repr->print(out, PrintOptions());
144-
}
145-
out << " : ";
146-
if (auto *repr = getConstraintRepr()) {
147-
repr->print(out, PrintOptions());
148-
}
149-
break;
150-
151-
case RequirementReprKind::SameType:
152-
if (auto *repr = getFirstTypeRepr()) {
153-
repr->print(out, PrintOptions());
154-
}
155-
out << " == ";
156-
if (auto *repr = getSecondTypeRepr()) {
157-
repr->print(out, PrintOptions());
158-
}
159-
break;
160-
}
161-
}
162-
163-
void RequirementRepr::print(raw_ostream &out) const {
164-
StreamPrinter printer(out);
165-
printImpl(printer);
166-
}
167-
void RequirementRepr::print(ASTPrinter &out) const {
168-
printImpl(out);
169-
}
170-
171-
static void printTrailingRequirements(ASTPrinter &Printer,
172-
ArrayRef<RequirementRepr> Reqs,
173-
bool printWhereKeyword) {
174-
if (Reqs.empty()) return;
175-
176-
if (printWhereKeyword)
177-
Printer << " where ";
178-
interleave(
179-
Reqs,
180-
[&](const RequirementRepr &req) {
181-
Printer.callPrintStructurePre(PrintStructureKind::GenericRequirement);
182-
req.print(Printer);
183-
Printer.printStructurePost(PrintStructureKind::GenericRequirement);
184-
},
185-
[&] { Printer << ", "; });
186-
}
187-
188-
void GenericParamList::print(llvm::raw_ostream &OS) const {
189-
OS << '<';
190-
interleave(*this,
191-
[&](const GenericTypeParamDecl *P) {
192-
OS << P->getName();
193-
if (!P->getInherited().empty()) {
194-
OS << " : ";
195-
P->getInherited()[0].getType().print(OS);
196-
}
197-
},
198-
[&] { OS << ", "; });
199-
200-
StreamPrinter Printer(OS);
201-
printTrailingRequirements(Printer, getRequirements(),
202-
/*printWhereKeyword*/true);
203-
OS << '>';
204-
}
205-
206-
void GenericParamList::dump() const {
207-
print(llvm::errs());
208-
llvm::errs() << '\n';
209-
}
210-
211-
void TrailingWhereClause::print(llvm::raw_ostream &OS,
212-
bool printWhereKeyword) const {
213-
StreamPrinter Printer(OS);
214-
printTrailingRequirements(Printer, getRequirements(),
215-
printWhereKeyword);
216-
}
217-
218116
static void printGenericParameters(raw_ostream &OS, GenericParamList *Params) {
219117
if (!Params)
220118
return;
@@ -3139,6 +3037,12 @@ class PrintTypeRepr : public TypeReprVisitor<PrintTypeRepr> {
31393037
PrintWithColorRAII(OS, ParenthesisColor) << ')';
31403038
}
31413039

3040+
void visitNamedOpaqueReturnTypeRepr(NamedOpaqueReturnTypeRepr *T) {
3041+
printCommon("type_named_opaque_return") << '\n';
3042+
printRec(T->getBase());
3043+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
3044+
}
3045+
31423046
void visitPlaceholderTypeRepr(PlaceholderTypeRepr *T) {
31433047
printCommon("type_placeholder");
31443048
PrintWithColorRAII(OS, ParenthesisColor) << ')';

lib/AST/ASTPrinter.cpp

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "swift/AST/ExistentialLayout.h"
2727
#include "swift/AST/Expr.h"
2828
#include "swift/AST/FileUnit.h"
29+
#include "swift/AST/GenericParamList.h"
2930
#include "swift/AST/GenericSignature.h"
3031
#include "swift/AST/Module.h"
3132
#include "swift/AST/NameLookup.h"
@@ -5855,3 +5856,113 @@ swift::getInheritedForPrinting(const Decl *decl, const PrintOptions &options,
58555856
}
58565857
}
58575858
}
5859+
5860+
//===----------------------------------------------------------------------===//
5861+
// Generic param list printing.
5862+
//===----------------------------------------------------------------------===//
5863+
5864+
void RequirementRepr::dump() const {
5865+
print(llvm::errs());
5866+
llvm::errs() << "\n";
5867+
}
5868+
5869+
void RequirementRepr::print(raw_ostream &out) const {
5870+
StreamPrinter printer(out);
5871+
print(printer);
5872+
}
5873+
5874+
void RequirementRepr::print(ASTPrinter &out) const {
5875+
auto printLayoutConstraint =
5876+
[&](const LayoutConstraintLoc &LayoutConstraintLoc) {
5877+
LayoutConstraintLoc.getLayoutConstraint()->print(out, PrintOptions());
5878+
};
5879+
5880+
switch (getKind()) {
5881+
case RequirementReprKind::LayoutConstraint:
5882+
if (auto *repr = getSubjectRepr()) {
5883+
repr->print(out, PrintOptions());
5884+
}
5885+
out << " : ";
5886+
printLayoutConstraint(getLayoutConstraintLoc());
5887+
break;
5888+
5889+
case RequirementReprKind::TypeConstraint:
5890+
if (auto *repr = getSubjectRepr()) {
5891+
repr->print(out, PrintOptions());
5892+
}
5893+
out << " : ";
5894+
if (auto *repr = getConstraintRepr()) {
5895+
repr->print(out, PrintOptions());
5896+
}
5897+
break;
5898+
5899+
case RequirementReprKind::SameType:
5900+
if (auto *repr = getFirstTypeRepr()) {
5901+
repr->print(out, PrintOptions());
5902+
}
5903+
out << " == ";
5904+
if (auto *repr = getSecondTypeRepr()) {
5905+
repr->print(out, PrintOptions());
5906+
}
5907+
break;
5908+
}
5909+
}
5910+
5911+
void GenericParamList::dump() const {
5912+
print(llvm::errs());
5913+
llvm::errs() << '\n';
5914+
}
5915+
5916+
void GenericParamList::print(raw_ostream &out, const PrintOptions &PO) const {
5917+
StreamPrinter printer(out);
5918+
print(printer, PO);
5919+
}
5920+
5921+
static void printTrailingRequirements(ASTPrinter &Printer,
5922+
ArrayRef<RequirementRepr> Reqs,
5923+
bool printWhereKeyword) {
5924+
if (Reqs.empty())
5925+
return;
5926+
5927+
if (printWhereKeyword)
5928+
Printer << " where ";
5929+
interleave(
5930+
Reqs,
5931+
[&](const RequirementRepr &req) {
5932+
Printer.callPrintStructurePre(PrintStructureKind::GenericRequirement);
5933+
req.print(Printer);
5934+
Printer.printStructurePost(PrintStructureKind::GenericRequirement);
5935+
},
5936+
[&] { Printer << ", "; });
5937+
}
5938+
5939+
void GenericParamList::print(ASTPrinter &Printer,
5940+
const PrintOptions &PO) const {
5941+
Printer << '<';
5942+
interleave(
5943+
*this,
5944+
[&](const GenericTypeParamDecl *P) {
5945+
Printer << P->getName();
5946+
if (!P->getInherited().empty()) {
5947+
Printer << " : ";
5948+
5949+
auto loc = P->getInherited()[0];
5950+
if (willUseTypeReprPrinting(loc, nullptr, PO)) {
5951+
loc.getTypeRepr()->print(Printer, PO);
5952+
} else {
5953+
loc.getType()->print(Printer, PO);
5954+
}
5955+
}
5956+
},
5957+
[&] { Printer << ", "; });
5958+
5959+
printTrailingRequirements(Printer, getRequirements(),
5960+
/*printWhereKeyword*/ true);
5961+
Printer << '>';
5962+
}
5963+
5964+
void TrailingWhereClause::print(llvm::raw_ostream &OS,
5965+
bool printWhereKeyword) const {
5966+
StreamPrinter Printer(OS);
5967+
printTrailingRequirements(Printer, getRequirements(), printWhereKeyword);
5968+
}

0 commit comments

Comments
 (0)