[Parse] Allow named opaque types in more places

- Allow named opaque types in typed patterns and subscripts
- Fix inheritance clause printing for `GenericParamList`
- clang-format changes from previous commit on this branch
This commit is contained in:
Benjamin Driscoll
2021-06-24 10:59:28 -04:00
parent dddf0eceb0
commit deb0457032
12 changed files with 164 additions and 153 deletions

View File

@@ -81,8 +81,6 @@ class RequirementRepr {
: SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false), : SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false),
FirstType(FirstType), SecondLayout(SecondLayout) { } FirstType(FirstType), SecondLayout(SecondLayout) { }
void printImpl(ASTPrinter &OS) const;
public: public:
/// Construct a new type-constraint requirement. /// Construct a new type-constraint requirement.
/// ///

View File

@@ -1114,8 +1114,7 @@ class NamedOpaqueReturnTypeRepr : public TypeRepr {
GenericParamList *GenericParams; GenericParamList *GenericParams;
public: public:
NamedOpaqueReturnTypeRepr(TypeRepr *Base, NamedOpaqueReturnTypeRepr(TypeRepr *Base, GenericParamList *GenericParams)
GenericParamList *GenericParams)
: TypeRepr(TypeReprKind::NamedOpaqueReturn), Base(Base), : TypeRepr(TypeReprKind::NamedOpaqueReturn), Base(Base),
GenericParams(GenericParams) { GenericParams(GenericParams) {
assert(Base && GenericParams); assert(Base && GenericParams);
@@ -1127,9 +1126,7 @@ public:
static bool classof(const TypeRepr *T) { static bool classof(const TypeRepr *T) {
return T->getKind() == TypeReprKind::NamedOpaqueReturn; return T->getKind() == TypeReprKind::NamedOpaqueReturn;
} }
static bool classof(const NamedOpaqueReturnTypeRepr *T) { static bool classof(const NamedOpaqueReturnTypeRepr *T) { return true; }
return true;
}
private: private:
SourceLoc getStartLocImpl() const; SourceLoc getStartLocImpl() const;

View File

@@ -1223,6 +1223,13 @@ public:
ParserResult<TypeRepr> parseType(Diag<> MessageID, ParserResult<TypeRepr> parseType(Diag<> MessageID,
bool IsSILFuncDecl = false); 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> ParserResult<TypeRepr>
parseTypeSimpleOrComposition(Diag<> MessageID); parseTypeSimpleOrComposition(Diag<> MessageID);

View File

@@ -21,7 +21,6 @@
#include "swift/AST/ForeignAsyncConvention.h" #include "swift/AST/ForeignAsyncConvention.h"
#include "swift/AST/ForeignErrorConvention.h" #include "swift/AST/ForeignErrorConvention.h"
#include "swift/AST/GenericEnvironment.h" #include "swift/AST/GenericEnvironment.h"
#include "swift/AST/GenericParamList.h"
#include "swift/AST/Initializer.h" #include "swift/AST/Initializer.h"
#include "swift/AST/ParameterList.h" #include "swift/AST/ParameterList.h"
#include "swift/AST/ProtocolConformance.h" #include "swift/AST/ProtocolConformance.h"
@@ -114,111 +113,6 @@ namespace {
}; };
} // end anonymous 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);
}
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 << " : ";
P->getInherited()[0].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);
}
static void printGenericParameters(raw_ostream &OS, GenericParamList *Params) { static void printGenericParameters(raw_ostream &OS, GenericParamList *Params) {
if (!Params) if (!Params)
return; return;
@@ -3143,9 +3037,8 @@ public:
PrintWithColorRAII(OS, ParenthesisColor) << ')'; PrintWithColorRAII(OS, ParenthesisColor) << ')';
} }
void void visitNamedOpaqueReturnTypeRepr(NamedOpaqueReturnTypeRepr *T) {
visitNamedOpaqueReturnTypeRepr(NamedOpaqueReturnTypeRepr *T) { printCommon("type_named_opaque_return") << '\n';
printCommon("type_opaque_return_parameterized") << '\n';
printRec(T->getBase()); printRec(T->getBase());
PrintWithColorRAII(OS, ParenthesisColor) << ')'; PrintWithColorRAII(OS, ParenthesisColor) << ')';
} }

View File

