From 627ecbdfff41e02dff5c841e711e96f5cd5f0281 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Tue, 3 Aug 2021 16:13:59 -0700 Subject: [PATCH 1/2] Rip designated types out of the AST Designated types were removed from the constraint solver in #34315, but they are currently still represented in the AST and fully checked. This change removes them as completely as possible without breaking source compatibility (mainly with old swiftinterfaces) or changing the SwiftSyntax tree. Designated types are still parsed, but they are dropped immediately and a warning is diagnosed. During decl checking we also still check if the precedence group is really a designated type, but only so that we can diagnose a warning and fall back to DefaultPrecedence. This change also fixes an apparent bug in the parser where we did not diagnose operator declarations that contained a `:` followed by a non-identifier token. --- include/swift/AST/Decl.h | 81 +++++----------- include/swift/AST/DiagnosticsParse.def | 9 +- lib/AST/ASTDumper.cpp | 24 +---- lib/AST/ASTPrinter.cpp | 27 ------ lib/Parse/ParseDecl.cpp | 76 +++++++-------- lib/Sema/TypeCheckAccess.cpp | 6 +- lib/Sema/TypeCheckDecl.cpp | 92 +++++------------- lib/Sema/TypeCheckDecl.h | 3 - lib/Sema/TypeCheckDeclPrimary.cpp | 14 +-- lib/Serialization/Deserialization.cpp | 32 +------ lib/Serialization/ModuleFormat.h | 8 +- lib/Serialization/Serialization.cpp | 12 +-- stdlib/public/core/Policy.swift | 94 +++++++++---------- test/Parse/operator_decl.swift | 2 +- .../operator_decl_designated_types.swift | 33 +++++-- 15 files changed, 170 insertions(+), 343 deletions(-) diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 6528914bf2558..ab8efd76cb853 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -7276,22 +7276,13 @@ class OperatorDecl : public Decl { Identifier name; - ArrayRef> Identifiers; - ArrayRef DesignatedNominalTypes; SourceLoc getLocFromSource() const { return NameLoc; } friend class Decl; public: OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc, - Identifier Name, SourceLoc NameLoc, - ArrayRef> Identifiers) - : Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name), - Identifiers(Identifiers) {} - - OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc, - Identifier Name, SourceLoc NameLoc, - ArrayRef DesignatedNominalTypes) - : Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name), - DesignatedNominalTypes(DesignatedNominalTypes) {} + Identifier Name, SourceLoc NameLoc) + : Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name) + {} /// Retrieve the operator's fixity, corresponding to the concrete subclass /// of the OperatorDecl. @@ -7318,25 +7309,6 @@ class OperatorDecl : public Decl { // OperatorDecls. DeclBaseName getBaseName() const { return name; } - /// Get the list of identifiers after the colon in the operator declaration. - /// - /// This list includes the names of designated types. For infix operators, the - /// first item in the list is a precedence group instead. - /// - /// \todo These two purposes really ought to be in separate properties and the - /// designated type list should be of TypeReprs instead of Identifiers. - ArrayRef> getIdentifiers() const { - return Identifiers; - } - - ArrayRef getDesignatedNominalTypes() const { - return DesignatedNominalTypes; - } - - void setDesignatedNominalTypes(ArrayRef nominalTypes) { - DesignatedNominalTypes = nominalTypes; - } - static bool classof(const Decl *D) { // Workaround: http://llvm.org/PR35906 if (DeclKind::Last_Decl == DeclKind::Last_OperatorDecl) @@ -7352,22 +7324,23 @@ class OperatorDecl : public Decl { /// infix operator /+/ : AdditionPrecedence, Numeric /// \endcode class InfixOperatorDecl : public OperatorDecl { - SourceLoc ColonLoc; + SourceLoc ColonLoc, PrecedenceGroupLoc; + Identifier PrecedenceGroupName; public: InfixOperatorDecl(DeclContext *DC, SourceLoc operatorLoc, Identifier name, SourceLoc nameLoc, SourceLoc colonLoc, - ArrayRef> identifiers) - : OperatorDecl(DeclKind::InfixOperator, DC, operatorLoc, name, nameLoc, - identifiers), - ColonLoc(colonLoc) {} + Identifier precedenceGroupName, + SourceLoc precedenceGroupLoc) + : OperatorDecl(DeclKind::InfixOperator, DC, operatorLoc, name, nameLoc), + ColonLoc(colonLoc), PrecedenceGroupLoc(precedenceGroupLoc), + PrecedenceGroupName(precedenceGroupName) {} SourceLoc getEndLoc() const { - auto identifiers = getIdentifiers(); - if (identifiers.empty()) - return getNameLoc(); + if (getPrecedenceGroupLoc().isValid()) + return getPrecedenceGroupLoc(); - return identifiers.back().Loc; + return getNameLoc(); } SourceRange getSourceRange() const { @@ -7376,6 +7349,8 @@ class InfixOperatorDecl : public OperatorDecl { SourceLoc getColonLoc() const { return ColonLoc; } + Identifier getPrecedenceGroupName() const { return PrecedenceGroupName; } + SourceLoc getPrecedenceGroupLoc() const { return PrecedenceGroupLoc; } PrecedenceGroupDecl *getPrecedenceGroup() const; static bool classof(const Decl *D) { @@ -7391,16 +7366,9 @@ class InfixOperatorDecl : public OperatorDecl { class PrefixOperatorDecl : public OperatorDecl { public: PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name, - SourceLoc NameLoc, - ArrayRef> Identifiers) - : OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc, - Identifiers) {} - - PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name, - SourceLoc NameLoc, - ArrayRef designatedNominalTypes) - : OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc, - designatedNominalTypes) {} + SourceLoc NameLoc) + : OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc) + {} SourceRange getSourceRange() const { return { getOperatorLoc(), getNameLoc() }; @@ -7419,16 +7387,9 @@ class PrefixOperatorDecl : public OperatorDecl { class PostfixOperatorDecl : public OperatorDecl { public: PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name, - SourceLoc NameLoc, - ArrayRef> Identifiers) - : OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc, - Identifiers) {} - - PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name, - SourceLoc NameLoc, - ArrayRef designatedNominalTypes) - : OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc, - designatedNominalTypes) {} + SourceLoc NameLoc) + : OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc) + {} SourceRange getSourceRange() const { return { getOperatorLoc(), getNameLoc() }; diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def index 141f26771079d..adc92efc16486 100644 --- a/include/swift/AST/DiagnosticsParse.def +++ b/include/swift/AST/DiagnosticsParse.def @@ -435,11 +435,12 @@ ERROR(deprecated_operator_body_use_group,PointsToFirstBadToken, "use a precedence group instead", ()) ERROR(operator_decl_no_fixity,none, "operator must be declared as 'prefix', 'postfix', or 'infix'", ()) +ERROR(operator_decl_expected_precedencegroup, none, + "expected precedence group name after ':' in operator declaration", ()) -ERROR(operator_decl_expected_type,none, - "expected designated type in operator declaration", ()) -ERROR(operator_decl_trailing_comma,none, - "trailing comma in operator declaration", ()) +WARNING(operator_decl_remove_designated_types,none, + "designated types are no longer used by the compiler; please remove " + "the designated type list from this operator declaration", ()) // PrecedenceGroup ERROR(precedencegroup_not_infix,none, diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index d5700a6f8e681..817e689c781e4 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -1145,43 +1145,23 @@ namespace { PrintWithColorRAII(OS, ParenthesisColor) << ')'; } - void printOperatorIdentifiers(OperatorDecl *OD) { - auto identifiers = OD->getIdentifiers(); - for (auto index : indices(identifiers)) { - OS.indent(Indent + 2); - OS << "identifier #" << index << " " << identifiers[index].Item; - if (index != identifiers.size() - 1) - OS << "\n"; - } - } - void visitInfixOperatorDecl(InfixOperatorDecl *IOD) { printCommon(IOD, "infix_operator_decl"); OS << " " << IOD->getName(); - if (!IOD->getIdentifiers().empty()) { - OS << "\n"; - printOperatorIdentifiers(IOD); - } + if (!IOD->getPrecedenceGroupName().empty()) + OS << " precedence_group_name=" << IOD->getPrecedenceGroupName(); PrintWithColorRAII(OS, ParenthesisColor) << ')'; } void visitPrefixOperatorDecl(PrefixOperatorDecl *POD) { printCommon(POD, "prefix_operator_decl"); OS << " " << POD->getName(); - if (!POD->getIdentifiers().empty()) { - OS << "\n"; - printOperatorIdentifiers(POD); - } PrintWithColorRAII(OS, ParenthesisColor) << ')'; } void visitPostfixOperatorDecl(PostfixOperatorDecl *POD) { printCommon(POD, "postfix_operator_decl"); OS << " " << POD->getName(); - if (!POD->getIdentifiers().empty()) { - OS << "\n"; - printOperatorIdentifiers(POD); - } PrintWithColorRAII(OS, ParenthesisColor) << ')'; } diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 5d8062e74f0cc..98834079c0b2e 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -3776,15 +3776,6 @@ void PrintAST::visitInfixOperatorDecl(InfixOperatorDecl *decl) { }); if (auto *group = decl->getPrecedenceGroup()) Printer << " : " << group->getName(); - auto designatedNominalTypes = decl->getDesignatedNominalTypes(); - auto first = true; - for (auto typeDecl : designatedNominalTypes) { - if (first && !decl->getPrecedenceGroup()) - Printer << " : " << typeDecl->getName(); - else - Printer << ", " << typeDecl->getName(); - first = false; - } } void PrintAST::visitPrecedenceGroupDecl(PrecedenceGroupDecl *decl) { @@ -3853,15 +3844,6 @@ void PrintAST::visitPrefixOperatorDecl(PrefixOperatorDecl *decl) { [&]{ Printer.printName(decl->getName()); }); - auto designatedNominalTypes = decl->getDesignatedNominalTypes(); - auto first = true; - for (auto typeDecl : designatedNominalTypes) { - if (first) - Printer << " : " << typeDecl->getName(); - else - Printer << ", " << typeDecl->getName(); - first = false; - } } void PrintAST::visitPostfixOperatorDecl(PostfixOperatorDecl *decl) { @@ -3871,15 +3853,6 @@ void PrintAST::visitPostfixOperatorDecl(PostfixOperatorDecl *decl) { [&]{ Printer.printName(decl->getName()); }); - auto designatedNominalTypes = decl->getDesignatedNominalTypes(); - auto first = true; - for (auto typeDecl : designatedNominalTypes) { - if (first) - Printer << " : " << typeDecl->getName(); - else - Printer << ", " << typeDecl->getName(); - first = false; - } } void PrintAST::visitModuleDecl(ModuleDecl *decl) { } diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 630e8ef8e8cc6..9d113fa3ddb61 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -8115,8 +8115,8 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name, // designated protocol. These both look like identifiers, so we // parse them both as identifiers here and sort it out in type // checking. - SourceLoc colonLoc; - SmallVector, 4> identifiers; + SourceLoc colonLoc, groupLoc; + Identifier groupName; if (Tok.is(tok::colon)) { SyntaxParsingContext GroupCtxt(SyntaxContext, SyntaxKind::OperatorPrecedenceAndTypes); @@ -8131,43 +8131,40 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name, return makeParserCodeCompletionResult(); } - if (Context.TypeCheckerOpts.EnableOperatorDesignatedTypes) { - if (Tok.is(tok::identifier)) { - SyntaxParsingContext GroupCtxt(SyntaxContext, - SyntaxKind::IdentifierList); + SyntaxParsingContext ListCtxt(SyntaxContext, SyntaxKind::IdentifierList); - Identifier name; - auto loc = consumeIdentifier(name, /*diagnoseDollarPrefix=*/false); - identifiers.emplace_back(name, loc); + (void)parseIdentifier(groupName, groupLoc, + diag::operator_decl_expected_precedencegroup, + /*diagnoseDollarPrefix=*/false); - while (Tok.is(tok::comma)) { - auto comma = consumeToken(); + if (Context.TypeCheckerOpts.EnableOperatorDesignatedTypes) { + // Designated types have been removed; consume the list (mainly for source + // compatibility with old swiftinterfaces) and emit a warning. - if (Tok.is(tok::identifier)) { - Identifier name; - auto loc = consumeIdentifier(name, /*diagnoseDollarPrefix=*/false); - identifiers.emplace_back(name, loc); - } else { - if (Tok.isNot(tok::eof)) { - auto otherTokLoc = consumeToken(); - diagnose(otherTokLoc, diag::operator_decl_expected_type); - } else { - diagnose(comma, diag::operator_decl_trailing_comma); - } - } - } + // These SourceLocs point to the ends of the designated type list. If + // `typesEndLoc` never becomes valid, we didn't find any designated types. + SourceLoc typesStartLoc = Tok.getLoc(); + SourceLoc typesEndLoc; + + if (isPrefix || isPostfix) { + // These have no precedence group, so we already parsed the first entry + // in the designated types list. Retroactively include it in the range. + typesStartLoc = colonLoc; + typesEndLoc = groupLoc; } - } else if (Tok.is(tok::identifier)) { - SyntaxParsingContext GroupCtxt(SyntaxContext, - SyntaxKind::IdentifierList); - Identifier name; - auto nameLoc = consumeIdentifier(name, /*diagnoseDollarPrefix=*/false); - identifiers.emplace_back(name, nameLoc); + while (consumeIf(tok::comma, typesEndLoc)) { + if (Tok.isNot(tok::eof)) + typesEndLoc = consumeToken(); + } + if (typesEndLoc.isValid()) + diagnose(typesStartLoc, diag::operator_decl_remove_designated_types) + .fixItRemove({typesStartLoc, typesEndLoc}); + } else { if (isPrefix || isPostfix) { diagnose(colonLoc, diag::precedencegroup_not_infix) - .fixItRemove({colonLoc, nameLoc}); + .fixItRemove({colonLoc, groupLoc}); } // Nothing to complete here, simply consume the token. if (Tok.is(tok::code_complete)) @@ -8183,10 +8180,7 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name, } else { auto Diag = diagnose(lBraceLoc, diag::deprecated_operator_body); if (Tok.is(tok::r_brace)) { - SourceLoc lastGoodLoc = - !identifiers.empty() ? identifiers.back().Loc : SourceLoc(); - if (lastGoodLoc.isInvalid()) - lastGoodLoc = NameLoc; + SourceLoc lastGoodLoc = groupLoc.isValid() ? groupLoc : NameLoc; SourceLoc lastGoodLocEnd = Lexer::getLocForEndOfToken(SourceMgr, lastGoodLoc); SourceLoc rBraceEnd = Lexer::getLocForEndOfToken(SourceMgr, Tok.getLoc()); @@ -8199,18 +8193,16 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name, } OperatorDecl *res; - if (Attributes.hasAttribute()) + if (isPrefix) res = new (Context) - PrefixOperatorDecl(CurDeclContext, OperatorLoc, Name, NameLoc, - Context.AllocateCopy(identifiers)); - else if (Attributes.hasAttribute()) + PrefixOperatorDecl(CurDeclContext, OperatorLoc, Name, NameLoc); + else if (isPostfix) res = new (Context) - PostfixOperatorDecl(CurDeclContext, OperatorLoc, Name, NameLoc, - Context.AllocateCopy(identifiers)); + PostfixOperatorDecl(CurDeclContext, OperatorLoc, Name, NameLoc); else res = new (Context) InfixOperatorDecl(CurDeclContext, OperatorLoc, Name, NameLoc, colonLoc, - Context.AllocateCopy(identifiers)); + groupName, groupLoc); diagnoseOperatorFixityAttributes(*this, Attributes, res); diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp index 7969cff02e0eb..ba09960520acf 100644 --- a/lib/Sema/TypeCheckAccess.cpp +++ b/lib/Sema/TypeCheckAccess.cpp @@ -1874,12 +1874,10 @@ class DeclAvailabilityChecker : public DeclVisitor { } void visitInfixOperatorDecl(InfixOperatorDecl *IOD) { - // FIXME: Handle operator designated types (which also applies to prefix - // and postfix operators). if (auto *precedenceGroup = IOD->getPrecedenceGroup()) { - if (!IOD->getIdentifiers().empty()) { + if (!IOD->getPrecedenceGroupName().empty()) { checkPrecedenceGroup(precedenceGroup, IOD, IOD->getLoc(), - IOD->getIdentifiers().front().Loc); + IOD->getPrecedenceGroupLoc()); } } } diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index ad3d58496fe05..094a954a86907 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -1524,44 +1524,19 @@ TypeChecker::lookupPrecedenceGroup(DeclContext *dc, Identifier name, return PrecedenceGroupLookupResult(dc, name, std::move(groups)); } -static NominalTypeDecl *resolveSingleNominalTypeDecl( - DeclContext *DC, SourceLoc loc, Identifier ident, ASTContext &Ctx, - TypeResolutionFlags flags = TypeResolutionFlags(0)) { +static bool canResolveSingleNominalTypeDecl( + DeclContext *DC, SourceLoc loc, Identifier ident, ASTContext &Ctx) { auto *TyR = new (Ctx) SimpleIdentTypeRepr(DeclNameLoc(loc), DeclNameRef(ident)); - const auto options = - TypeResolutionOptions(TypeResolverContext::TypeAliasDecl) | flags; - + TypeResolutionOptions options{TypeResolverContext::TypeAliasDecl}; + options |= TypeResolutionFlags::SilenceErrors; const auto result = - TypeResolution::forInterface(DC, options, - // FIXME: Should unbound generics be allowed - // to appear amongst designated types? - /*unboundTyOpener*/ nullptr, + TypeResolution::forInterface(DC, options, /*unboundTyOpener*/ nullptr, /*placeholderHandler*/ nullptr) .resolveType(TyR); - if (result->hasError()) - return nullptr; - return result->getAnyNominal(); -} - -bool swift::checkDesignatedTypes(OperatorDecl *OD, - ArrayRef> identifiers) { - auto &ctx = OD->getASTContext(); - auto *DC = OD->getDeclContext(); - - SmallVector designatedNominalTypes; - for (auto ident : identifiers) { - auto *decl = resolveSingleNominalTypeDecl(DC, ident.Loc, ident.Item, ctx); - if (!decl) - return true; - - designatedNominalTypes.push_back(decl); - } - - OD->setDesignatedNominalTypes(ctx.AllocateCopy(designatedNominalTypes)); - return false; + return !result->hasError(); } /// Validate the given operator declaration. @@ -1575,49 +1550,28 @@ OperatorPrecedenceGroupRequest::evaluate(Evaluator &evaluator, auto &ctx = IOD->getASTContext(); auto *dc = IOD->getDeclContext(); - auto enableOperatorDesignatedTypes = - ctx.TypeCheckerOpts.EnableOperatorDesignatedTypes; - - PrecedenceGroupDecl *group = nullptr; - - auto identifiers = IOD->getIdentifiers(); - if (!identifiers.empty()) { - auto name = identifiers[0].Item; - auto loc = identifiers[0].Loc; - - auto canResolveType = [&]() -> bool { - return enableOperatorDesignatedTypes && - resolveSingleNominalTypeDecl(dc, loc, name, ctx, - TypeResolutionFlags::SilenceErrors); - }; - - // Make sure not to diagnose in the case where we failed to find a - // precedencegroup, but we could resolve a type instead. + auto name = IOD->getPrecedenceGroupName(); + if (!name.empty()) { + auto loc = IOD->getPrecedenceGroupLoc(); auto groups = TypeChecker::lookupPrecedenceGroup(dc, name, loc); - if (groups.hasResults() || !canResolveType()) { - group = groups.getSingleOrDiagnose(loc); - identifiers = identifiers.slice(1); - } - } - // Unless operator designed types are enabled, the parser will ensure that - // only one identifier is allowed in the clause, which we should have just - // handled. - assert(identifiers.empty() || enableOperatorDesignatedTypes); + bool wasActuallyADesignatedType = !groups.hasResults() && + ctx.TypeCheckerOpts.EnableOperatorDesignatedTypes && + canResolveSingleNominalTypeDecl(dc, loc, name, ctx); - if (!group) { - auto groups = TypeChecker::lookupPrecedenceGroup( - dc, ctx.Id_DefaultPrecedence, SourceLoc()); - group = groups.getSingleOrDiagnose(IOD->getLoc(), /*forBuiltin*/ true); - } + if (!wasActuallyADesignatedType) + return groups.getSingleOrDiagnose(loc); - auto nominalTypes = IOD->getDesignatedNominalTypes(); - if (nominalTypes.empty() && enableOperatorDesignatedTypes) { - if (checkDesignatedTypes(IOD, identifiers)) { - IOD->setInvalid(); - } + // Warn about the designated type, then fall through to look up + // DefaultPrecedence as though `PrecedenceGroupName` had never been set. + ctx.Diags.diagnose(IOD->getColonLoc(), + diag::operator_decl_remove_designated_types) + .fixItRemove({IOD->getColonLoc(), loc}); } - return group; + + auto groups = TypeChecker::lookupPrecedenceGroup( + dc, ctx.Id_DefaultPrecedence, SourceLoc()); + return groups.getSingleOrDiagnose(IOD->getLoc(), /*forBuiltin*/ true); } SelfAccessKind diff --git a/lib/Sema/TypeCheckDecl.h b/lib/Sema/TypeCheckDecl.h index 6c6622a73b1f8..bd8d71d440762 100644 --- a/lib/Sema/TypeCheckDecl.h +++ b/lib/Sema/TypeCheckDecl.h @@ -56,9 +56,6 @@ Optional computeAutomaticEnumValueKind(EnumDecl *ED); void validatePrecedenceGroup(PrecedenceGroupDecl *PGD); -bool checkDesignatedTypes(OperatorDecl *OD, - ArrayRef> identifiers); - void diagnoseAttrsAddedByAccessNote(SourceFile &SF); } diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index 083327078b9a1..e8e3d99fc9538 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -1746,20 +1746,8 @@ class DeclChecker : public DeclVisitor { void visitOperatorDecl(OperatorDecl *OD) { TypeChecker::checkDeclAttributes(OD); checkRedeclaration(OD); - auto &Ctx = OD->getASTContext(); - if (auto *IOD = dyn_cast(OD)) { + if (auto *IOD = dyn_cast(OD)) (void)IOD->getPrecedenceGroup(); - } else { - auto nominalTypes = OD->getDesignatedNominalTypes(); - const auto wantsDesignatedTypes = - Ctx.TypeCheckerOpts.EnableOperatorDesignatedTypes; - if (nominalTypes.empty() && wantsDesignatedTypes) { - auto identifiers = OD->getIdentifiers(); - if (checkDesignatedTypes(OD, identifiers)) - OD->setInvalid(); - } - return; - } checkAccessControl(OD); } diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index f91e10305aab1..0330f0d2a8bf7 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -3632,27 +3632,16 @@ class DeclDeserializer { StringRef blobData) { IdentifierID nameID; DeclContextID contextID; - ArrayRef designatedNominalTypeDeclIDs; - OperatorLayout::readRecord(scratch, nameID, contextID, - designatedNominalTypeDeclIDs); + OperatorLayout::readRecord(scratch, nameID, contextID); Identifier name = MF.getIdentifier(nameID); PrettySupplementalDeclNameTrace trace(name); auto DC = MF.getDeclContext(contextID); - SmallVector designatedNominalTypes; - for (auto id : designatedNominalTypeDeclIDs) { - Expected nominal = MF.getDeclChecked(id); - if (!nominal) - return nominal.takeError(); - designatedNominalTypes.push_back(cast(nominal.get())); - } - auto result = MF.createDecl( - DC, SourceLoc(), name, SourceLoc(), - ctx.AllocateCopy(designatedNominalTypes)); + DC, SourceLoc(), name, SourceLoc()); declOrOffset = result; return result; @@ -3675,11 +3664,9 @@ class DeclDeserializer { IdentifierID nameID; DeclContextID contextID; DeclID precedenceGroupID; - ArrayRef designatedNominalTypeDeclIDs; decls_block::InfixOperatorLayout::readRecord(scratch, nameID, contextID, - precedenceGroupID, - designatedNominalTypeDeclIDs); + precedenceGroupID); Identifier name = MF.getIdentifier(nameID); PrettySupplementalDeclNameTrace trace(name); @@ -3689,18 +3676,9 @@ class DeclDeserializer { auto DC = MF.getDeclContext(contextID); - SmallVector designatedNominalTypes; - for (auto id : designatedNominalTypeDeclIDs) { - Expected nominal = MF.getDeclChecked(id); - if (!nominal) - return nominal.takeError(); - designatedNominalTypes.push_back(cast(nominal.get())); - } - auto result = MF.createDecl( - DC, SourceLoc(), name, SourceLoc(), SourceLoc(), - ArrayRef>{}); - result->setDesignatedNominalTypes(ctx.AllocateCopy(designatedNominalTypes)); + DC, SourceLoc(), name, SourceLoc(), SourceLoc(), Identifier(), + SourceLoc()); ctx.evaluator.cacheOutput( OperatorPrecedenceGroupRequest{result}, std::move(cast_or_null(precedenceGroup.get()))); diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index a69451a8b11df..533012dcda162 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -56,7 +56,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 622; // builtin conformance kind +const uint16_t SWIFTMODULE_VERSION_MINOR = 623; // remove designated types /// A standard hash seed used for all string hashes in a serialized module. /// @@ -1427,8 +1427,7 @@ namespace decls_block { using UnaryOperatorLayout = BCRecordLayout< Code, // ID field IdentifierIDField, // name - DeclContextIDField, // context decl - BCArray // designated types + DeclContextIDField // context decl >; using PrefixOperatorLayout = UnaryOperatorLayout; @@ -1438,8 +1437,7 @@ namespace decls_block { INFIX_OPERATOR_DECL, IdentifierIDField, // name DeclContextIDField,// context decl - DeclIDField, // precedence group - BCArray // designated types + DeclIDField // precedence group >; using PrecedenceGroupLayout = BCRecordLayout< diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 4bc8b3776c60d..fcdabc69e0a4b 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -3238,29 +3238,21 @@ class Serializer::DeclSerializer : public DeclVisitor { auto contextID = S.addDeclContextRef(op->getDeclContext()); auto nameID = S.addDeclBaseNameRef(op->getName()); auto groupID = S.addDeclRef(op->getPrecedenceGroup()); - SmallVector designatedNominalTypeDeclIDs; - for (auto *decl : op->getDesignatedNominalTypes()) - designatedNominalTypeDeclIDs.push_back(S.addDeclRef(decl)); unsigned abbrCode = S.DeclTypeAbbrCodes[InfixOperatorLayout::Code]; InfixOperatorLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, nameID, - contextID.getOpaqueValue(), groupID, - designatedNominalTypeDeclIDs); + contextID.getOpaqueValue(), groupID); } template void visitUnaryOperatorDecl(const OperatorDecl *op) { auto contextID = S.addDeclContextRef(op->getDeclContext()); - SmallVector designatedNominalTypeDeclIDs; - for (auto *decl : op->getDesignatedNominalTypes()) - designatedNominalTypeDeclIDs.push_back(S.addDeclRef(decl)); unsigned abbrCode = S.DeclTypeAbbrCodes[Layout::Code]; Layout::emitRecord(S.Out, S.ScratchRecord, abbrCode, S.addDeclBaseNameRef(op->getName()), - contextID.getOpaqueValue(), - designatedNominalTypeDeclIDs); + contextID.getOpaqueValue()); } void visitPrefixOperatorDecl(const PrefixOperatorDecl *op) { diff --git a/stdlib/public/core/Policy.swift b/stdlib/public/core/Policy.swift index 5cd9435261271..161c53a55bf53 100644 --- a/stdlib/public/core/Policy.swift +++ b/stdlib/public/core/Policy.swift @@ -384,7 +384,7 @@ precedencegroup BitwiseShiftPrecedence { // Standard postfix operators. postfix operator ++ postfix operator -- -postfix operator ...: Comparable +postfix operator ... // Optional unwrapping operator is built into the compiler as a part of // postfix expression grammar. @@ -394,42 +394,42 @@ postfix operator ...: Comparable // Standard prefix operators. prefix operator ++ prefix operator -- -prefix operator !: Bool -prefix operator ~: BinaryInteger -prefix operator +: AdditiveArithmetic -prefix operator -: SignedNumeric -prefix operator ...: Comparable -prefix operator ..<: Comparable +prefix operator ! +prefix operator ~ +prefix operator + +prefix operator - +prefix operator ... +prefix operator ..< // Standard infix operators. // "Exponentiative" -infix operator <<: BitwiseShiftPrecedence, BinaryInteger -infix operator &<<: BitwiseShiftPrecedence, FixedWidthInteger -infix operator >>: BitwiseShiftPrecedence, BinaryInteger -infix operator &>>: BitwiseShiftPrecedence, FixedWidthInteger +infix operator <<: BitwiseShiftPrecedence +infix operator &<<: BitwiseShiftPrecedence +infix operator >>: BitwiseShiftPrecedence +infix operator &>>: BitwiseShiftPrecedence // "Multiplicative" -infix operator *: MultiplicationPrecedence, Numeric -infix operator &*: MultiplicationPrecedence, FixedWidthInteger -infix operator /: MultiplicationPrecedence, BinaryInteger, FloatingPoint -infix operator %: MultiplicationPrecedence, BinaryInteger -infix operator &: MultiplicationPrecedence, BinaryInteger +infix operator *: MultiplicationPrecedence +infix operator &*: MultiplicationPrecedence +infix operator /: MultiplicationPrecedence +infix operator %: MultiplicationPrecedence +infix operator &: MultiplicationPrecedence // "Additive" -infix operator +: AdditionPrecedence, AdditiveArithmetic, String, Array, Strideable -infix operator &+: AdditionPrecedence, FixedWidthInteger -infix operator -: AdditionPrecedence, AdditiveArithmetic, Strideable -infix operator &-: AdditionPrecedence, FixedWidthInteger -infix operator |: AdditionPrecedence, BinaryInteger -infix operator ^: AdditionPrecedence, BinaryInteger +infix operator +: AdditionPrecedence +infix operator &+: AdditionPrecedence +infix operator -: AdditionPrecedence +infix operator &-: AdditionPrecedence +infix operator |: AdditionPrecedence +infix operator ^: AdditionPrecedence // FIXME: is this the right precedence level for "..." ? -infix operator ...: RangeFormationPrecedence, Comparable -infix operator ..<: RangeFormationPrecedence, Comparable +infix operator ...: RangeFormationPrecedence +infix operator ..<: RangeFormationPrecedence // The cast operators 'as' and 'is' are hardcoded as if they had the // following attributes: @@ -441,12 +441,12 @@ infix operator ??: NilCoalescingPrecedence // "Comparative" -infix operator <: ComparisonPrecedence, Comparable -infix operator <=: ComparisonPrecedence, Comparable -infix operator >: ComparisonPrecedence, Comparable -infix operator >=: ComparisonPrecedence, Comparable -infix operator ==: ComparisonPrecedence, Equatable -infix operator !=: ComparisonPrecedence, Equatable +infix operator <: ComparisonPrecedence +infix operator <=: ComparisonPrecedence +infix operator >: ComparisonPrecedence +infix operator >=: ComparisonPrecedence +infix operator ==: ComparisonPrecedence +infix operator !=: ComparisonPrecedence infix operator ===: ComparisonPrecedence infix operator !==: ComparisonPrecedence // FIXME: ~= will be built into the compiler. @@ -454,11 +454,11 @@ infix operator ~=: ComparisonPrecedence // "Conjunctive" -infix operator &&: LogicalConjunctionPrecedence, Bool +infix operator &&: LogicalConjunctionPrecedence // "Disjunctive" -infix operator ||: LogicalDisjunctionPrecedence, Bool +infix operator ||: LogicalDisjunctionPrecedence // User-defined ternary operators are not supported. The ? : operator is // hardcoded as if it had the following attributes: @@ -470,21 +470,21 @@ infix operator ||: LogicalDisjunctionPrecedence, Bool // Compound -infix operator *=: AssignmentPrecedence, Numeric -infix operator &*=: AssignmentPrecedence, FixedWidthInteger -infix operator /=: AssignmentPrecedence, BinaryInteger -infix operator %=: AssignmentPrecedence, BinaryInteger -infix operator +=: AssignmentPrecedence, AdditiveArithmetic, String, Array, Strideable -infix operator &+=: AssignmentPrecedence, FixedWidthInteger -infix operator -=: AssignmentPrecedence, AdditiveArithmetic, Strideable -infix operator &-=: AssignmentPrecedence, FixedWidthInteger -infix operator <<=: AssignmentPrecedence, BinaryInteger -infix operator &<<=: AssignmentPrecedence, FixedWidthInteger -infix operator >>=: AssignmentPrecedence, BinaryInteger -infix operator &>>=: AssignmentPrecedence, FixedWidthInteger -infix operator &=: AssignmentPrecedence, BinaryInteger -infix operator ^=: AssignmentPrecedence, BinaryInteger -infix operator |=: AssignmentPrecedence, BinaryInteger +infix operator *=: AssignmentPrecedence +infix operator &*=: AssignmentPrecedence +infix operator /=: AssignmentPrecedence +infix operator %=: AssignmentPrecedence +infix operator +=: AssignmentPrecedence +infix operator &+=: AssignmentPrecedence +infix operator -=: AssignmentPrecedence +infix operator &-=: AssignmentPrecedence +infix operator <<=: AssignmentPrecedence +infix operator &<<=: AssignmentPrecedence +infix operator >>=: AssignmentPrecedence +infix operator &>>=: AssignmentPrecedence +infix operator &=: AssignmentPrecedence +infix operator ^=: AssignmentPrecedence +infix operator |=: AssignmentPrecedence // Workaround for SubTLF: Default // implementations in protocols. Library authors should ensure diff --git a/test/Parse/operator_decl.swift b/test/Parse/operator_decl.swift index 3cd52b66232ff..ca6f918d0eebd 100644 --- a/test/Parse/operator_decl.swift +++ b/test/Parse/operator_decl.swift @@ -63,7 +63,7 @@ infix operator =#= infix operator +++= infix operator *** : A -infix operator --- : ; +infix operator --- : ; // expected-error {{expected precedence group name after ':' in operator declaration}} precedencegroup { // expected-error {{expected identifier after 'precedencegroup'}} associativity: right diff --git a/test/Parse/operator_decl_designated_types.swift b/test/Parse/operator_decl_designated_types.swift index 0a236141abef7..403d34fca27ab 100644 --- a/test/Parse/operator_decl_designated_types.swift +++ b/test/Parse/operator_decl_designated_types.swift @@ -19,8 +19,11 @@ protocol InfixMagicOperatorProtocol { } prefix operator ^^ : PrefixMagicOperatorProtocol +// expected-warning@-1 {{designated types are no longer used by the compiler; please remove the designated type list from this operator declaration}} {{20-49=}} infix operator <*< : MediumPrecedence, InfixMagicOperatorProtocol +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{39-67=}} postfix operator ^^ : PostfixMagicOperatorProtocol +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{21-51=}} infix operator ^*^ prefix operator *^^ @@ -30,44 +33,56 @@ infix operator **>> : UndeclaredPrecedence // expected-error@-1 {{unknown precedence group 'UndeclaredPrecedence'}} infix operator **+> : MediumPrecedence, UndeclaredProtocol -// expected-error@-1 {{cannot find type 'UndeclaredProtocol' in scope}} +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{39-59=}} prefix operator *+*> : MediumPrecedence -// expected-error@-1 {{cannot find type 'MediumPrecedence' in scope}} +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{22-40=}} postfix operator ++*> : MediumPrecedence -// expected-error@-1 {{cannot find type 'MediumPrecedence' in scope}} +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{23-41=}} prefix operator *++> : UndeclaredProtocol -// expected-error@-1 {{cannot find type 'UndeclaredProtocol' in scope}} +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{22-42=}} postfix operator +*+> : UndeclaredProtocol -// expected-error@-1 {{cannot find type 'UndeclaredProtocol' in scope}} +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{23-43=}} struct Struct {} class Class {} infix operator *>*> : Struct +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{21-29=}} infix operator >**> : Class +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{21-28=}} prefix operator **>> : Struct +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{22-30=}} prefix operator *>*> : Class +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{22-29=}} postfix operator >*>* : Struct +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{23-31=}} postfix operator >>** : Class +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{23-30=}} infix operator <*<<< : MediumPrecedence, & -// expected-error@-1 {{expected designated type in operator declaration}} +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{41-44=}} infix operator **^^ : MediumPrecedence // expected-note {{previous operator declaration here}} infix operator **^^ : InfixMagicOperatorProtocol // expected-error {{operator redeclared}} +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{21-50=}} infix operator ^%*%^ : MediumPrecedence, Struct, Class +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{40-55=}} infix operator ^%*%% : Struct, Class +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{30-37=}} +// expected-warning@-2 {{designated types are no longer used by the compiler}} {{22-30=}} prefix operator %^*^^ : Struct, Class +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{23-38=}} postfix operator ^^*^% : Struct, Class +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{24-39=}} prefix operator %%*^^ : LowPrecedence, Class -// expected-error@-1{{cannot find type 'LowPrecedence' in scope}} +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{23-45=}} postfix operator ^^*%% : MediumPrecedence, Class -// expected-error@-1{{cannot find type 'MediumPrecedence' in scope}} +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{24-49=}} -// expected-error@+1 {{trailing comma in operator declaration}} infix operator <*<>*> : AdditionPrecedence, +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{43-44=}} From ec05421e2cd97b46e595560b5a77662c2f701b5f Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Mon, 2 Aug 2021 23:07:44 -0700 Subject: [PATCH 2/2] Don't try to look up designated types It's not strictly necessary for source compatibility, since removing it just means that (in a not-officially-supported compiler mode) we will accept code we would previously have rejected. --- lib/Sema/TypeCheckDecl.cpp | 27 ++++--------------- .../operator_decl_designated_types.swift | 2 +- 2 files changed, 6 insertions(+), 23 deletions(-) diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 094a954a86907..d2c2c818db18e 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -1524,21 +1524,6 @@ TypeChecker::lookupPrecedenceGroup(DeclContext *dc, Identifier name, return PrecedenceGroupLookupResult(dc, name, std::move(groups)); } -static bool canResolveSingleNominalTypeDecl( - DeclContext *DC, SourceLoc loc, Identifier ident, ASTContext &Ctx) { - auto *TyR = new (Ctx) SimpleIdentTypeRepr(DeclNameLoc(loc), - DeclNameRef(ident)); - - TypeResolutionOptions options{TypeResolverContext::TypeAliasDecl}; - options |= TypeResolutionFlags::SilenceErrors; - const auto result = - TypeResolution::forInterface(DC, options, /*unboundTyOpener*/ nullptr, - /*placeholderHandler*/ nullptr) - .resolveType(TyR); - - return !result->hasError(); -} - /// Validate the given operator declaration. /// /// This establishes key invariants, such as an InfixOperatorDecl's @@ -1555,15 +1540,13 @@ OperatorPrecedenceGroupRequest::evaluate(Evaluator &evaluator, auto loc = IOD->getPrecedenceGroupLoc(); auto groups = TypeChecker::lookupPrecedenceGroup(dc, name, loc); - bool wasActuallyADesignatedType = !groups.hasResults() && - ctx.TypeCheckerOpts.EnableOperatorDesignatedTypes && - canResolveSingleNominalTypeDecl(dc, loc, name, ctx); - - if (!wasActuallyADesignatedType) + if (groups.hasResults() || + !ctx.TypeCheckerOpts.EnableOperatorDesignatedTypes) return groups.getSingleOrDiagnose(loc); - // Warn about the designated type, then fall through to look up - // DefaultPrecedence as though `PrecedenceGroupName` had never been set. + // We didn't find the named precedence group and designated types are + // enabled, so we will assume that it was actually a designated type. Warn + // and fall through as though `PrecedenceGroupName` had never been set. ctx.Diags.diagnose(IOD->getColonLoc(), diag::operator_decl_remove_designated_types) .fixItRemove({IOD->getColonLoc(), loc}); diff --git a/test/Parse/operator_decl_designated_types.swift b/test/Parse/operator_decl_designated_types.swift index 403d34fca27ab..ad8c78be2aa6d 100644 --- a/test/Parse/operator_decl_designated_types.swift +++ b/test/Parse/operator_decl_designated_types.swift @@ -30,7 +30,7 @@ prefix operator *^^ postfix operator ^^* infix operator **>> : UndeclaredPrecedence -// expected-error@-1 {{unknown precedence group 'UndeclaredPrecedence'}} +// expected-warning@-1 {{designated types are no longer used by the compiler}} {{21-43=}} infix operator **+> : MediumPrecedence, UndeclaredProtocol // expected-warning@-1 {{designated types are no longer used by the compiler}} {{39-59=}}