Skip to content

[Frontend][Parse] Parse new named opaque return type syntax #38041

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions include/swift/AST/GenericParamList.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,6 @@ class RequirementRepr {
: SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false),
FirstType(FirstType), SecondLayout(SecondLayout) { }

void printImpl(ASTPrinter &OS) const;

public:
/// Construct a new type-constraint requirement.
///
Expand Down Expand Up @@ -339,14 +337,15 @@ class GenericParamList final :
/// to the given DeclContext.
GenericParamList *clone(DeclContext *dc) const;

void print(raw_ostream &OS) const;
SWIFT_DEBUG_DUMP;

bool walk(ASTWalker &walker);

/// Finds a generic parameter declaration by name. This should only
/// be used from the SIL parser.
GenericTypeParamDecl *lookUpGenericParam(Identifier name) const;

SWIFT_DEBUG_DUMP;
void print(raw_ostream &OS, const PrintOptions &PO = PrintOptions()) const;
void print(ASTPrinter &Printer, const PrintOptions &PO) const;
};

/// A trailing where clause.
Expand Down
48 changes: 42 additions & 6 deletions include/swift/AST/TypeRepr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1061,13 +1061,13 @@ class SILBoxTypeReprField {
TypeRepr *getFieldType() const { return FieldTypeAndMutable.getPointer(); }
bool isMutable() const { return FieldTypeAndMutable.getInt(); }
};
/// TypeRepr for opaque return types.

/// A TypeRepr for anonymous opaque return types.
///
/// This can occur in the return position of a function declaration, or the
/// top-level type of a property, to specify that the concrete return type
/// should be abstracted from callers, given a set of generic constraints that
/// the concrete return type satisfies:
/// This can occur in the return type of a function declaration, or the type of
/// a property, to specify that the concrete return type should be abstracted
/// from callers, given a set of generic constraints that the concrete return
/// type satisfies:
///
/// func foo() -> some Collection { return [1,2,3] }
/// var bar: some SignedInteger = 1
Expand Down Expand Up @@ -1101,6 +1101,41 @@ class OpaqueReturnTypeRepr : public TypeRepr {
friend class TypeRepr;
};

/// A TypeRepr for a type with a generic parameter list of named opaque return
/// types.
///
/// This can occur only as the return type of a function declaration, to specify
/// subtypes which should be abstracted from callers, given a set of generic
/// constraints that the concrete types satisfy:
///
/// func foo() -> <T: Collection> T { return [1] }
class NamedOpaqueReturnTypeRepr : public TypeRepr {
TypeRepr *Base;
GenericParamList *GenericParams;

public:
NamedOpaqueReturnTypeRepr(TypeRepr *Base, GenericParamList *GenericParams)
: TypeRepr(TypeReprKind::NamedOpaqueReturn), Base(Base),
GenericParams(GenericParams) {
assert(Base && GenericParams);
}

TypeRepr *getBase() const { return Base; }
GenericParamList *getGenericParams() const { return GenericParams; }

static bool classof(const TypeRepr *T) {
return T->getKind() == TypeReprKind::NamedOpaqueReturn;
}
static bool classof(const NamedOpaqueReturnTypeRepr *T) { return true; }

private:
SourceLoc getStartLocImpl() const;
SourceLoc getEndLocImpl() const;
SourceLoc getLocImpl() const;
void printImpl(ASTPrinter &Printer, const PrintOptions &Opts) const;
friend class TypeRepr;
};