@@ -26,6 +26,7 @@
#include "swift/AST/ExistentialLayout.h" #include "swift/AST/ExistentialLayout.h"
#include "swift/AST/Expr.h" #include "swift/AST/Expr.h"
#include "swift/AST/FileUnit.h" #include "swift/AST/FileUnit.h"
#include "swift/AST/GenericParamList.h"
#include "swift/AST/GenericSignature.h" #include "swift/AST/GenericSignature.h"
#include "swift/AST/Module.h" #include "swift/AST/Module.h"
#include "swift/AST/NameLookup.h" #include "swift/AST/NameLookup.h"
@@ -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);
}

View File

@@ -1858,8 +1858,7 @@ bool Traversal::visitOpaqueReturnTypeRepr(OpaqueReturnTypeRepr *T) {
return doIt(T->getConstraint()); return doIt(T->getConstraint());
} }
bool Traversal::visitNamedOpaqueReturnTypeRepr( bool Traversal::visitNamedOpaqueReturnTypeRepr(NamedOpaqueReturnTypeRepr *T) {
NamedOpaqueReturnTypeRepr *T) {
return doIt(T->getBase()); return doIt(T->getBase());
} }

View File

@@ -453,8 +453,8 @@ SourceLoc NamedOpaqueReturnTypeRepr::getLocImpl() const {
return Base->getLoc(); return Base->getLoc();
} }
void NamedOpaqueReturnTypeRepr::printImpl( void NamedOpaqueReturnTypeRepr::printImpl(ASTPrinter &Printer,
ASTPrinter &Printer, const PrintOptions &Opts) const { const PrintOptions &Opts) const {
GenericParams->print(Printer, Opts); GenericParams->print(Printer, Opts);
Printer << ' '; Printer << ' ';
printTypeRepr(Base, Printer, Opts); printTypeRepr(Base, Printer, Opts);

View File

@@ -824,7 +824,7 @@ Parser::parseFunctionArguments(SmallVectorImpl<Identifier> &NamePieces,
/// func-signature: /// func-signature:
/// func-arguments ('async'|'reasync')? func-throws? func-signature-result? /// func-arguments ('async'|'reasync')? func-throws? func-signature-result?
/// func-signature-result: /// func-signature-result:
/// '->' generic-params? type /// '->' type
/// ///
/// Note that this leaves retType as null if unspecified. /// Note that this leaves retType as null if unspecified.
ParserStatus ParserStatus
@@ -865,22 +865,10 @@ Parser::parseFunctionSignature(Identifier SimpleName,
arrowLoc = consumeToken(tok::colon); arrowLoc = consumeToken(tok::colon);
} }
// Check for effect specifiers after the arrow, but before the generic // Check for effect specifiers after the arrow, but before the return type,
// parameters, and correct it. // and correct it.
parseEffectsSpecifiers(arrowLoc, asyncLoc, &reasync, throwsLoc, &rethrows); parseEffectsSpecifiers(arrowLoc, asyncLoc, &reasync, throwsLoc, &rethrows);
GenericParamList *genericParams = nullptr;
if (Context.LangOpts.EnableExperimentalOpaqueReturnTypes) {
auto genericParamsResult = maybeParseGenericParams();
genericParams = genericParamsResult.getPtrOrNull();
Status |= genericParamsResult;
// Check for effect specifiers after the generic parameters, but before
// the return type, and correct it.
parseEffectsSpecifiers(arrowLoc, asyncLoc, &reasync, throwsLoc,
&rethrows);
}
ParserResult<TypeRepr> ResultType = ParserResult<TypeRepr> ResultType =
parseDeclResultType(diag::expected_type_function_result); parseDeclResultType(diag::expected_type_function_result);
retType = ResultType.getPtrOrNull(); retType = ResultType.getPtrOrNull();
@@ -888,11 +876,6 @@ Parser::parseFunctionSignature(Identifier SimpleName,
if (Status.isErrorOrHasCompletion()) if (Status.isErrorOrHasCompletion())
return Status; return Status;
if (genericParams != nullptr) {
retType = new (Context)
NamedOpaqueReturnTypeRepr(retType, genericParams);
}
// Check for effect specifiers after the type and correct it. // Check for effect specifiers after the type and correct it.
parseEffectsSpecifiers(arrowLoc, asyncLoc, &reasync, throwsLoc, &rethrows); parseEffectsSpecifiers(arrowLoc, asyncLoc, &reasync, throwsLoc, &rethrows);
} else { } else {

View File

@@ -547,6 +547,27 @@ ParserResult<TypeRepr> Parser::parseType(Diag<> MessageID,
applyAttributeToType(tyR, attrs, specifier, specifierLoc, isolatedLoc)); applyAttributeToType(tyR, attrs, specifier, specifierLoc, isolatedLoc));
} }
ParserResult<TypeRepr> Parser::parseTypeWithOpaqueParams(Diag<> MessageID) {
GenericParamList *genericParams = nullptr;
if (Context.LangOpts.EnableExperimentalOpaqueReturnTypes) {
auto result = maybeParseGenericParams();
genericParams = result.getPtrOrNull();
if (result.hasCodeCompletion())
return makeParserCodeCompletionStatus();
}
auto typeResult = parseType(MessageID);
if (auto type = typeResult.getPtrOrNull()) {
return makeParserResult(
ParserStatus(typeResult),
genericParams ? new (Context)
NamedOpaqueReturnTypeRepr(type, genericParams)
: type);
} else {
return typeResult;
}
}
ParserResult<TypeRepr> Parser::parseDeclResultType(Diag<> MessageID) { ParserResult<TypeRepr> Parser::parseDeclResultType(Diag<> MessageID) {
if (Tok.is(tok::code_complete)) { if (Tok.is(tok::code_complete)) {
if (CodeCompletion) if (CodeCompletion)
@@ -555,7 +576,7 @@ ParserResult<TypeRepr> Parser::parseDeclResultType(Diag<> MessageID) {
return makeParserCodeCompletionStatus(); return makeParserCodeCompletionStatus();
} }
auto result = parseType(MessageID); auto result = parseTypeWithOpaqueParams(MessageID);
if (!result.isParseErrorOrHasCompletion()) { if (!result.isParseErrorOrHasCompletion()) {
if (Tok.is(tok::r_square)) { if (Tok.is(tok::r_square)) {

View File

@@ -1,10 +1,14 @@
func f() -> <T> () { func f0() -> <T> () {
} }
func g() -> <T> Int { func f1() -> <T> Int {
}
func f2() -> <T: SignedInteger, U: SignedInteger> Int {
} }
// RUN: %target-swift-ide-test -print-ast-typechecked -enable-experimental-opaque-return-types -source-filename %s | %FileCheck %s -check-prefix=CHECK1 // RUN: %target-swift-ide-test -print-ast-typechecked -enable-experimental-opaque-return-types -source-filename %s | %FileCheck %s -check-prefix=CHECK1
// CHECK1: {{^}}func f() {{{$}} // CHECK1: {{^}}func f0() {{{$}}
// CHECK1: {{^}}}{{$}} // CHECK1: {{^}}}{{$}}
// CHECK1: {{^}}func g() -> <T> Int {{{$}} // CHECK1: {{^}}func f1() -> <T> Int {{{$}}
// CHECK1: {{^}}}{{$}}
// CHECK1: {{^}}func f2() -> <T : SignedInteger, U : SignedInteger> Int {{{$}}
// CHECK1: {{^}}}{{$}} // CHECK1: {{^}}}{{$}}

View File

@@ -9,5 +9,4 @@ func f4() async -> <T> () { }
func g0() -> <T> { } // expected-error{{expected type for function result}} func g0() -> <T> { } // expected-error{{expected type for function result}}
func g1() -> async <T> () { } // expected-error{{'async' may only occur before '->'}} func g1() -> async <T> () { } // expected-error{{'async' may only occur before '->'}}
func g2() -> <T> async () { } // expected-error{{'async' may only occur before '->'}} func g2() -> <T> () async { } // expected-error{{'async' may only occur before '->'}}
func g3() -> <T> () async { } // expected-error{{'async' may only occur before '->'}}

View File

@@ -763,12 +763,11 @@ DisableImplicitConcurrencyImport("disable-implicit-concurrency-module-import",
llvm::cl::desc("Disable implicit import of _Concurrency module"), llvm::cl::desc("Disable implicit import of _Concurrency module"),
llvm::cl::init(false)); llvm::cl::init(false));
static llvm::cl::opt<bool> static llvm::cl::opt<bool> EnableExperimentalOpaqueReturnTypes(
EnableExperimentalOpaqueReturnTypes("enable-experimental-opaque-return-types", "enable-experimental-opaque-return-types",
llvm::cl::desc("Enable experimental extensions to opaque return type support"), llvm::cl::desc(
llvm::cl::Hidden, "Enable experimental extensions to opaque return type support"),
llvm::cl::cat(Category), llvm::cl::Hidden, llvm::cl::cat(Category), llvm::cl::init(false));
llvm::cl::init(false));
static llvm::cl::opt<bool> static llvm::cl::opt<bool>
EnableExperimentalDistributed("enable-experimental-distributed", EnableExperimentalDistributed("enable-experimental-distributed",