/// TypeRepr for a user-specified placeholder (essentially, a user-facing
/// representation of an anonymous type variable.
///
Expand Down Expand Up @@ -1227,6 +1262,7 @@ inline bool TypeRepr::isSimple() const {
case TypeReprKind::InOut:
case TypeReprKind::Composition:
case TypeReprKind::OpaqueReturn:
case TypeReprKind::NamedOpaqueReturn:
return false;
case TypeReprKind::SimpleIdent:
case TypeReprKind::GenericIdent:
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/TypeReprNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ TYPEREPR(Composition, TypeRepr)
TYPEREPR(Metatype, TypeRepr)
TYPEREPR(Protocol, TypeRepr)
TYPEREPR(OpaqueReturn, TypeRepr)
TYPEREPR(NamedOpaqueReturn, TypeRepr)
TYPEREPR(Placeholder, TypeRepr)
ABSTRACT_TYPEREPR(Specifier, TypeRepr)
TYPEREPR(InOut, SpecifierTypeRepr)
Expand Down
5 changes: 5 additions & 0 deletions include/swift/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,11 @@ namespace swift {
/// Enable experimental concurrency model.
bool EnableExperimentalConcurrency = false;

/// Enable experimental support for additional opaque return type features,
/// i.e. named opaque return types (with 'where' clause support), and opaque
/// types in nested position within the function return type.
bool EnableExperimentalOpaqueReturnTypes = false;

/// Enable experimental flow-sensitive concurrent captures.
bool EnableExperimentalFlowSensitiveConcurrentCaptures = false;

Expand Down
4 changes: 4 additions & 0 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,10 @@ def enable_experimental_static_assert :
Flag<["-"], "enable-experimental-static-assert">,
HelpText<"Enable experimental #assert">;

def enable_experimental_opaque_return_types :
Flag<["-"], "enable-experimental-opaque-return-types">,
HelpText<"Enable experimental extensions to opaque return type support">;

def enable_deserialization_recovery :
Flag<["-"], "enable-deserialization-recovery">,
HelpText<"Attempt to recover from missing xrefs (etc) in swiftmodules">;
Expand Down
7 changes: 7 additions & 0 deletions include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1223,6 +1223,13 @@ class Parser {
ParserResult<TypeRepr> parseType(Diag<> MessageID,
bool IsSILFuncDecl = false);

/// Parse a type optionally prefixed by a list of named opaque parameters. If
/// no params present, return 'type'. Otherwise, return 'type-named-opaque'.
///
/// type-named-opaque:
/// generic-params type
ParserResult<TypeRepr> parseTypeWithOpaqueParams(Diag<> MessageID);

ParserResult<TypeRepr>
parseTypeSimpleOrComposition(Diag<> MessageID);

Expand Down
108 changes: 6 additions & 102 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#include "swift/AST/ForeignAsyncConvention.h"
#include "swift/AST/ForeignErrorConvention.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/GenericParamList.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/ProtocolConformance.h"
Expand Down Expand Up @@ -114,107 +113,6 @@ namespace {
};
} // end anonymous namespace

//===----------------------------------------------------------------------===//
// Generic param list printing.
//===----------------------------------------------------------------------===//

void RequirementRepr::dump() const {
print(llvm::errs());
llvm::errs() << "\n";
}

void RequirementRepr::printImpl(ASTPrinter &out) const {
auto printLayoutConstraint =
[&](const LayoutConstraintLoc &LayoutConstraintLoc) {
LayoutConstraintLoc.getLayoutConstraint()->print(out, PrintOptions());
};

switch (getKind()) {
case RequirementReprKind::LayoutConstraint:
if (auto *repr = getSubjectRepr()) {
repr->print(out, PrintOptions());
}
out << " : ";
printLayoutConstraint(getLayoutConstraintLoc());
break;

case RequirementReprKind::TypeConstraint:
if (auto *repr = getSubjectRepr()) {
repr->print(out, PrintOptions());
}
out << " : ";
if (auto *repr = getConstraintRepr()) {
repr->print(out, PrintOptions());
}
break;

case RequirementReprKind::SameType:
if (auto *repr = getFirstTypeRepr()) {
repr->print(out, PrintOptions());
}
out << " == ";
if (auto *repr = getSecondTypeRepr()) {
repr->print(out, PrintOptions());
}
break;
}
}

void RequirementRepr::print(raw_ostream &out) const {
StreamPrinter printer(out);
printImpl(printer);
}
void RequirementRepr::print(ASTPrinter &out) const {
printImpl(out);
}

static void printTrailingRequirements(ASTPrinter &Printer,
ArrayRef<RequirementRepr> Reqs,
bool printWhereKeyword) {
if (Reqs.empty()) return;

if (printWhereKeyword)
Printer << " where ";
interleave(
Reqs,
[&](const RequirementRepr &req) {
Printer.callPrintStructurePre(PrintStructureKind::GenericRequirement);
req.print(Printer);
Printer.printStructurePost(PrintStructureKind::GenericRequirement);
},
[&] { Printer << ", "; });
}

void GenericParamList::print(llvm::raw_ostream &OS) const {
OS << '<';
interleave(*this,
[&](const GenericTypeParamDecl *P) {
OS << P->getName();
if (!P->getInherited().empty()) {
OS << " : ";
P->getInherited()[0].getType().print(OS);
}
},
[&] { OS << ", "; });

StreamPrinter Printer(OS);
printTrailingRequirements(Printer, getRequirements(),
/*printWhereKeyword*/true);
OS << '>';
}

void GenericParamList::dump() const {
print(llvm::errs());
llvm::errs() << '\n';
}

void TrailingWhereClause::print(llvm::raw_ostream &OS,
bool printWhereKeyword) const {
StreamPrinter Printer(OS);
printTrailingRequirements(Printer, getRequirements(),
printWhereKeyword);
}

static void printGenericParameters(raw_ostream &OS, GenericParamList *Params) {
if (!Params)
return;
Expand Down Expand Up @@ -3139,6 +3037,12 @@ class PrintTypeRepr : public TypeReprVisitor<PrintTypeRepr> {
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}

void visitNamedOpaqueReturnTypeRepr(NamedOpaqueReturnTypeRepr *T) {
printCommon("type_named_opaque_return") << '\n';
printRec(T->getBase());
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}

void visitPlaceholderTypeRepr(PlaceholderTypeRepr *T) {
printCommon("type_placeholder");
PrintWithColorRAII(OS, ParenthesisColor) << ')';
Expand Down
111 changes: 111 additions & 0 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/Expr.h"
#include "swift/AST/FileUnit.h"
#include "swift/AST/GenericParamList.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/Module.h"
#include "swift/AST/NameLookup.h"
Expand Down Expand Up @@ -5851,3 +5852,113 @@ swift::getInheritedForPrinting(const Decl *decl, const PrintOptions &options,
}
}
}

//===----------------------------------------------------------------------===//
// Generic param list printing.
//===----------------------------------------------------------------------===//

void RequirementRepr::dump() const {
print(llvm::errs());
llvm::errs() << "\n";
}

void RequirementRepr::print(raw_ostream &out) const {
StreamPrinter printer(out);
print(printer);
}

void RequirementRepr::print(ASTPrinter &out) const {
auto printLayoutConstraint =
[&](const LayoutConstraintLoc &LayoutConstraintLoc) {
LayoutConstraintLoc.getLayoutConstraint()->print(out, PrintOptions());
};

switch (getKind()) {
case RequirementReprKind::LayoutConstraint:
if (auto *repr = getSubjectRepr()) {
repr->print(out, PrintOptions());
}
out << " : ";
printLayoutConstraint(getLayoutConstraintLoc());
break;

case RequirementReprKind::TypeConstraint:
if (auto *repr = getSubjectRepr()) {
repr->print(out, PrintOptions());
}
out << " : ";
if (auto *repr = getConstraintRepr()) {
repr->print(out, PrintOptions());
}
break;

case RequirementReprKind::SameType:
if (auto *repr = getFirstTypeRepr()) {
repr->print(out, PrintOptions());
}
out << " == ";
if (auto *repr = getSecondTypeRepr()) {
repr->print(out, PrintOptions());
}
break;
}
}

void GenericParamList::dump() const {
print(llvm::errs());
llvm::errs() << '\n';
}

void GenericParamList::print(raw_ostream &out, const PrintOptions &PO) const {
StreamPrinter printer(out);
print(printer, PO);
}

static void printTrailingRequirements(ASTPrinter &Printer,
ArrayRef<RequirementRepr> Reqs,
bool printWhereKeyword) {
if (Reqs.empty())
return;

if (printWhereKeyword)
Printer << " where ";
interleave(
Reqs,
[&](const RequirementRepr &req) {
Printer.callPrintStructurePre(PrintStructureKind::GenericRequirement);
req.print(Printer);
Printer.printStructurePost(PrintStructureKind::GenericRequirement);
},
[&] { Printer << ", "; });
}

void GenericParamList::print(ASTPrinter &Printer,
const PrintOptions &PO) const {
Printer << '<';
interleave(
*this,
[&](const GenericTypeParamDecl *P) {
Printer << P->getName();
if (!P->getInherited().empty()) {
Printer << " : ";

auto loc = P->getInherited()[0];
if (willUseTypeReprPrinting(loc, nullptr, PO)) {
loc.getTypeRepr()->print(Printer, PO);
} else {
loc.getType()->print(Printer, PO);
}
}
},
[&] { Printer << ", "; });

printTrailingRequirements(Printer, getRequirements(),
/*printWhereKeyword*/ true);
Printer << '>';
}

void TrailingWhereClause::print(llvm::raw_ostream &OS,
bool printWhereKeyword) const {
StreamPrinter Printer(OS);
printTrailingRequirements(Printer, getRequirements(), printWhereKeyword);
}
Loading