From 2052a4233f8892fe2895146126e37301e444d31a Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Thu, 8 May 2025 16:37:15 -0700 Subject: [PATCH 01/11] Use parseDeclNameRef in a few more places --- include/swift/AST/DiagnosticsParse.def | 4 +++ include/swift/Parse/Parser.h | 6 +++++ lib/Parse/ParseDecl.cpp | 34 ++++++++++++++------------ lib/Parse/ParseExpr.cpp | 13 ++++++++-- test/Parse/operator_decl.swift | 3 +++ 5 files changed, 43 insertions(+), 17 deletions(-) diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def index c0d4dd345dc72..4abe1e520e62f 100644 --- a/include/swift/AST/DiagnosticsParse.def +++ b/include/swift/AST/DiagnosticsParse.def @@ -2199,5 +2199,9 @@ ERROR(using_decl_invalid_specifier,PointsToFirstBadToken, ERROR(experimental_using_decl_disabled,PointsToFirstBadToken, "'using' is an experimental feature that is currently disabled", ()) +ERROR(impossible_parse,none, + "parser entered impossible state; please file a bug report with this " + "source file", ()) + #define UNDEFINE_DIAGNOSTIC_MACROS #include "DefineDiagnosticMacros.h" diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index 4d6c58ae69240..dcb6777d62492 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -1830,6 +1830,9 @@ class Parser { /// cases this doesn't actually make sense but we need to accept them for /// backwards compatibility. AllowLowercaseAndUppercaseSelf = 1 << 6, + + /// If passed, `$0` etc. are allowed. + AllowAnonymousParamNames = 1 << 7, }; using DeclNameOptions = OptionSet; @@ -1837,6 +1840,9 @@ class Parser { return DeclNameOptions(flag1) | flag2; } + /// Parse a declaration name that results in a `DeclNameRef` in the syntax + /// tree. + /// /// Without \c DeclNameFlag::AllowCompoundNames, parse an /// unqualified-decl-base-name. /// diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index e008914b2ad2c..c9149b1fa753a 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -10317,8 +10317,9 @@ 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, groupLoc; - Identifier groupName; + SourceLoc colonLoc; + DeclNameLoc groupLoc; + DeclNameRef groupName; if (Tok.is(tok::colon)) { colonLoc = consumeToken(); if (Tok.is(tok::code_complete)) { @@ -10331,9 +10332,9 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name, return makeParserCodeCompletionResult(); } - (void)parseIdentifier(groupName, groupLoc, - diag::operator_decl_expected_precedencegroup, - /*diagnoseDollarPrefix=*/false); + groupName = parseDeclNameRef(groupLoc, + diag::operator_decl_expected_precedencegroup, + {}); if (Context.TypeCheckerOpts.EnableOperatorDesignatedTypes) { // Designated types have been removed; consume the list (mainly for source @@ -10348,7 +10349,7 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name, // 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; + typesEndLoc = groupLoc.getEndLoc(); } while (Tok.isNot(tok::eof)) { @@ -10367,7 +10368,7 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name, } else { if (isPrefix || isPostfix) { // If we have nothing after the colon, then just remove the colon. - auto endLoc = groupLoc.isValid() ? groupLoc : colonLoc; + auto endLoc = groupLoc.isValid() ? groupLoc.getEndLoc() : colonLoc; diagnose(colonLoc, diag::precedencegroup_not_infix) .fixItRemove({colonLoc, endLoc}); } @@ -10378,6 +10379,7 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name, } // Diagnose deprecated operator body syntax `operator + { ... }`. + SourceLoc lastGoodLoc = PreviousLoc; SourceLoc lBraceLoc; if (consumeIf(tok::l_brace, lBraceLoc)) { if (isInfix && !Tok.is(tok::r_brace)) { @@ -10385,7 +10387,6 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name, } else { auto Diag = diagnose(lBraceLoc, diag::deprecated_operator_body); if (Tok.is(tok::r_brace)) { - SourceLoc lastGoodLoc = groupLoc.isValid() ? groupLoc : NameLoc; SourceLoc lastGoodLocEnd = Lexer::getLocForEndOfToken(SourceMgr, lastGoodLoc); SourceLoc rBraceEnd = Lexer::getLocForEndOfToken(SourceMgr, Tok.getLoc()); @@ -10407,7 +10408,8 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name, else res = new (Context) InfixOperatorDecl(CurDeclContext, OperatorLoc, Name, NameLoc, colonLoc, - groupName, groupLoc); + groupName.getBaseIdentifier(), + groupLoc.getBaseNameLoc()); diagnoseOperatorFixityAttributes(*this, Attributes, res); @@ -10626,14 +10628,16 @@ Parser::parseDeclPrecedenceGroup(ParseDeclOptions flags, return abortBody(/*hasCodeCompletion*/true); } - if (Tok.isNot(tok::identifier)) { - diagnose(Tok, diag::expected_precedencegroup_relation, attrName); + DeclNameLoc nameLoc; + auto name = parseDeclNameRef(nameLoc, + { diag::expected_precedencegroup_relation, + attrName }, + {}); + if (!name) { return abortBody(); } - Identifier name; - SourceLoc nameLoc = consumeIdentifier(name, - /*diagnoseDollarPrefix=*/false); - relations.push_back({nameLoc, name, nullptr}); + relations.push_back({nameLoc.getBaseNameLoc(), name.getBaseIdentifier(), + nullptr}); if (skipUnspacedCodeCompleteToken()) return abortBody(/*hasCodeCompletion*/true); diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index b6e94d0120d4b..739fe4e4d9e8d 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -2263,6 +2263,10 @@ DeclNameRef Parser::parseDeclNameRef(DeclNameLoc &loc, Identifier baseNameId; baseNameLoc = consumeIdentifier(baseNameId, /*diagnoseDollarPrefix=*/false); baseName = baseNameId; + } else if (flags.contains(DeclNameFlag::AllowAnonymousParamNames) + && Tok.is(tok::dollarident)) { + baseName = Context.getIdentifier(Tok.getText()); + baseNameLoc = consumeToken(tok::dollarident); } else if (flags.contains(DeclNameFlag::AllowOperators) && Tok.isAnyOperator()) { baseName = Context.getIdentifier(Tok.getText()); @@ -3047,8 +3051,13 @@ ParserResult Parser::parseExprClosure() { /// expr-anon-closure-argument: /// dollarident Expr *Parser::parseExprAnonClosureArg() { - StringRef Name = Tok.getText(); - SourceLoc Loc = consumeToken(tok::dollarident); + DeclNameLoc nameLoc; + DeclNameRef nameRef = + parseDeclNameRef(nameLoc, diag::impossible_parse, + DeclNameFlag::AllowAnonymousParamNames); + + StringRef Name = nameRef.getBaseIdentifier().str(); + SourceLoc Loc = nameLoc.getBaseNameLoc(); assert(Name[0] == '$' && "Not a dollarident"); // We know from the lexer that this is all-numeric. diff --git a/test/Parse/operator_decl.swift b/test/Parse/operator_decl.swift index 1daec13369d74..84e86053ef9d8 100644 --- a/test/Parse/operator_decl.swift +++ b/test/Parse/operator_decl.swift @@ -83,6 +83,9 @@ precedencegroup D { precedencegroup E { higherThan: } // expected-error {{expected name of related precedence group after 'higherThan'}} +precedencegroup EE { + higherThan: E, +} // expected-error {{expected name of related precedence group after 'higherThan'}} precedencegroup F { higherThan: A, B, C From 29038353ed435b01d6bb6f5ac829eb490d22b613 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Thu, 8 May 2025 21:04:27 -0700 Subject: [PATCH 02/11] [NFC] Add DeclNameLoc to specialize/dynamicReplacement --- include/swift/AST/ASTBridging.h | 23 ++++++----- include/swift/AST/Attr.h | 45 ++++++++++++++++------ include/swift/Parse/Parser.h | 2 +- lib/AST/Attr.cpp | 34 ++++++++++------ lib/AST/Bridging/DeclAttributeBridging.cpp | 17 +++++--- lib/ASTGen/Sources/ASTGen/DeclAttrs.swift | 13 ++++--- lib/Parse/ParseDecl.cpp | 39 +++++++++---------- 7 files changed, 109 insertions(+), 64 deletions(-) diff --git a/include/swift/AST/ASTBridging.h b/include/swift/AST/ASTBridging.h index 99f9d05e0eef3..4ac2b1657c90f 100644 --- a/include/swift/AST/ASTBridging.h +++ b/include/swift/AST/ASTBridging.h @@ -941,11 +941,12 @@ BridgedDocumentationAttr BridgedDocumentationAttr_createParsed( SWIFT_NAME( "BridgedDynamicReplacementAttr.createParsed(_:atLoc:attrNameLoc:lParenLoc:" - "replacedFunction:rParenLoc:)") + "replacedFunction:replacedFunctionLoc:rParenLoc:)") BridgedDynamicReplacementAttr BridgedDynamicReplacementAttr_createParsed( - BridgedASTContext cContext, swift::SourceLoc atLoc, - swift::SourceLoc attrNameLoc, swift::SourceLoc lParenLoc, - BridgedDeclNameRef cReplacedFunction, swift::SourceLoc rParenLoc); + BridgedASTContext cContext, swift::SourceLoc cAtLoc, + swift::SourceLoc cAttrNameLoc, swift::SourceLoc cLParenLoc, + BridgedDeclNameRef cReplacedFunction, + BridgedDeclNameLoc cReplacedFunctionLoc, swift::SourceLoc cRParenLoc); SWIFT_NAME("BridgedEffectsAttr.createParsed(_:atLoc:range:effectKind:)") BridgedEffectsAttr BridgedEffectsAttr_createParsed( @@ -1276,22 +1277,24 @@ enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedSpecializationKind : uint8_t { }; SWIFT_NAME("BridgedSpecializeAttr.createParsed(_:atLoc:range:whereClause:" - "exported:kind:taretFunction:spiGroups:availableAttrs:)") + "exported:kind:targetFunction:targetFunctionLoc:spiGroups:" + "availableAttrs:)") BridgedSpecializeAttr BridgedSpecializeAttr_createParsed( BridgedASTContext cContext, swift::SourceLoc atLoc, swift::SourceRange range, BridgedNullableTrailingWhereClause cWhereClause, bool exported, BridgedSpecializationKind cKind, - BridgedDeclNameRef cTargetFunction, BridgedArrayRef cSPIGroups, - BridgedArrayRef cAvailableAttrs); + BridgedDeclNameRef cTargetFunction, BridgedDeclNameLoc cTargetFunctionLoc, + BridgedArrayRef cSPIGroups, BridgedArrayRef cAvailableAttrs); SWIFT_NAME("BridgedSpecializedAttr.createParsed(_:atLoc:range:whereClause:" - "exported:kind:taretFunction:spiGroups:availableAttrs:)") + "exported:kind:targetFunction:targetFunctionLoc:spiGroups:" + "availableAttrs:)") BridgedSpecializedAttr BridgedSpecializedAttr_createParsed( BridgedASTContext cContext, swift::SourceLoc atLoc, swift::SourceRange range, BridgedNullableTrailingWhereClause cWhereClause, bool exported, BridgedSpecializationKind cKind, - BridgedDeclNameRef cTargetFunction, BridgedArrayRef cSPIGroups, - BridgedArrayRef cAvailableAttrs); + BridgedDeclNameRef cTargetFunction, BridgedDeclNameLoc cTargetFunctionLoc, + BridgedArrayRef cSPIGroups, BridgedArrayRef cAvailableAttrs); SWIFT_NAME( "BridgedSPIAccessControlAttr.createParsed(_:atLoc:range:spiGroupName:)") diff --git a/include/swift/AST/Attr.h b/include/swift/AST/Attr.h index fc94b967ac3cf..4fce6b047069d 100644 --- a/include/swift/AST/Attr.h +++ b/include/swift/AST/Attr.h @@ -1253,19 +1253,22 @@ class DynamicReplacementAttr final friend class DynamicallyReplacedDeclRequest; DeclNameRef ReplacedFunctionName; + DeclNameLoc ReplacedFunctionNameLoc; LazyMemberLoader *Resolver = nullptr; uint64_t ResolverContextData; /// Create an @_dynamicReplacement(for:) attribute written in the source. DynamicReplacementAttr(SourceLoc atLoc, SourceRange baseRange, DeclNameRef replacedFunctionName, + DeclNameLoc replacedFunctionNameLoc, SourceRange parenRange); DynamicReplacementAttr(DeclNameRef name, AbstractFunctionDecl *f) : DeclAttribute(DeclAttrKind::DynamicReplacement, SourceLoc(), SourceRange(), /*Implicit=*/false), - ReplacedFunctionName(name), Resolver(nullptr), ResolverContextData(0) { + ReplacedFunctionName(name), ReplacedFunctionNameLoc(), + Resolver(nullptr), ResolverContextData(0) { Bits.DynamicReplacementAttr.HasTrailingLocationInfo = false; } @@ -1274,8 +1277,8 @@ class DynamicReplacementAttr final : DeclAttribute(DeclAttrKind::DynamicReplacement, SourceLoc(), SourceRange(), /*Implicit=*/false), - ReplacedFunctionName(name), Resolver(Resolver), - ResolverContextData(Data) { + ReplacedFunctionName(name), ReplacedFunctionNameLoc(), + Resolver(Resolver), ResolverContextData(Data) { Bits.DynamicReplacementAttr.HasTrailingLocationInfo = false; } @@ -1296,7 +1299,8 @@ class DynamicReplacementAttr final public: static DynamicReplacementAttr * create(ASTContext &Context, SourceLoc AtLoc, SourceLoc DynReplLoc, - SourceLoc LParenLoc, DeclNameRef replacedFunction, SourceLoc RParenLoc); + SourceLoc LParenLoc, DeclNameRef replacedFunction, + DeclNameLoc replacedFunctionNameLoc, SourceLoc RParenLoc); static DynamicReplacementAttr *create(ASTContext &ctx, DeclNameRef replacedFunction, @@ -1311,6 +1315,10 @@ class DynamicReplacementAttr final return ReplacedFunctionName; } + DeclNameLoc getReplacedFunctionNameLoc() const { + return ReplacedFunctionNameLoc; + } + /// Retrieve the location of the opening parentheses, if there is one. SourceLoc getLParenLoc() const; @@ -1800,6 +1808,7 @@ class AbstractSpecializeAttr GenericSignature specializedSignature; DeclNameRef targetFunctionName; + DeclNameLoc targetFunctionNameLoc; LazyMemberLoader *resolver = nullptr; uint64_t resolverContextData; size_t numSPIGroups; @@ -1812,7 +1821,9 @@ class AbstractSpecializeAttr TrailingWhereClause *clause, bool exported, SpecializationKind kind, GenericSignature specializedSignature, - DeclNameRef targetFunctionName, ArrayRef spiGroups, + DeclNameRef targetFunctionName, + DeclNameLoc targetFunctionNameLoc, + ArrayRef spiGroups, ArrayRef availabilityAttrs, size_t typeErasedParamsCount); @@ -1896,6 +1907,10 @@ class AbstractSpecializeAttr return targetFunctionName; } + DeclNameLoc getTargetFunctionNameLoc() const { + return targetFunctionNameLoc; + } + /// \p forDecl is the value decl that the attribute belongs to. ValueDecl *getTargetFunctionDecl(const ValueDecl *forDecl) const; @@ -1925,19 +1940,23 @@ class SpecializeAttr final : public AbstractSpecializeAttr, TrailingWhereClause *clause, bool exported, SpecializationKind kind, GenericSignature specializedSignature, - DeclNameRef targetFunctionName, ArrayRef spiGroups, + DeclNameRef targetFunctionName, + DeclNameLoc targetFunctionNameLoc, + ArrayRef spiGroups, ArrayRef availabilityAttrs, size_t typeErasedParamsCount) : AbstractSpecializeAttr(DeclAttrKind::Specialize, atLoc, Range, clause, exported, kind, specializedSignature, targetFunctionName, - spiGroups, availabilityAttrs, typeErasedParamsCount) {} + targetFunctionNameLoc, spiGroups, availabilityAttrs, + typeErasedParamsCount) {} public: static SpecializeAttr * create(ASTContext &Ctx, SourceLoc atLoc, SourceRange Range, TrailingWhereClause *clause, bool exported, SpecializationKind kind, - DeclNameRef targetFunctionName, ArrayRef spiGroups, + DeclNameRef targetFunctionName, DeclNameLoc targetFunctionNameLoc, + ArrayRef spiGroups, ArrayRef availabilityAttrs, GenericSignature specializedSignature = nullptr); @@ -1981,19 +2000,23 @@ class SpecializedAttr final : public AbstractSpecializeAttr , TrailingWhereClause *clause, bool exported, SpecializationKind kind, GenericSignature specializedSignature, - DeclNameRef targetFunctionName, ArrayRef spiGroups, + DeclNameRef targetFunctionName, + DeclNameLoc targetFunctionNameLoc, + ArrayRef spiGroups, ArrayRef availabilityAttrs, size_t typeErasedParamsCount) : AbstractSpecializeAttr(DeclAttrKind::Specialized, atLoc, Range, clause, exported, kind, specializedSignature, targetFunctionName, - spiGroups, availabilityAttrs, typeErasedParamsCount) {} + targetFunctionNameLoc, spiGroups, availabilityAttrs, + typeErasedParamsCount) {} public: static SpecializedAttr * create(ASTContext &Ctx, SourceLoc atLoc, SourceRange Range, TrailingWhereClause *clause, bool exported, SpecializationKind kind, - DeclNameRef targetFunctionName, ArrayRef spiGroups, + DeclNameRef targetFunctionName, DeclNameLoc targetFunctionNameLoc, + ArrayRef spiGroups, ArrayRef availabilityAttrs, GenericSignature specializedSignature = nullptr); diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index dcb6777d62492..31e32a7ad43f9 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -1063,7 +1063,7 @@ class Parser { std::optional &Exported, std::optional &Kind, TrailingWhereClause *&TrailingWhereClause, DeclNameRef &targetFunction, - AvailabilityRange *SILAvailability, + DeclNameLoc &targetFunctionLoc, AvailabilityRange *SILAvailability, SmallVectorImpl &spiGroups, SmallVectorImpl &availableAttrs, llvm::function_ref parseSILTargetName, diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp index 0e0daf7154bfa..16484752d1bb7 100644 --- a/lib/AST/Attr.cpp +++ b/lib/AST/Attr.cpp @@ -2118,10 +2118,11 @@ PrivateImportAttr *PrivateImportAttr::create(ASTContext &Ctxt, SourceLoc AtLoc, DynamicReplacementAttr::DynamicReplacementAttr(SourceLoc atLoc, SourceRange baseRange, DeclNameRef name, + DeclNameLoc nameLoc, SourceRange parenRange) : DeclAttribute(DeclAttrKind::DynamicReplacement, atLoc, baseRange, /*Implicit=*/false), - ReplacedFunctionName(name) { + ReplacedFunctionName(name), ReplacedFunctionNameLoc(nameLoc) { Bits.DynamicReplacementAttr.HasTrailingLocationInfo = true; getTrailingLocations()[0] = parenRange.Start; getTrailingLocations()[1] = parenRange.End; @@ -2130,11 +2131,12 @@ DynamicReplacementAttr::DynamicReplacementAttr(SourceLoc atLoc, DynamicReplacementAttr * DynamicReplacementAttr::create(ASTContext &Ctx, SourceLoc AtLoc, SourceLoc DynReplLoc, SourceLoc LParenLoc, - DeclNameRef ReplacedFunction, SourceLoc RParenLoc) { + DeclNameRef ReplacedFunction, + DeclNameLoc nameLoc, SourceLoc RParenLoc) { void *mem = Ctx.Allocate(totalSizeToAlloc(2), alignof(DynamicReplacementAttr)); return new (mem) DynamicReplacementAttr( - AtLoc, SourceRange(DynReplLoc, RParenLoc), ReplacedFunction, + AtLoc, SourceRange(DynReplLoc, RParenLoc), ReplacedFunction, nameLoc, SourceRange(LParenLoc, RParenLoc)); } @@ -2490,12 +2492,15 @@ AbstractSpecializeAttr::AbstractSpecializeAttr(DeclAttrKind DK, SpecializationKind kind, GenericSignature specializedSignature, DeclNameRef targetFunctionName, + DeclNameLoc targetFunctionNameLoc, ArrayRef spiGroups, ArrayRef availableAttrs, size_t typeErasedParamsCount) : DeclAttribute(DK, atLoc, range, /*Implicit=*/clause == nullptr), trailingWhereClause(clause), specializedSignature(specializedSignature), - targetFunctionName(targetFunctionName), numSPIGroups(spiGroups.size()), + targetFunctionName(targetFunctionName), + targetFunctionNameLoc(targetFunctionNameLoc), + numSPIGroups(spiGroups.size()), numAvailableAttrs(availableAttrs.size()), numTypeErasedParams(typeErasedParamsCount), typeErasedParamsInitialized(false) { @@ -2517,6 +2522,7 @@ SpecializeAttr *SpecializeAttr::create(ASTContext &Ctx, SourceLoc atLoc, TrailingWhereClause *clause, bool exported, SpecializationKind kind, DeclNameRef targetFunctionName, + DeclNameLoc targetFunctionNameLoc, ArrayRef spiGroups, ArrayRef availableAttrs, GenericSignature specializedSignature) { @@ -2540,7 +2546,8 @@ SpecializeAttr *SpecializeAttr::create(ASTContext &Ctx, SourceLoc atLoc, return new (mem) SpecializeAttr(atLoc, range, clause, exported, kind, specializedSignature, - targetFunctionName, spiGroups, availableAttrs, typeErasedParamsCount); + targetFunctionName, targetFunctionNameLoc, spiGroups, + availableAttrs, typeErasedParamsCount); } SpecializeAttr *SpecializeAttr::create(ASTContext &ctx, bool exported, @@ -2553,8 +2560,8 @@ SpecializeAttr *SpecializeAttr::create(ASTContext &ctx, bool exported, spiGroups.size(), availableAttrs.size(), 0); void *mem = ctx.Allocate(size, alignof(SpecializeAttr)); return new (mem) SpecializeAttr( - SourceLoc(), SourceRange(), nullptr, exported, kind, - specializedSignature, targetFunctionName, spiGroups, availableAttrs, 0); + SourceLoc(), SourceRange(), nullptr, exported, kind, specializedSignature, + targetFunctionName, DeclNameLoc(), spiGroups, availableAttrs, 0); } SpecializeAttr *SpecializeAttr::create( @@ -2568,7 +2575,8 @@ SpecializeAttr *SpecializeAttr::create( void *mem = ctx.Allocate(size, alignof(SpecializeAttr)); auto *attr = new (mem) SpecializeAttr( SourceLoc(), SourceRange(), nullptr, exported, kind, specializedSignature, - targetFunctionName, spiGroups, availableAttrs, typeErasedParams.size()); + targetFunctionName, DeclNameLoc(), spiGroups, availableAttrs, + typeErasedParams.size()); attr->setTypeErasedParams(typeErasedParams); attr->setResolver(resolver, data); return attr; @@ -2581,6 +2589,7 @@ SpecializedAttr *SpecializedAttr::create(ASTContext &Ctx, SourceLoc atLoc, TrailingWhereClause *clause, bool exported, SpecializationKind kind, DeclNameRef targetFunctionName, + DeclNameLoc targetFunctionNameLoc, ArrayRef spiGroups, ArrayRef availableAttrs, GenericSignature specializedSignature) { @@ -2604,7 +2613,8 @@ SpecializedAttr *SpecializedAttr::create(ASTContext &Ctx, SourceLoc atLoc, return new (mem) SpecializedAttr(atLoc, range, clause, exported, kind, specializedSignature, - targetFunctionName, spiGroups, availableAttrs, typeErasedParamsCount); + targetFunctionName, targetFunctionNameLoc, spiGroups, + availableAttrs, typeErasedParamsCount); } SpecializedAttr *SpecializedAttr::create(ASTContext &ctx, bool exported, @@ -2618,7 +2628,8 @@ SpecializedAttr *SpecializedAttr::create(ASTContext &ctx, bool exported, void *mem = ctx.Allocate(size, alignof(SpecializedAttr)); return new (mem) SpecializedAttr( SourceLoc(), SourceRange(), nullptr, exported, kind, - specializedSignature, targetFunctionName, spiGroups, availableAttrs, 0); + specializedSignature, targetFunctionName, DeclNameLoc(), spiGroups, + availableAttrs, 0); } SpecializedAttr *SpecializedAttr::create( @@ -2632,7 +2643,8 @@ SpecializedAttr *SpecializedAttr::create( void *mem = ctx.Allocate(size, alignof(SpecializedAttr)); auto *attr = new (mem) SpecializedAttr( SourceLoc(), SourceRange(), nullptr, exported, kind, specializedSignature, - targetFunctionName, spiGroups, availableAttrs, typeErasedParams.size()); + targetFunctionName, DeclNameLoc(), spiGroups, availableAttrs, + typeErasedParams.size()); attr->setTypeErasedParams(typeErasedParams); attr->setResolver(resolver, data); return attr; diff --git a/lib/AST/Bridging/DeclAttributeBridging.cpp b/lib/AST/Bridging/DeclAttributeBridging.cpp index 0803748c5d9e2..5adcd07d67121 100644 --- a/lib/AST/Bridging/DeclAttributeBridging.cpp +++ b/lib/AST/Bridging/DeclAttributeBridging.cpp @@ -258,10 +258,11 @@ BridgedDifferentiableAttr BridgedDifferentiableAttr_createParsed( BridgedDynamicReplacementAttr BridgedDynamicReplacementAttr_createParsed( BridgedASTContext cContext, SourceLoc atLoc, SourceLoc attrNameLoc, SourceLoc lParenLoc, BridgedDeclNameRef cReplacedFunction, - SourceLoc rParenLoc) { + BridgedDeclNameLoc cReplacedFunctionLoc, swift::SourceLoc rParenLoc) { return DynamicReplacementAttr::create( cContext.unbridged(), atLoc, attrNameLoc, lParenLoc, - cReplacedFunction.unbridged(), rParenLoc); + cReplacedFunction.unbridged(), cReplacedFunctionLoc.unbridged(), + rParenLoc); } BridgedDocumentationAttr BridgedDocumentationAttr_createParsed( @@ -686,7 +687,8 @@ BridgedSpecializeAttr BridgedSpecializeAttr_createParsed( BridgedASTContext cContext, SourceLoc atLoc, SourceRange range, BridgedNullableTrailingWhereClause cWhereClause, bool exported, BridgedSpecializationKind cKind, BridgedDeclNameRef cTargetFunction, - BridgedArrayRef cSPIGroups, BridgedArrayRef cAvailableAttrs) { + BridgedDeclNameLoc cTargetFunctionLoc, BridgedArrayRef cSPIGroups, + BridgedArrayRef cAvailableAttrs) { auto spiGroups = cSPIGroups.unbridged(); SmallVector availableAttrs; for (auto bridging : cAvailableAttrs.unbridged()) @@ -694,14 +696,16 @@ BridgedSpecializeAttr BridgedSpecializeAttr_createParsed( return SpecializeAttr::create( cContext.unbridged(), atLoc, range, cWhereClause.unbridged(), exported, - unbridge(cKind), cTargetFunction.unbridged(), spiGroups, availableAttrs); + unbridge(cKind), cTargetFunction.unbridged(), + cTargetFunctionLoc.unbridged(), spiGroups, availableAttrs); } BridgedSpecializedAttr BridgedSpecializedAttr_createParsed( BridgedASTContext cContext, SourceLoc atLoc, SourceRange range, BridgedNullableTrailingWhereClause cWhereClause, bool exported, BridgedSpecializationKind cKind, BridgedDeclNameRef cTargetFunction, - BridgedArrayRef cSPIGroups, BridgedArrayRef cAvailableAttrs) { + BridgedDeclNameLoc cTargetFunctionLoc, BridgedArrayRef cSPIGroups, + BridgedArrayRef cAvailableAttrs) { auto spiGroups = cSPIGroups.unbridged(); SmallVector availableAttrs; for (auto bridging : cAvailableAttrs.unbridged()) @@ -709,7 +713,8 @@ BridgedSpecializedAttr BridgedSpecializedAttr_createParsed( return SpecializedAttr::create( cContext.unbridged(), atLoc, range, cWhereClause.unbridged(), exported, - unbridge(cKind), cTargetFunction.unbridged(), spiGroups, availableAttrs); + unbridge(cKind), cTargetFunction.unbridged(), + cTargetFunctionLoc.unbridged(), spiGroups, availableAttrs); } BridgedSPIAccessControlAttr diff --git a/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift b/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift index f6a5a96aed226..db463abab5347 100644 --- a/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift +++ b/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift @@ -768,6 +768,7 @@ extension ASTGenVisitor { attrNameLoc: self.generateSourceLoc(node.attributeName), lParenLoc: self.generateSourceLoc(node.leftParen), replacedFunction: replacedFunction.name, + replacedFunctionLoc: replacedFunction.loc, rParenLoc: self.generateSourceLoc(node.rightParen) ) } @@ -1909,7 +1910,7 @@ extension ASTGenVisitor { let exported: Bool? = nil let kind: BridgedSpecializationKind? = nil var whereClause: BridgedTrailingWhereClause? = nil - let targetFunction: BridgedDeclNameRef? = nil + let targetFunction: (name: BridgedDeclNameRef, loc: BridgedDeclNameLoc)? = nil let spiGroups: [Identifier] = [] let availableAttrs: [BridgedAvailableAttr] = [] @@ -1922,7 +1923,8 @@ extension ASTGenVisitor { whereClause: whereClause.asNullable, exported: exported ?? false, kind: kind ?? .full, - taretFunction: targetFunction ?? BridgedDeclNameRef(), + targetFunction: targetFunction?.name ?? BridgedDeclNameRef(), + targetFunctionLoc: targetFunction?.loc ?? BridgedDeclNameLoc(), spiGroups: spiGroups.lazy.bridgedArray(in: self), availableAttrs: availableAttrs.lazy.bridgedArray(in: self) ) @@ -1942,7 +1944,7 @@ extension ASTGenVisitor { var exported: Bool? var kind: BridgedSpecializationKind? = nil var whereClause: BridgedTrailingWhereClause? = nil - var targetFunction: BridgedDeclNameRef? = nil + var targetFunction: (name: BridgedDeclNameRef, loc: BridgedDeclNameLoc)? var spiGroups: [Identifier] = [] var availableAttrs: [BridgedAvailableAttr] = [] @@ -1954,7 +1956,7 @@ extension ASTGenVisitor { if targetFunction != nil { // TODO: Diangose. } - targetFunction = self.generateDeclNameRef(declReferenceExpr: arg.declName).name + targetFunction = self.generateDeclNameRef(declReferenceExpr: arg.declName) case .specializeAvailabilityArgument(let arg): availableAttrs = self.generateAvailableAttr( atLoc: self.generateSourceLoc(arg.availabilityLabel), @@ -2018,7 +2020,8 @@ extension ASTGenVisitor { whereClause: whereClause.asNullable, exported: exported ?? false, kind: kind ?? .full, - taretFunction: targetFunction ?? BridgedDeclNameRef(), + targetFunction: targetFunction?.name ?? BridgedDeclNameRef(), + targetFunctionLoc: targetFunction?.loc ?? BridgedDeclNameLoc(), spiGroups: spiGroups.lazy.bridgedArray(in: self), availableAttrs: availableAttrs.lazy.bridgedArray(in: self) ) diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index c9149b1fa753a..b280e0588f44b 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -564,8 +564,8 @@ bool Parser::parseSpecializeAttributeArguments( std::optional &Exported, std::optional &Kind, swift::TrailingWhereClause *&TrailingWhereClause, - DeclNameRef &targetFunction, AvailabilityRange *SILAvailability, - SmallVectorImpl &spiGroups, + DeclNameRef &targetFunction, DeclNameLoc &targetFunctionLoc, + AvailabilityRange *SILAvailability, SmallVectorImpl &spiGroups, SmallVectorImpl &availableAttrs, llvm::function_ref parseSILTargetName, llvm::function_ref parseSILSIPModule) { @@ -677,9 +677,8 @@ bool Parser::parseSpecializeAttributeArguments( } if (ParamLabel == "target") { if (!parseSILTargetName(*this)) { - DeclNameLoc loc; targetFunction = parseDeclNameRef( - loc, diag::attr_specialize_expected_function, + targetFunctionLoc, diag::attr_specialize_expected_function, DeclNameFlag::AllowZeroArgCompoundNames | DeclNameFlag::AllowKeywordsUsingSpecialNames | DeclNameFlag::AllowOperators | @@ -893,13 +892,14 @@ bool Parser::parseSpecializeAttribute( TrailingWhereClause *trailingWhereClause = nullptr; DeclNameRef targetFunction; + DeclNameLoc targetFunctionLoc; SmallVector spiGroups; SmallVector availableAttrs; if (!parseSpecializeAttributeArguments( ClosingBrace, isPublic, DiscardAttribute, exported, kind, trailingWhereClause, - targetFunction, SILAvailability, spiGroups, availableAttrs, - parseSILTargetName, parseSILSIPModule)) { + targetFunction, targetFunctionLoc, SILAvailability, spiGroups, + availableAttrs, parseSILTargetName, parseSILSIPModule)) { return false; } @@ -931,13 +931,13 @@ bool Parser::parseSpecializeAttribute( Attr = SpecializedAttr::create(Context, AtLoc, SourceRange(Loc, rParenLoc), trailingWhereClause, exported.value(), - kind.value(), targetFunction, spiGroups, - availableAttrs); + kind.value(), targetFunction, + targetFunctionLoc, spiGroups, availableAttrs); else Attr = SpecializeAttr::create(Context, AtLoc, SourceRange(Loc, rParenLoc), trailingWhereClause, exported.value(), - kind.value(), targetFunction, spiGroups, - availableAttrs); + kind.value(), targetFunction, + targetFunctionLoc, spiGroups, availableAttrs); return true; } @@ -3592,6 +3592,7 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc LParenLoc = consumeAttributeLParen(); DeclNameRef replacedFunction; + DeclNameLoc replacedFunctionLoc; { // Parse 'for'. if (Tok.getText() != "for") { @@ -3606,15 +3607,12 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes, return makeParserSuccess(); } consumeToken(tok::colon); - { - DeclNameLoc loc; - replacedFunction = parseDeclNameRef( - loc, diag::attr_dynamic_replacement_expected_function, - DeclNameFlag::AllowZeroArgCompoundNames | - DeclNameFlag::AllowKeywordsUsingSpecialNames | - DeclNameFlag::AllowOperators | - DeclNameFlag::AllowLowercaseAndUppercaseSelf); - } + replacedFunction = parseDeclNameRef( + replacedFunctionLoc, diag::attr_dynamic_replacement_expected_function, + DeclNameFlag::AllowZeroArgCompoundNames | + DeclNameFlag::AllowKeywordsUsingSpecialNames | + DeclNameFlag::AllowOperators | + DeclNameFlag::AllowLowercaseAndUppercaseSelf); } // Parse the matching ')'. @@ -3628,7 +3626,8 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes, DynamicReplacementAttr *attr = DynamicReplacementAttr::create( - Context, AtLoc, Loc, LParenLoc, replacedFunction, RParenLoc); + Context, AtLoc, Loc, LParenLoc, replacedFunction, replacedFunctionLoc, + RParenLoc); Attributes.add(attr); break; } From 968111790b07e5f5952595f20e1c9ac1f6d12927 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Thu, 7 Aug 2025 17:34:49 -0700 Subject: [PATCH 03/11] [NFC] Make ASTDumper more defensive Try to avoid calling `getSourceRange()` on a decl where that will form an invalid range. --- lib/AST/ASTDumper.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index cf0772419ed15..e52c1953a9c9b 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -1970,7 +1970,8 @@ namespace { printFlag(!ABIRoleInfo(D).providesAPI(), "abi_only"); - printSourceRange(D->getSourceRange(), &D->getASTContext()); + if (D->getStartLoc().isValid() && D->getEndLoc().isValid()) + printSourceRange(D->getSourceRange(), &D->getASTContext()); printFlag(D->TrailingSemiLoc.isValid(), "trailing_semi", DeclModifierColor); From b59d3886f56300b7f4df985ab19b53746f8dfb7f Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Mon, 11 Aug 2025 17:18:03 -0700 Subject: [PATCH 04/11] [NFC] Tweak source loc of @_implements error When closing paren is missing, point at the location where it should be found, not the opening paren. --- lib/Parse/ParseDecl.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index b280e0588f44b..7f2098219cd07 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1148,9 +1148,10 @@ Parser::parseImplementsAttribute(SourceLoc AtLoc, SourceLoc Loc) { } SourceLoc rParenLoc; - if (!consumeIf(tok::r_paren, rParenLoc)) { - diagnose(lParenLoc, diag::attr_expected_rparen, AttrName, - /*DeclModifier=*/false); + if (parseMatchingToken(tok::r_paren, rParenLoc, + { diag::attr_expected_rparen, + { AttrName, /*DeclModifier=*/false } }, + lParenLoc)) { Status.setIsParseError(); } From 3cf4244abb680a52e341479cec41a6cf9d66b015 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Mon, 11 Aug 2025 18:39:28 -0700 Subject: [PATCH 05/11] [NFC] Make pattern type checking more defensive --- lib/Sema/TypeCheckPattern.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index 52d8705d7b072..e2ce3f20b5774 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -1591,8 +1591,9 @@ Pattern *TypeChecker::coercePatternToType( parentTy->getAnyNominal() == type->getAnyNominal()) { enumTy = type; } else { - diags.diagnose(EEP->getLoc(), diag::ambiguous_enum_pattern_type, - parentTy, type); + if (!type->hasError()) + diags.diagnose(EEP->getLoc(), diag::ambiguous_enum_pattern_type, + parentTy, type); return nullptr; } } @@ -1698,15 +1699,17 @@ Pattern *TypeChecker::coercePatternToType( Type elementType = type->getOptionalObjectType(); if (elementType.isNull()) { - auto diagID = diag::optional_element_pattern_not_valid_type; - SourceLoc loc = OP->getQuestionLoc(); - // Produce tailored diagnostic for if/let and other conditions. - if (OP->isImplicit()) { - diagID = diag::condition_optional_element_pattern_not_valid_type; - loc = OP->getLoc(); - } + if (!type->hasError()) { + auto diagID = diag::optional_element_pattern_not_valid_type; + SourceLoc loc = OP->getQuestionLoc(); + // Produce tailored diagnostic for if/let and other conditions. + if (OP->isImplicit()) { + diagID = diag::condition_optional_element_pattern_not_valid_type; + loc = OP->getLoc(); + } - diags.diagnose(loc, diagID, type); + diags.diagnose(loc, diagID, type); + } return nullptr; } From 679c927aca2e1882cdf06b7f138d0495d021ef97 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Wed, 13 Aug 2025 14:10:15 -0700 Subject: [PATCH 06/11] [NFC-ish] Do lookahead without llvm::function_ref --- include/swift/Parse/Parser.h | 5 ++--- lib/Parse/ParseDecl.cpp | 2 +- lib/Parse/ParsePattern.cpp | 4 ++-- test/expr/postfix/dot/numeric_literals.swift | 9 +++++++++ 4 files changed, 14 insertions(+), 6 deletions(-) create mode 100644 test/expr/postfix/dot/numeric_literals.swift diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index 31e32a7ad43f9..218617d70b536 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -487,9 +487,8 @@ class Parser { /// \returns the value returned by \c f /// \note When calling, you may need to specify the \c Val type /// explicitly as a type parameter. - template - Val lookahead(unsigned char K, - llvm::function_ref f) { + template + decltype(auto) lookahead(unsigned char K, Fn f) { CancellableBacktrackingScope backtrackScope(*this); for (unsigned char i = 0; i < K; ++i) diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 7f2098219cd07..463e3b832a8c3 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3029,7 +3029,7 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes, // Backwards support for @cdecl("stringId"). Remove before enabling in // production so we accept only the identifier format. - lookahead(1, [&](CancellableBacktrackingScope &) { + lookahead(1, [&](CancellableBacktrackingScope &) { return Tok.isNot(tok::string_literal); })) { diff --git a/lib/Parse/ParsePattern.cpp b/lib/Parse/ParsePattern.cpp index 2644052959abb..0d990c81ca5c3 100644 --- a/lib/Parse/ParsePattern.cpp +++ b/lib/Parse/ParsePattern.cpp @@ -122,7 +122,7 @@ bool Parser::startsParameterName(bool isClosure) { // contextual keywords, so look ahead one more token (two total) and see // if we have a ':' that would // indicate that this is an argument label. - return lookahead(2, [&](CancellableBacktrackingScope &) { + return lookahead(2, [&](CancellableBacktrackingScope &) { if (Tok.is(tok::colon)) return true; // isolated : @@ -235,7 +235,7 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc, // is this token the identifier of an argument label? `inout` is a // reserved keyword but the other modifiers are not. if (!Tok.is(tok::kw_inout)) { - bool partOfArgumentLabel = lookahead(1, [&](CancellableBacktrackingScope &) { + bool partOfArgumentLabel = lookahead(1, [&](CancellableBacktrackingScope &) { if (Tok.is(tok::colon)) return true; // isolated : diff --git a/test/expr/postfix/dot/numeric_literals.swift b/test/expr/postfix/dot/numeric_literals.swift new file mode 100644 index 0000000000000..3675928a86497 --- /dev/null +++ b/test/expr/postfix/dot/numeric_literals.swift @@ -0,0 +1,9 @@ +// RUN: %target-typecheck-verify-swift + +func fn() { + _ = 1.description + _ = 1.5.description + + print(1.description) + print(1.5.description) +} From d2e48674443873b54938694b09f8afdbe39dec79 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Wed, 13 Aug 2025 14:32:49 -0700 Subject: [PATCH 07/11] [NFC] Add tok::colon_colon to parser --- include/swift/AST/TokenKinds.def | 1 + include/swift/Parse/Parser.h | 11 ++++++ lib/Parse/Lexer.cpp | 8 +++- lib/Parse/ParseDecl.cpp | 8 ++-- lib/Parse/ParseExpr.cpp | 38 ++++++++++++++----- .../module_selector.swift | 0 6 files changed, 51 insertions(+), 15 deletions(-) rename test/{NameLookup => Parse}/module_selector.swift (100%) diff --git a/include/swift/AST/TokenKinds.def b/include/swift/AST/TokenKinds.def index 11fc1469cb32d..f7cb378522b96 100644 --- a/include/swift/AST/TokenKinds.def +++ b/include/swift/AST/TokenKinds.def @@ -203,6 +203,7 @@ PUNCTUATOR(period_prefix, ".") PUNCTUATOR(comma, ",") PUNCTUATOR(ellipsis, "...") PUNCTUATOR(colon, ":") +PUNCTUATOR(colon_colon, "::") PUNCTUATOR(semi, ";") PUNCTUATOR(equal, "=") PUNCTUATOR(at_sign, "@") diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index 218617d70b536..639e00c1880d0 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -771,6 +771,17 @@ class Parser { consumeStartingCharacterOfCurrentToken(tok Kind = tok::oper_binary_unspaced, size_t Len = 1); + /// If the next token is \c tok::colon, consume it; if the next token is + /// \c tok::colon_colon, split it into two \c tok::colons and consume the + /// first; otherwise, do nothing and return false. + bool consumeIfColonSplittingDoubles() { + if (!Tok.isAny(tok::colon, tok::colon_colon)) + return false; + + consumeStartingCharacterOfCurrentToken(tok::colon); + return true; + } + //===--------------------------------------------------------------------===// // Primitive Parsing diff --git a/lib/Parse/Lexer.cpp b/lib/Parse/Lexer.cpp index 4529466531afd..049d521eef6c5 100644 --- a/lib/Parse/Lexer.cpp +++ b/lib/Parse/Lexer.cpp @@ -2762,9 +2762,15 @@ void Lexer::lexImpl() { case ',': return formToken(tok::comma, TokStart); case ';': return formToken(tok::semi, TokStart); - case ':': return formToken(tok::colon, TokStart); case '\\': return formToken(tok::backslash, TokStart); + case ':': + if (CurPtr[0] == ':') { + CurPtr++; + return formToken(tok::colon_colon, TokStart); + } + return formToken(tok::colon, TokStart); + case '#': { // Try lex a raw string literal. auto *Diags = getTokenDiags(); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 463e3b832a8c3..d449ebcfcb690 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1808,11 +1808,10 @@ void Parser::parseObjCSelector(SmallVector &Names, IsNullarySelector = true; while (true) { // Empty selector piece. - if (Tok.is(tok::colon)) { + if (consumeIfColonSplittingDoubles()) { Names.push_back(Identifier()); - NameLocs.push_back(Tok.getLoc()); + NameLocs.push_back(PreviousLoc); IsNullarySelector = false; - consumeToken(); continue; } @@ -1823,8 +1822,7 @@ void Parser::parseObjCSelector(SmallVector &Names, consumeToken(); // If we have a colon, consume it. - if (Tok.is(tok::colon)) { - consumeToken(); + if (consumeIfColonSplittingDoubles()) { IsNullarySelector = false; continue; } diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 739fe4e4d9e8d..5ad364dd6f6fa 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -2142,14 +2142,29 @@ ParserResult Parser::parseExprStringLiteral() { AppendingExpr)); } +/// Equivalent to \c Tok.is(tok::colon), but pretends that \c tok::colon_colon +/// doesn't exist if \c EnableExperimentalModuleSelector is disabled. +static bool isColon(Parser &P, Token Tok, tok altColon = tok::NUM_TOKENS) { + // FIXME: Introducing tok::colon_colon broke diag::empty_arg_label_underscore. + // We only care about tok::colon_colon when module selectors are turned on, so + // when they are turned off, this function works around the bug by treating + // tok::colon_colon as a synonym for tok::colon. However, the bug still exists + // when Feature::ModuleSelector is enabled. We will need to address this + // before the feature can be released. + + if (P.Context.LangOpts.hasFeature(Feature::ModuleSelector)) + return Tok.isAny(tok::colon, altColon); + + return Tok.isAny(tok::colon, tok::colon_colon, altColon); +} + void Parser::parseOptionalArgumentLabel(Identifier &name, SourceLoc &loc, bool isAttr) { /// A token that has the same meaning as colon, but is deprecated, if one exists for this call. auto altColon = isAttr ? tok::equal : tok::NUM_TOKENS; // Check to see if there is an argument label. - if (Tok.canBeArgumentLabel() && peekToken().isAny(tok::colon, altColon)) { - // Label found, including colon. + if (Tok.canBeArgumentLabel() && isColon(*this, peekToken(), altColon)) { auto text = Tok.getText(); // If this was an escaped identifier that need not have been escaped, say @@ -2168,7 +2183,7 @@ void Parser::parseOptionalArgumentLabel(Identifier &name, SourceLoc &loc, } loc = consumeArgumentLabel(name, /*diagnoseDollarPrefix=*/false); - } else if (Tok.isAny(tok::colon, altColon)) { + } else if (isColon(*this, Tok, altColon)) { // Found only the colon. diagnose(Tok, diag::expected_label_before_colon) .fixItInsert(Tok.getLoc(), "<#label#>"); @@ -2178,7 +2193,12 @@ void Parser::parseOptionalArgumentLabel(Identifier &name, SourceLoc &loc, } // If we get here, we ought to be on the colon. - assert(Tok.isAny(tok::colon, altColon)); + ASSERT(Tok.isAny(tok::colon, tok::colon_colon, altColon)); + + if (Tok.is(tok::colon_colon)) { + consumeIfColonSplittingDoubles(); + return; + } if (Tok.is(altColon)) diagnose(Tok, diag::replace_equal_with_colon_for_value) @@ -2208,7 +2228,7 @@ static bool tryParseArgLabelList(Parser &P, Parser::DeclNameOptions flags, flags.contains(Parser::DeclNameFlag::AllowZeroArgCompoundNames) && next.is(tok::r_paren); // An argument label. - bool nextIsArgLabel = next.canBeArgumentLabel() || next.is(tok::colon); + bool nextIsArgLabel = next.canBeArgumentLabel() || isColon(P, next); // An editor placeholder. bool nextIsPlaceholder = next.isEditorPlaceholder(); @@ -2221,11 +2241,11 @@ static bool tryParseArgLabelList(Parser &P, Parser::DeclNameOptions flags, lparenLoc = P.consumeToken(tok::l_paren); while (P.Tok.isNot(tok::r_paren)) { // If we see a ':', the user forgot the '_'; - if (P.Tok.is(tok::colon)) { - P.diagnose(P.Tok, diag::empty_arg_label_underscore) - .fixItInsert(P.Tok.getLoc(), "_"); + if (P.consumeIfColonSplittingDoubles()) { + P.diagnose(P.PreviousLoc, diag::empty_arg_label_underscore) + .fixItInsert(P.PreviousLoc, "_"); argumentLabels.push_back(Identifier()); - argumentLabelLocs.push_back(P.consumeToken(tok::colon)); + argumentLabelLocs.push_back(P.PreviousLoc); } Identifier argName; diff --git a/test/NameLookup/module_selector.swift b/test/Parse/module_selector.swift similarity index 100% rename from test/NameLookup/module_selector.swift rename to test/Parse/module_selector.swift From ab30cc98a208abb2203ee414580ba633ddbd93a6 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Wed, 13 Aug 2025 14:36:12 -0700 Subject: [PATCH 08/11] Parse module selectors in permitted locations --- include/swift/AST/DiagnosticsParse.def | 9 + include/swift/Parse/Parser.h | 19 +- lib/Parse/Lexer.cpp | 8 +- lib/Parse/ParseDecl.cpp | 36 +- lib/Parse/ParseExpr.cpp | 182 ++++-- lib/Parse/ParseStmt.cpp | 2 +- lib/Parse/ParseType.cpp | 58 +- test/Parse/module_selector.swift | 743 ++++++++++++++++++++++++- 8 files changed, 991 insertions(+), 66 deletions(-) diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def index 4abe1e520e62f..967dd5e5e3305 100644 --- a/include/swift/AST/DiagnosticsParse.def +++ b/include/swift/AST/DiagnosticsParse.def @@ -93,6 +93,15 @@ ERROR(forbidden_interpolated_string,none, ERROR(forbidden_extended_escaping_string,none, "%0 cannot be an extended escaping string literal", (StringRef)) +ERROR(expected_identifier_in_module_selector,none, + "expected module name in module selector", ()) +ERROR(expected_identifier_after_module_selector,none, + "expected identifier after module selector", ()) +NOTE(extra_whitespace_module_selector,none, + "remove extraneous whitespace after '::'", ()) +ERROR(module_selector_submodule_not_allowed,none, + "module selector cannot specify a submodule", ()) + //------------------------------------------------------------------------------ // MARK: Lexer diagnostics //------------------------------------------------------------------------------ diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index 639e00c1880d0..ac2f3d3bee19d 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -1817,6 +1817,19 @@ class Parser { void parseOptionalArgumentLabel(Identifier &name, SourceLoc &loc, bool isAttr = false); + /// Attempts to parse a \c module-selector if one is present. + /// + /// \verbatim + /// module-selector: identifier '::' + /// \endverbatim + /// + /// \return \c None if no selector is present or a selector is present but + /// is not allowed; an instance with an empty \c Identifier if a + /// selector is present but has no valid identifier; an instance with + /// a valid \c Identifier if a selector is present and includes a + /// module name. + std::optional> parseModuleSelector(); + enum class DeclNameFlag : uint8_t { /// If passed, operator basenames are allowed. AllowOperators = 1 << 0, @@ -1829,6 +1842,9 @@ class Parser { /// not ordinary identifiers. AllowKeywordsUsingSpecialNames = AllowKeywords | 1 << 2, + /// If passed, module selectors are not permitted on this declaration name. + ModuleSelectorUnsupported = 1 << 3, + /// If passed, compound names with argument lists are allowed, unless they /// have empty argument lists. AllowCompoundNames = 1 << 4, @@ -1876,7 +1892,8 @@ class Parser { SourceLoc &rightAngleLoc, ArgumentList *&argList, bool isExprBasic, DiagRef diag); - ParserResult parseExprIdentifier(bool allowKeyword); + ParserResult parseExprIdentifier(bool allowKeyword, + bool allowModuleSelector = true); Expr *parseExprEditorPlaceholder(Token PlaceholderTok, Identifier PlaceholderId); diff --git a/lib/Parse/Lexer.cpp b/lib/Parse/Lexer.cpp index 049d521eef6c5..1e53754313f44 100644 --- a/lib/Parse/Lexer.cpp +++ b/lib/Parse/Lexer.cpp @@ -819,9 +819,12 @@ static bool isLeftBound(const char *tokBegin, const char *bufferBegin) { static bool isRightBound(const char *tokEnd, bool isLeftBound, const char *codeCompletionPtr) { switch (*tokEnd) { + case ':': // ':' is an expression separator; '::' is not + return tokEnd[1] == ':'; + case ' ': case '\r': case '\n': case '\t': // whitespace case ')': case ']': case '}': // closing delimiters - case ',': case ';': case ':': // expression separators + case ',': case ';': // expression separators return false; case '\0': @@ -2765,7 +2768,7 @@ void Lexer::lexImpl() { case '\\': return formToken(tok::backslash, TokStart); case ':': - if (CurPtr[0] == ':') { + if (CurPtr[0] == ':' && LangOpts.hasFeature(Feature::ModuleSelector)) { CurPtr++; return formToken(tok::colon_colon, TokStart); } @@ -2879,6 +2882,7 @@ Token Lexer::getTokenAtLocation(const SourceManager &SM, SourceLoc Loc, // Use fake language options; language options only affect validity // and the exact token produced. LangOptions FakeLangOpts; + FakeLangOpts.enableFeature(Feature::ModuleSelector); // Here we return comments as tokens because either the caller skipped // comments and normally we won't be at the beginning of a comment token diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index d449ebcfcb690..6747c6dc65514 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -682,7 +682,8 @@ bool Parser::parseSpecializeAttributeArguments( DeclNameFlag::AllowZeroArgCompoundNames | DeclNameFlag::AllowKeywordsUsingSpecialNames | DeclNameFlag::AllowOperators | - DeclNameFlag::AllowLowercaseAndUppercaseSelf); + DeclNameFlag::AllowLowercaseAndUppercaseSelf | + DeclNameFlag::ModuleSelectorUnsupported); } } if (ParamLabel == "spiModule") { @@ -1136,7 +1137,8 @@ Parser::parseImplementsAttribute(SourceLoc AtLoc, SourceLoc Loc) { MemberNameLoc, diag::attr_implements_expected_member_name, DeclNameFlag::AllowZeroArgCompoundNames | DeclNameFlag::AllowOperators | - DeclNameFlag::AllowLowercaseAndUppercaseSelf); + DeclNameFlag::AllowLowercaseAndUppercaseSelf | + DeclNameFlag::ModuleSelectorUnsupported); if (!MemberName) { Status.setIsParseError(); } @@ -1159,7 +1161,7 @@ Parser::parseImplementsAttribute(SourceLoc AtLoc, SourceLoc Loc) { return Status; } - // FIXME(ModQual): Reject module qualification on MemberName. + assert(MemberName.getModuleSelector().empty()); return ParserResult( ImplementsAttr::create(Context, AtLoc, SourceRange(Loc, rParenLoc), ProtocolType.get(), MemberName.getFullName(), @@ -2440,7 +2442,8 @@ Parser::parseMacroRoleAttribute( (DeclNameFlag::AllowOperators | DeclNameFlag::AllowKeywords | DeclNameFlag::AllowKeywordsUsingSpecialNames | DeclNameFlag::AllowCompoundNames | - DeclNameFlag::AllowZeroArgCompoundNames)); + DeclNameFlag::AllowZeroArgCompoundNames | + DeclNameFlag::ModuleSelectorUnsupported)); if (!name) { status.setIsParseError(); return status; @@ -4269,11 +4272,15 @@ ParserStatus Parser::parseDeclAttribute(DeclAttributes &Attributes, .warnUntilSwiftVersion(6); } + bool hasModuleSelector = Context.LangOpts.hasFeature(Feature::ModuleSelector) + && peekToken().is(tok::colon_colon); + // If this not an identifier, the attribute is malformed. if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_in) && Tok.isNot(tok::kw_inout) && - Tok.isNot(tok::kw_rethrows)) { + Tok.isNot(tok::kw_rethrows) && + !hasModuleSelector) { if (Tok.is(tok::code_complete)) { if (CodeCompletionCallbacks) { @@ -4294,7 +4301,7 @@ ParserStatus Parser::parseDeclAttribute(DeclAttributes &Attributes, // If the attribute follows the new representation, switch // over to the alternate parsing path. - std::optional DK = + std::optional DK = hasModuleSelector ? std::nullopt : DeclAttribute::getAttrKindFromString(Tok.getText()); if (DK == DeclAttrKind::Rethrows) { DK = DeclAttrKind::AtRethrows; @@ -4306,7 +4313,7 @@ ParserStatus Parser::parseDeclAttribute(DeclAttributes &Attributes, auto checkInvalidAttrName = [&](StringRef invalidName, StringRef correctName, DeclAttrKind kind, std::optional> diag = std::nullopt) { - if (!DK && Tok.getText() == invalidName) { + if (!DK && !hasModuleSelector && Tok.getText() == invalidName) { DK = kind; if (diag) { @@ -4370,7 +4377,7 @@ ParserStatus Parser::parseDeclAttribute(DeclAttributes &Attributes, DeclAttrKind::Preconcurrency, diag::attr_renamed_warning); - if (!DK && Tok.getText() == "warn_unused_result") { + if (!DK && !hasModuleSelector && Tok.getText() == "warn_unused_result") { // The behavior created by @warn_unused_result is now the default. Emit a // Fix-It to remove. SourceLoc attrLoc = consumeToken(); @@ -4445,9 +4452,10 @@ ParserStatus Parser::parseDeclAttribute(DeclAttributes &Attributes, return parseNewDeclAttribute(Attributes, AtLoc, *DK, isFromClangAttribute); } - if (TypeAttribute::getAttrKindFromString(Tok.getText()).has_value()) + if (!hasModuleSelector && + TypeAttribute::getAttrKindFromString(Tok.getText()).has_value()) diagnose(Tok, diag::type_attribute_applied_to_decl); - else if (Tok.isContextualKeyword("unknown")) { + else if (!hasModuleSelector && Tok.isContextualKeyword("unknown")) { diagnose(Tok, diag::unknown_attr_name, "unknown"); } else { // Change the context to create a custom attribute syntax. @@ -5780,6 +5788,8 @@ static void skipAttribute(Parser &P) { // Parse the attribute name, which can be qualified, have // generic arguments, and so on. do { + P.parseModuleSelector(); + if (!(P.consumeIf(tok::identifier) || P.consumeIf(tok::kw_rethrows)) && !P.consumeIf(tok::code_complete)) return; @@ -10330,9 +10340,11 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name, return makeParserCodeCompletionResult(); } + // TODO: We could support module selectors for precedence groups if we + // implemented the lookup for it. groupName = parseDeclNameRef(groupLoc, diag::operator_decl_expected_precedencegroup, - {}); + DeclNameFlag::ModuleSelectorUnsupported); if (Context.TypeCheckerOpts.EnableOperatorDesignatedTypes) { // Designated types have been removed; consume the list (mainly for source @@ -10630,7 +10642,7 @@ Parser::parseDeclPrecedenceGroup(ParseDeclOptions flags, auto name = parseDeclNameRef(nameLoc, { diag::expected_precedencegroup_relation, attrName }, - {}); + DeclNameFlag::ModuleSelectorUnsupported); if (!name) { return abortBody(); } diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 5ad364dd6f6fa..579f3b32c7354 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -827,7 +827,8 @@ ParserResult Parser::parseExprKeyPathObjC() { ParserStatus status; SourceLoc LastDotLoc; DeclNameOptions flags = DeclNameFlag::AllowCompoundNames | - DeclNameFlag::AllowLowercaseAndUppercaseSelf; + DeclNameFlag::AllowLowercaseAndUppercaseSelf | + DeclNameFlag::ModuleSelectorUnsupported; while (true) { // Handle code completion. if (Tok.is(tok::code_complete)) @@ -1298,7 +1299,7 @@ Parser::parseExprPostfixSuffix(ParserResult Result, bool isExprBasic, } // Handle "x.self" expr. - if (Tok.is(tok::kw_self)) { + if (Tok.is(tok::kw_self) && !peekToken().is(tok::colon_colon)) { Result = makeParserResult( Result, new (Context) DotSelfExpr(Result.get(), TokLoc, consumeToken())); @@ -1744,10 +1745,13 @@ ParserResult Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) { LLVM_FALLTHROUGH; } case tok::kw_init: - case tok::kw_Self: // Self + case tok::kw_Self: // Self + case tok::colon_colon: // module selector with missing module name return parseExprIdentifier(/*allowKeyword=*/true); case tok::kw_Any: { // Any + if (peekToken().is(tok::colon_colon)) + return parseExprIdentifier(/*allowKeyword=*/true); auto TyR = parseAnyType(); return makeParserResult(new (Context) TypeExpr(TyR.get())); } @@ -1756,6 +1760,8 @@ ParserResult Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) { return makeParserResult(parseExprAnonClosureArg()); case tok::kw__: // _ + if (peekToken().is(tok::colon_colon)) + return parseExprIdentifier(/*allowKeyword=*/true); return makeParserResult( new (Context) DiscardAssignmentExpr(consumeToken(), /*Implicit=*/false)); @@ -1819,6 +1825,8 @@ ParserResult Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) { } case tok::kw_super: // 'super' + if (peekToken().is(tok::colon_colon)) + return parseExprIdentifier(/*allowKeyword=*/true); return parseExprSuper(); case tok::l_paren: @@ -2271,13 +2279,94 @@ static bool tryParseArgLabelList(Parser &P, Parser::DeclNameOptions flags, return true; } +std::optional> Parser::parseModuleSelector() { + if (!Context.LangOpts.hasFeature(Feature::ModuleSelector)) + return std::nullopt; + + auto isAtModuleSelector = [&]() -> bool { + // Also allow the current token to be colon_colon, for diagnostics. + if (peekToken().isNot(tok::colon_colon) && Tok.isNot(tok::colon_colon)) + return false; + + // Allow the module name to also be one of several invalid but + // identifier-like tokens. + return Tok.isAny(tok::identifier, tok::kw__, tok::kw_Any, tok::kw_self, + tok::kw_Self, tok::kw_super, tok::colon_colon); + }; + + if (!isAtModuleSelector()) + return std::nullopt; + + // We will parse the selector whether or not it's allowed, then early return + // if it's disallowed, then diagnose any other errors in what we parsed. This + // will make sure we always consume the module selector's tokens, but don't + // complain about a malformed selector when it's not supposed to be there at + // all. + + SourceLoc nameLoc; + Identifier moduleName; + + // Consume an identifier (or one of our selected keywords with a diagnostic). + if (parseAnyIdentifier(moduleName, nameLoc, + diag::expected_identifier_in_module_selector, + /*diagnoseDollarPrefix=*/true)) { + if (Tok.is(tok::colon_colon)) { + nameLoc = Tok.getLoc(); + } else { + moduleName = Context.getIdentifier(Tok.getText()); + nameLoc = consumeToken(); + } + } + + consumeToken(tok::colon_colon); + + // Foo::Bar::baz is an invalid attempt to address a submodule; diagnose it. + SourceLoc submoduleStartLoc = Tok.getLoc(); + while (!Tok.isAtStartOfLine() && isAtModuleSelector()) { + if (Tok.isNot(tok::colon_colon)) + consumeToken(); + consumeToken(tok::colon_colon); + } + + if (submoduleStartLoc != Tok.getLoc()) { + diagnose(submoduleStartLoc, diag::module_selector_submodule_not_allowed) + .highlightChars(submoduleStartLoc, getEndOfPreviousLoc()) + .fixItRemoveChars(submoduleStartLoc, getEndOfPreviousLoc()); + } + + return Located(moduleName, nameLoc); +} + DeclNameRef Parser::parseDeclNameRef(DeclNameLoc &loc, DiagRef diag, DeclNameOptions flags) { + // Consume the module name, if present. + SourceLoc moduleSelectorLoc; + Identifier moduleSelector; + bool hasModuleSelector = false; + if (!flags.contains(DeclNameFlag::ModuleSelectorUnsupported)) { + if (auto locatedModule = parseModuleSelector()) { + hasModuleSelector = true; + moduleSelectorLoc = locatedModule->Loc; + moduleSelector = locatedModule->Item; + } + } + // Consume the base name. DeclBaseName baseName; SourceLoc baseNameLoc; - if (Tok.is(tok::identifier) || + if (hasModuleSelector && Tok.isAtStartOfLine()) { + // Newline is not allowed between module selector and following token. + diagnose(getEndOfPreviousLoc(), + diag::expected_identifier_after_module_selector); + if (Tok.isIdentifierOrUnderscore() || Tok.isKeyword()) { + diagnose(getEndOfPreviousLoc(), diag::extra_whitespace_module_selector) + .fixItRemoveChars(getEndOfPreviousLoc(), Tok.getLoc()); + } + // This is recoverable. + baseName = DeclBaseName(); + baseNameLoc = PreviousLoc; + } else if (Tok.is(tok::identifier) || (flags.contains(DeclNameFlag::AllowLowercaseAndUppercaseSelf) && Tok.isAny(tok::kw_Self, tok::kw_self))) { Identifier baseNameId; @@ -2291,7 +2380,8 @@ DeclNameRef Parser::parseDeclNameRef(DeclNameLoc &loc, Tok.isAnyOperator()) { baseName = Context.getIdentifier(Tok.getText()); baseNameLoc = consumeToken(); - } else if (flags.contains(DeclNameFlag::AllowKeywords) && Tok.isKeyword()) { + } else if ((flags.contains(DeclNameFlag::AllowKeywords) + || hasModuleSelector) && Tok.isKeyword()) { bool specialDeinitAndSubscript = flags.contains(DeclNameFlag::AllowKeywordsUsingSpecialNames); @@ -2309,8 +2399,17 @@ DeclNameRef Parser::parseDeclNameRef(DeclNameLoc &loc, baseNameLoc = consumeToken(); } else { checkForInputIncomplete(); - diagnose(Tok, diag); - return DeclNameRef(); + + // If we already parsed a module selector, diagnose that it has no base name + // and recover. Otherwise, use the caller-specified diagnostic and bail. + if (hasModuleSelector) { + diagnose(Tok, diag::expected_identifier_after_module_selector); + baseName = DeclBaseName(); + baseNameLoc = PreviousLoc; + } else { + diagnose(Tok, diag); + return DeclNameRef(); + } } // Parse an argument list, if the flags allow it and it's present. @@ -2324,15 +2423,15 @@ DeclNameRef Parser::parseDeclNameRef(DeclNameLoc &loc, rparenLoc); if (argumentLabelLocs.empty() || !hadArgList) - loc = DeclNameLoc(baseNameLoc); + loc = DeclNameLoc(Context, moduleSelectorLoc, baseNameLoc); else - loc = DeclNameLoc(Context, baseNameLoc, lparenLoc, argumentLabelLocs, - rparenLoc); + loc = DeclNameLoc(Context, moduleSelectorLoc, baseNameLoc, + lparenLoc, argumentLabelLocs, rparenLoc); if (!hadArgList) - return DeclNameRef(baseName); + return DeclNameRef(Context, moduleSelector, baseName); - return DeclNameRef({ Context, baseName, argumentLabels }); + return DeclNameRef(Context, moduleSelector, baseName, argumentLabels); } ParserStatus Parser::parseFreestandingMacroExpansion( @@ -2351,7 +2450,8 @@ ParserStatus Parser::parseFreestandingMacroExpansion( bool hasWhitespaceBeforeName = poundEndLoc != Tok.getLoc(); - macroNameRef = parseDeclNameRef(macroNameLoc, diag, DeclNameFlag::AllowKeywords); + macroNameRef = parseDeclNameRef(macroNameLoc, diag, + DeclNameFlag::AllowKeywords); if (!macroNameRef) return makeParserError(); @@ -2395,9 +2495,11 @@ ParserStatus Parser::parseFreestandingMacroExpansion( /// expr-identifier: /// unqualified-decl-name generic-args? -ParserResult Parser::parseExprIdentifier(bool allowKeyword) { +ParserResult Parser::parseExprIdentifier(bool allowKeyword, + bool allowModuleSelector) { ParserStatus status; - assert(Tok.isAny(tok::identifier, tok::kw_self, tok::kw_Self) || + assert(Tok.isAny(tok::identifier, tok::kw_self, tok::kw_Self, + tok::colon_colon) || (allowKeyword && Tok.isKeyword())); Token IdentTok = Tok; @@ -2406,6 +2508,9 @@ ParserResult Parser::parseExprIdentifier(bool allowKeyword) { if (allowKeyword) { declNameFlags |= DeclNameFlag::AllowKeywords; } + if (!allowModuleSelector) { + declNameFlags |= DeclNameFlag::ModuleSelectorUnsupported; + } // Parse the unqualified-decl-name. DeclNameLoc loc; DeclNameRef name = parseDeclNameRef(loc, diag::expected_expr, declNameFlags); @@ -2436,8 +2541,12 @@ ParserResult Parser::parseExprIdentifier(bool allowKeyword) { } auto refKind = DeclRefKind::Ordinary; - Expr *E = new (Context) UnresolvedDeclRefExpr(name, refKind, loc); - + Expr *E; + if (name.getBaseName().empty()) + E = new (Context) ErrorExpr(loc.getSourceRange()); + else + E = new (Context) UnresolvedDeclRefExpr(name, refKind, loc); + if (hasGenericArgumentList) { E = UnresolvedSpecializeExpr::create(Context, E, LAngleLoc, args, RAngleLoc); @@ -2722,7 +2831,8 @@ ParserStatus Parser::parseClosureSignatureIfPresent( // the expression to capture. if (!Tok.is(tok::code_complete)) { name = Context.getIdentifier(Tok.getText()); - auto initializerResult = parseExprIdentifier(/*allowKeyword=*/false); + auto initializerResult = parseExprIdentifier(/*allowKeyword=*/false, + /*allowModuleSelector=*/false); status |= initializerResult; initializer = initializerResult.get(); } else { @@ -3074,7 +3184,8 @@ Expr *Parser::parseExprAnonClosureArg() { DeclNameLoc nameLoc; DeclNameRef nameRef = parseDeclNameRef(nameLoc, diag::impossible_parse, - DeclNameFlag::AllowAnonymousParamNames); + DeclNameFlag::AllowAnonymousParamNames | + DeclNameFlag::ModuleSelectorUnsupported); StringRef Name = nameRef.getBaseIdentifier().str(); SourceLoc Loc = nameLoc.getBaseNameLoc(); @@ -3220,19 +3331,26 @@ Parser::parseArgumentList(tok leftTok, tok rightTok, bool isExprBasic, return makeParserResult(status, argList); } +/// See if we have an operator decl ref '()'. The operator token in +/// this case lexes as a binary operator because it neither leads nor +/// follows a proper subexpression. +bool listElementIsBinaryOperator(Parser &P, tok rightTok) { + // Look past a module selector, if present. + if (P.Tok.is(tok::identifier) && P.peekToken().is(tok::colon_colon)) { + return P.lookahead(2, [&](auto &scope) { + return listElementIsBinaryOperator(P, rightTok); + }); + } + + return P.Tok.isBinaryOperator() && P.peekToken().isAny(rightTok, tok::comma); +} + ParserStatus Parser::parseExprListElement(tok rightTok, bool isArgumentList, SourceLoc leftLoc, SmallVectorImpl &elts) { Identifier FieldName; SourceLoc FieldNameLoc; parseOptionalArgumentLabel(FieldName, FieldNameLoc); - // See if we have an operator decl ref '()'. The operator token in - // this case lexes as a binary operator because it neither leads nor - // follows a proper subexpression. - auto isUnappliedOperator = [&]() { - return Tok.isBinaryOperator() && peekToken().isAny(rightTok, tok::comma); - }; - - if (isUnappliedOperator()) { + if (listElementIsBinaryOperator(*this, rightTok)) { // Check to see if we have the start of a regex literal `/.../`. We need // to do this for an unapplied operator reference, as e.g `(/, /)` might // be a regex literal. @@ -3241,7 +3359,7 @@ ParserStatus Parser::parseExprListElement(tok rightTok, bool isArgumentList, Sou ParserStatus Status; Expr *SubExpr = nullptr; - if (isUnappliedOperator()) { + if (listElementIsBinaryOperator(*this, rightTok)) { DeclNameLoc Loc; auto OperName = parseDeclNameRef(Loc, diag::expected_operator_ref, @@ -3350,8 +3468,10 @@ Parser::parseTrailingClosures(bool isExprBasic, SourceRange calleeRange, // Record the line numbers for the diagnostics below. // Note that *do not* move this to after 'parseExprClosure()' it slows down // 'getLineNumber()' call because of cache in SourceMgr. - auto origLine = SourceMgr.getLineAndColumnInBuffer(calleeRange.End).first; - auto braceLine = SourceMgr.getLineAndColumnInBuffer(braceLoc).first; + auto origLine = calleeRange.End.isInvalid() ? 0 + : SourceMgr.getLineAndColumnInBuffer(calleeRange.End).first; + auto braceLine = braceLoc.isInvalid() ? 0 + : SourceMgr.getLineAndColumnInBuffer(braceLoc).first; ParserStatus result; @@ -3367,7 +3487,7 @@ Parser::parseTrailingClosures(bool isExprBasic, SourceRange calleeRange, // Warn if the trailing closure is separated from its callee by more than // one line. A single-line separation is acceptable for a trailing closure // call, and will be diagnosed later only if the call fails to typecheck. - if (braceLine > origLine + 1) { + if (origLine != 0 && braceLine != 0 && braceLine > origLine + 1) { diagnose(braceLoc, diag::trailing_closure_after_newlines); diagnose(calleeRange.Start, diag::trailing_closure_callee_here); diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 390a7bf367177..29fb662f3e4b8 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -471,7 +471,7 @@ ParserStatus Parser::parseBraceItems(SmallVectorImpl &Entries, // explicit '{' or '}', so the start and end locations should be // the same as those of the result node, plus any junk consumed // afterwards - auto Brace = BraceStmt::create(Context, Result.getStartLoc(), + auto Brace = BraceStmt::create(Context, StartLoc, Result, PreviousLoc, /*Implicit=*/true); TLCD->setBody(Brace); Entries.push_back(TLCD); diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp index 28bf11f65a4dd..76003b9da7577 100644 --- a/lib/Parse/ParseType.cpp +++ b/lib/Parse/ParseType.cpp @@ -180,9 +180,28 @@ ParserResult Parser::parseTypeSimple( tildeLoc = consumeToken(); } + auto diagnoseAndRecover = [&]() -> ParserResult { + { + auto diag = diagnose(Tok, MessageID); + // If the next token is closing or separating, the type was likely + // forgotten + if (Tok.isAny(tok::r_paren, tok::r_brace, tok::r_square, tok::arrow, + tok::equal, tok::comma, tok::semi)) + diag.fixItInsert(getEndOfPreviousLoc(), " <#type#>"); + } + if (Tok.isKeyword() && !Tok.isAtStartOfLine()) { + ty = makeParserErrorResult(ErrorTypeRepr::create(Context, Tok.getLoc())); + consumeToken(); + return ty; + } + checkForInputIncomplete(); + return nullptr; + }; + switch (Tok.getKind()) { case tok::kw_Self: case tok::identifier: + case tok::colon_colon: // In SIL files (not just when parsing SIL types), accept the // Pack{} syntax for spelling variadic type packs. if (isInSILMode() && Tok.isContextualKeyword("Pack") && @@ -225,7 +244,10 @@ ParserResult Parser::parseTypeSimple( } break; case tok::kw_Any: - ty = parseAnyType(); + if (peekToken().is(tok::colon_colon)) + ty = parseTypeIdentifier(/*base=*/nullptr); + else + ty = parseAnyType(); break; case tok::l_paren: ty = parseTypeTupleBody(); @@ -245,29 +267,26 @@ ParserResult Parser::parseTypeSimple( break; } case tok::kw__: - ty = makeParserResult(new (Context) PlaceholderTypeRepr(consumeToken())); + if (peekToken().is(tok::colon_colon)) + ty = parseTypeIdentifier(/*base=*/nullptr); + else + ty = makeParserResult(new (Context) PlaceholderTypeRepr(consumeToken())); break; case tok::kw_protocol: - if (startsWithLess(peekToken())) { + if (Tok.is(tok::kw_protocol) && startsWithLess(peekToken())) { ty = parseOldStyleProtocolComposition(); break; } - LLVM_FALLTHROUGH; - default: - { - auto diag = diagnose(Tok, MessageID); - // If the next token is closing or separating, the type was likely forgotten - if (Tok.isAny(tok::r_paren, tok::r_brace, tok::r_square, tok::arrow, - tok::equal, tok::comma, tok::semi)) - diag.fixItInsert(getEndOfPreviousLoc(), " <#type#>"); - } - if (Tok.isKeyword() && !Tok.isAtStartOfLine()) { - ty = makeParserErrorResult(ErrorTypeRepr::create(Context, Tok.getLoc())); - consumeToken(); - return ty; + return diagnoseAndRecover(); + case tok::kw_self: + case tok::kw_super: + if (peekToken().is(tok::colon_colon)) { + ty = parseTypeIdentifier(/*base=*/nullptr); + break; } - checkForInputIncomplete(); - return nullptr; + return diagnoseAndRecover(); + default: + return diagnoseAndRecover(); } // '.X', '.Type', '.Protocol', '?', '!', '[]'. @@ -1872,6 +1891,9 @@ bool Parser::canParseCollectionType() { } bool Parser::canParseTypeIdentifier() { + // Parse a module selector, if present. + parseModuleSelector(); + // Parse an identifier. // // FIXME: We should expect e.g. 'X.var'. Almost any keyword is a valid member component. diff --git a/test/Parse/module_selector.swift b/test/Parse/module_selector.swift index 0efc97316ec2c..dbc0f3fb687ec 100644 --- a/test/Parse/module_selector.swift +++ b/test/Parse/module_selector.swift @@ -1,3 +1,744 @@ -// RUN: %target-typecheck-verify-swift -enable-experimental-feature ModuleSelector +// RUN: %target-typecheck-verify-swift -sdk %clang-importer-sdk -module-name main -I %S/Inputs -enable-experimental-feature ModuleSelector -parse + +// Make sure the lack of the experimental flag disables the feature: +// RUN: not %target-typecheck-verify-swift -sdk %clang-importer-sdk -module-name main -I %S/Inputs 2>/dev/null // REQUIRES: swift_feature_ModuleSelector + +// ModuleSelectorCorrectCode +extension ModuleSelectorTestingKit::A {} + +extension A: @retroactive Swift::Equatable { + @_implements(Swift::Equatable, ==(_:_:)) + public static func equals(_: ModuleSelectorTestingKit::A, _: ModuleSelectorTestingKit::A) -> Swift::Bool { + Swift::fatalError() + } + + // FIXME: Add tests with autodiff @_differentiable(jvp:vjp:) and + // @_derivative(of:) + + @_dynamicReplacement(for: ModuleSelectorTestingKit::negate()) + mutating func myNegate() { + let fn: (Swift::Int, Swift::Int) -> Swift::Int = (Swift::+) + + let magnitude: Int.Swift::Magnitude = main::magnitude + + if Swift::Bool.Swift::random() { + self.ModuleSelectorTestingKit::negate() + } else { + self = ModuleSelectorTestingKit::A(value: .Swift::min) + self = A.ModuleSelectorTestingKit::init(value: .min) + } + + self.main::myNegate() + + Swift::fatalError() + } + + // FIXME: Can we test @convention(witness_method:)? +} + + +extension ModuleSelectorIncorrectAttrNames { + // An attribute with a module selector *must* be a custom attribute and should be parsed as such. + @main::available(macOS 10.15, *) var use1: String { "foo" } + // expected-error@-1 {{expected ',' separator}} + + @main::available var use2 + + @main::available(foo: bar) var use3 + + func builderUser2(@main::MyBuilder fn: () -> Void) {} +} + +// Repeat this test case at top level to make sure we correctly skip attribute +// module selectors when looking ahead to distinguish declarations from +// expressions. +@main::available(macOS 10.15, *) var use1: String { "foo" } +// expected-error@-1 {{expected ',' separator}} + + +// ModuleSelectorWhitespace +_ = Swift::print + +_ = Swift:: print + +_ = Swift ::print + +_ = Swift :: print + +_ = Swift:: +print +// expected-error@-2 {{expected identifier after module selector}} +// expected-note@-3 {{remove extraneous whitespace after '::'}} {{12-+1:1=}} + +_ = Swift +::print + +_ = Swift :: +print +// expected-error@-2 {{expected identifier after module selector}} +// expected-note@-3 {{remove extraneous whitespace after '::'}} {{13-+1:1=}} + +_ = Swift +:: print + +_ = Swift +:: +print +// expected-error@-2 {{expected identifier after module selector}} +// expected-note@-3 {{remove extraneous whitespace after '::'}} {{3-+1:1=}} + + +// ModuleSelectorIncorrectFuncSignature +func main::decl1() {} +// expected-error@-1 {{expected '(' in argument list of function declaration}} {{none}} +// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{10-10=;}} +// expected-error@-3 {{expected module name in module selector}} {{none}} + +func decl1( + main::p1: Swift::A +// expected-error@-2 {{expected parameter name followed by ':'}} {{none}} +) {} + +// Round-tripping failures: +func decl1( + main::p1: ::A +// expected-error@-2 {{expected parameter name followed by ':'}} {{none}} +) {} + +func decl1( + main::p1: Swift:: +// expected-error@-2 {{expected parameter name followed by ':'}} {{none}} +) {} + +func decl1( + main::label p2: Swift::inout A +// expected-error@-2 {{expected parameter name followed by ':'}} {{none}} +) {} + +func decl1( + label main::p3: @Swift::escaping () -> A +// expected-error@-1 {{expected parameter name followed by ':'}} {{none}} +// expected-error@-2 {{expected ',' separator}} {{13-13=,}} +// expected-error@-3 {{expected ':' following argument label and parameter name}} {{none}} +) {} + + +func testModuleSelectorIncorrectBindingDecls() { + let main::decl1a = "a" + // expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{11-11=;}} + // expected-error@-2 {{expected module name in module selector}} + + // Found by mutation testing: + let let::decl1a = "a" + // expected-error@-1 {{'let' cannot appear nested inside another 'var' or 'let' pattern}} + // expected-error@-2 {{expected pattern}} + + var main::decl1b = "b" + // expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{11-11=;}} + // expected-error@-2 {{expected module name in module selector}} + + let (main::decl1c, Swift::decl1d) = ("c", "d") + // expected-error@-1 {{expected ',' separator}} {{12-12=,}} + // expected-error@-2 {{expected pattern}} + + if let (main::decl1e, Swift::decl1f) = Optional(("e", "f")) {} + // expected-error@-1 {{expected ',' separator}} {{15-15=,}} + // expected-error@-2 {{expected module name in module selector}} + + guard let (main::decl1g, Swift::decl1h) = Optional(("g", "h")) else { return } + // expected-error@-1 {{expected ',' separator}} {{18-18=,}} + // expected-error@-2 {{expected module name in module selector}} + + switch Optional(main::decl1g) { + case Optional.some(let Swift::decl1i): + // expected-error@-1 {{expected ',' separator}} {{31-31=,}} + // expected-error@-2 {{expected module name in module selector}} + break + case .none: + break + } + + switch Optional(main::decl1g) { + case let Optional.some(Swift::decl1j): + // expected-error@-1 {{expected ',' separator}} {{31-31=,}} + // expected-error@-2 {{expected module name in module selector}} + break + case .none: + break + } + + switch Optional(main::decl1g) { + case let Swift::decl1k?: + // expected-error@-1 {{expected ':' after 'case'}} {{none}} + // expected-error@-2 {{expected module name in module selector}} + // expected-error@-3 {{consecutive statements on a line must be separated by ';'}} {{26-26=;}} + // expected-error@-4 {{expected expression}} + break + case .none: + break + } + + for main::decl1l in "lll" {} + // expected-error@-1 {{expected 'in' after for-each pattern}} {{none}} + // expected-error@-2 {{expected module name in module selector}} {{none}} + // expected-error@-3 {{expected '{' to start the body of for-each loop}} +} + + +// ModuleSelectorIncorrectClosureDecls +// This gets radically misinterpreted as two statements followed by some invalid code. +"lll".forEach { [Swift::magnitude] + main::elem in print(elem) + // expected-error@-1 {{expected expression}} + // expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{13-13=;}} +} + +"lll".forEach { (main::elem) in print(elem) } +// expected-error@-1 {{expected parameter name followed by ':'}} {{none}} +// expected-error@-2 {{expected ',' separator}} {{22-22=,}} + +"lll".forEach { (main::elem) -> Void in print(elem) } +// expected-error@-1 {{expected parameter name followed by ':'}} {{none}} +// expected-error@-2 {{expected ',' separator}} {{22-22=,}} + +"lll".forEach { (main::elem: Character) -> Void in print(elem) } +// expected-error@-1 {{expected parameter name followed by ':'}} +// expected-error@-2 {{expected ',' separator}} {{22-22=,}} + + +// ModuleSelectorIncorrectTypeDecls +enum main::decl2 {} +// expected-error@-1 {{expected '{' in enum}} +enum decl2_substitute { + // expected-note@-1 {{in declaration of 'decl2_substitute'}} + case Swift::decl2a + // expected-error@-1 {{expected declaration}} + // expected-error@-2 {{consecutive declarations on a line must be separated by ';'}} {{13-13=;}} +} + +struct main::decl3 {} +// expected-error@-1 {{expected '{' in struct}} + +class main::decl4 {} +// expected-error@-1 {{expected '{' in class}} + +typealias main::decl5 = Swift::Bool +// expected-error@-1 {{expected '=' in type alias declaration}} + +protocol main::decl6 {} +// expected-error@-1 {{expected '{' in protocol type}} +protocol decl6_substitute { + // expected-note@-1 {{in declaration of 'decl6_substitute'}} + associatedtype Swift::decl6a + // expected-error@-1 {{expected declaration}} + // expected-error@-2 {{consecutive declarations on a line must be separated by ';'}} {{23-23=;}} +} + + +// ModuleSelectorIncorrectGlobalVarDecls +let main::decl7 = 7 +// expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{9-9=;}} +// expected-error@-2 {{expected module name in module selector}} + +var main::decl8 = 8 { +// expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{9-9=;}} +// expected-error@-2 {{expected module name in module selector}} +// expected-error@-3 {{consecutive statements on a line must be separated by ';'}} {{20-20=;}} +// expected-error@-4 {{top-level statement cannot begin with a closure expression}} + willSet(Swift::newValue) {} + didSet(Foo::oldValue) {} +} + +var decl8_willSet = 8 { + willSet(Swift::newValue) {} +// expected-error@-1 {{expected ')' after willSet parameter name}} +// expected-note@-2 {{to match this opening '('}} +// expected-error@-3 {{expected '{' to start 'willSet' definition}} + didSet(Foo::oldValue) {} +} + +var decl8_didSet = 8 { + willSet(newValue) {} + didSet(Foo::oldValue) {} + // expected-error@-1 {{expected ')' after didSet parameter name}} + // expected-note@-2 {{to match this opening '('}} + // expected-error@-3 {{expected '{' to start 'didSet' definition}} +} + + +// ModuleSelectorIncorrectNestedDecls +struct Parent { + // expected-note@-1 {{in declaration of 'Parent'}} + + func main::decl1() {} + // expected-error@-1 {{expected '(' in argument list of function declaration}} + // expected-error@-2 {{consecutive declarations on a line must be separated by ';'}} {{12-12=;}} + // expected-error@-3 {{expected declaration}} + + enum main::decl2 {} + // expected-error@-1 {{expected '{' in enum}} + + enum decl2_substitute { + // expected-note@-1 {{in declaration of 'decl2_substitute'}} + case Swift::decl2a + // expected-error@-1 {{consecutive declarations on a line must be separated by ';'}} {{15-15=;}} + // expected-error@-2 {{expected declaration}} + } + + struct main::decl3 {} +// expected-error@-1 {{expected '{' in struct}} + + class main::decl4 {} +// expected-error@-1 {{expected '{' in class}} + + typealias main::decl5 = Swift::Bool +// expected-error@-1 {{expected '=' in type alias declaration}} +} + + +// ModuleSelectorMacroDecls +struct CreatesDeclExpectation { + #main::myMacro() +} + + +// ModuleSelectorIncorrectRuntimeBaseAttr +@_swift_native_objc_runtime_base(main::BaseClass) +// expected-error@-1 {{expected ')' in '_swift_native_objc_runtime_base' attribute}} +// expected-error@-2 {{expected declaration}} +class C1 {} + + +// ModuleSelectorOperatorDecls +infix operator <<<<< : Swift::AdditionPrecedence +// expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{29-29=;}} +// expected-error@-2 {{expected module name in module selector}} + +precedencegroup main::PG1 {} +// expected-error@-1 {{expected '{' after name of precedence group}} +precedencegroup PG1_substitute { + higherThan: Swift::AdditionPrecedence +// expected-error@-1 {{expected operator attribute identifier in precedence group body}} +} + + +// ModuleSelectorIllFormedModuleNames +var a: ::Int +// expected-error@-1 {{expected module name in module selector}} + +var b: (::Int) +// expected-error@-1 {{expected module name in module selector}} + +var c: *::Int +// expected-error@-1 {{expected type}} +// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} +// expected-error@-3 {{expected module name in module selector}} + +var d: _::Int +// expected-error@-1 {{'_' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{8-9=`_`}} + +var e: Self::Int +// expected-error@-1 {{keyword 'Self' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{8-12=`Self`}} + +var f: self::Int +// expected-error@-1 {{keyword 'self' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{8-12=`self`}} + +var g: inout::Int +// expected-error@-1 {{expected module name in module selector}} + +var h: Any::Int +// expected-error@-1 {{keyword 'Any' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{8-11=`Any`}} + +var aArray: [::Int] +// expected-error@-1 {{expected module name in module selector}} + +var bArray: [(::Int)] +// expected-error@-1 {{expected module name in module selector}} + +var cArray: [*::Int] +// expected-error@-1 {{expected element type}} +// expected-error@-2 {{expected ']' in array type}} +// expected-note@-3 {{to match this opening '['}} +// expected-error@-4 {{consecutive statements on a line must be separated by ';'}} {{14-14=;}} +// expected-error@-5 {{expected module name in module selector}} +// expected-error@-6 {{consecutive statements on a line must be separated by ';'}} {{20-20=;}} +// expected-error@-7 {{expected expression}} + +var dArray: [_::Int] +// expected-error@-1 {{'_' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{14-15=`_`}} + +var eArray: [Self::Int] +// expected-error@-1 {{keyword 'Self' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{14-18=`Self`}} + +var fArray: [self::Int] +// expected-error@-1 {{keyword 'self' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{14-18=`self`}} + +var gArray: [inout::Int] +// expected-error@-1 {{expected module name in module selector}} + +var hArray: [Any::Int] +// expected-error@-1 {{keyword 'Any' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{14-17=`Any`}} + +var aIndex: String.::Index +// expected-error@-1 {{expected module name in module selector}} + +// FIXME: This gets interpreted as a single `.*` operator; may not be ideal. +var cIndex: String.*::Index +// expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{19-19=;}} +// expected-error@-2 {{expected expression after unary operator}} +// expected-error@-3 {{expected module name in module selector}} + +var dIndex: String._::Index +// expected-error@-1 {{'_' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{20-21=`_`}} + +var eIndex: String.Self::Index +// expected-error@-1 {{keyword 'Self' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{20-24=`Self`}} + +var fIndex: String.self::Index +// expected-error@-1 {{keyword 'self' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{20-24=`self`}} + +var gIndex: String.inout::Index +// expected-error@-1 {{expected identifier in dotted type}} +// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{20-20=;}} +// expected-error@-3 {{expected expression}} + +var hIndex: String.Any::Index +// expected-error@-1 {{keyword 'Any' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{20-23=`Any`}} + +func inExpr() { + ::print() +// expected-error@-1 {{expected module name in module selector}} +} + +func inExpr() { + (::print()) +// expected-error@-1 {{expected module name in module selector}} +} + +func inExpr() { + *::print() +// expected-error@-1 {{expected module name in module selector}} +} + +func inExpr() { + _::print() +// expected-error@-1 {{'_' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{3-4=`_`}} +} + +func inExpr() { + Self::print() +// expected-error@-1 {{keyword 'Self' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{3-7=`Self`}} +} + +func inExpr() { + self::print() +// expected-error@-1 {{keyword 'self' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{3-7=`self`}} +} + +func inExpr() { + inout::print() +// expected-error@-1 {{expected expression}} +} + +func inExpr() { + Any::print() +// expected-error@-1 {{keyword 'Any' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{3-6=`Any`}} +} + +func inExpr() { + _ = 1.::magnitude +// expected-error@-1 {{expected module name in module selector}} +} + +func inExpr() { + _ = (1.::magnitude) +// expected-error@-1 {{expected module name in module selector}} +} + +// FIXME: This gets interpreted as a single `.*` operator; may not be ideal. +func inExpr() { + _ = 1.*::magnitude +// expected-error@-1 {{expected module name in module selector}} +} + +func inExpr() { + _ = 1._::magnitude +// expected-error@-1 {{'_' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{9-10=`_`}} +} + +func inExpr() { + _ = 1.Self::magnitude +// expected-error@-1 {{keyword 'Self' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{9-13=`Self`}} +} + +func inExpr() { + _ = 1.self::magnitude +// expected-error@-1 {{keyword 'self' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{9-13=`self`}} +} + +func inExpr() { + _ = 1.inout::magnitude +// expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{14-14=;}} +// expected-error@-2 {{expected module name in module selector}} +} + +func inExpr() { + _ = 1.Any::magnitude +// expected-error@-1 {{keyword 'Any' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{9-12=`Any`}} +} + + +// ModuleSelectorAttrs +@_spi(main::Private) +// expected-error@-1 {{expected ')' in '_spi' attribute}} {{none}} +// expected-error@-2 {{expected declaration}} +public struct BadImplementsAttr: CustomStringConvertible {} + +@_implements(main::CustomStringConvertible, Swift::description) +// expected-error@-1 {{expected ')' in '_implements' attribute}} +// expected-note@-2 {{to match this opening '('}} +// expected-error@-3 {{expected declaration}} +public var stringValue: String { fatalError() } + +@_specialize(target: main::fn(), spi: Swift::Private, where T == Swift::Int) +// expected-error@-1 {{missing ',' in '_specialize' attribute}} {{none}} +// expected-error@-2 {{missing ',' in '_specialize' attribute}} {{none}} +public func fn() -> T { fatalError() } + +func fn(_: @isolated(Swift::any) () -> Void) {} +// expected-error@-1 {{expected 'any' as the isolation kind}} +// expected-error@-2 {{expected ')' after isolation kind}} {{none}} +// expected-note@-3 {{to match this opening '('}} +// expected-error@-4 {{expected module name in module selector}} +// expected-error@-5 {{consecutive statements on a line must be separated by ';'}} {{44-44=;}} +// expected-error@-6 {{expected expression}} +// expected-error@-7 {{cannot have more than one parameter list}} FIXME: wat? + +@_documentation(metadata: Swift::GroupName) +// expected-error@-1 {{expected ',' separator}} {{32-32=,}} +// expected-error@-2 {{'_documentation' attribute expected 'visibility' or 'metadata' argument}} +func fn() {} + +@derivative(of: Swift::Foo.Swift::Bar.Swift::baz(), wrt: quux) +func fn() {} + + +// ModuleSelectorExpr +let x = Swift::do { 1 } + +let x = Swift:: +do { 1 } +// expected-error@-2 {{expected identifier after module selector}} +// expected-note@-3 {{remove extraneous whitespace after '::'}} {{16-+1:1=}} + +let x = Swift::if y { 1 } else { 0 } +// expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{18-18=;}} +// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{26-26=;}} +// expected-error@-3 {{expected expression}} + +let x = Swift:: +if y { 1 } else { 0 } +// expected-error@-2 {{expected identifier after module selector}} +// expected-note@-3 {{remove extraneous whitespace after '::'}} {{16-+1:1=}} + +let x = Swift::switch y { +// expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{22-22=;}} +// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{24-24=;}} + // expected-error@-3 {{top-level statement cannot begin with a closure expression}} +case true: 1 +// expected-error@-1 {{'case' label can only appear inside a 'switch' statement}} +case false: 0 +// expected-error@-1 {{'case' label can only appear inside a 'switch' statement}} +} + +let x = Swift:: +// expected-error@-1 {{expected identifier after module selector}} +// expected-note@-2 {{remove extraneous whitespace after '::'}} {{16-+3:1=}} +switch y { +case true: 1 +case false: 0 +} + +fn(Swift::&x) +// expected-error@-1 {{expected identifier after module selector}} +// expected-error@-2 {{expected ',' separator}} + +_ = Swift::\main::Foo.BarKit::bar +// expected-error@-1 {{expected identifier after module selector}} +// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} + +_ = \main::Foo.BarKit::bar + +_ = Swift::-x +// expected-error@-1 {{expected identifier after module selector}} +// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} + +_ = Swift::1 +// expected-error@-1 {{expected identifier after module selector}} +// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} + +_ = Swift::1.0 +// expected-error@-1 {{expected identifier after module selector}} +// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} + +func fn() { + _ = Swift::@"fnord" + // expected-error@-1 {{expected identifier after module selector}} + // expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{14-14=;}} + // expected-error@-3 {{string literals in Swift are not preceded by an '@' sign}} +} + +_ = Swift::"fnord" +// expected-error@-1 {{expected identifier after module selector}} +// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} + +_ = Swift::/fnord/ +// expected-error@-1 {{expected identifier after module selector}} +// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} + +_ = Swift::nil + +_ = Swift::true + +_ = Swift::identifier + +_ = Swift::self + +func fn() { + // FIXME: ASTGen might be doing something weird here + _ = Swift::init +} + +@attached(extension, names: Swift::deinit) macro m() +// expected-error@-1 {{unknown introduced name kind 'Swift'}} +// expected-error@-2 {{expected '{' for deinitializer}} + +@attached(extension, names: Swift::subscript) macro m() +// expected-error@-1 {{unknown introduced name kind 'Swift'}} +// expected-error@-2 {{expected '(' for subscript parameters}} + +_ = Swift::Self + +_ = Swift::Any + +_ = { + _ = Swift::$0 + // expected-error@-1 {{expected identifier after module selector}} + // expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{14-14=;}} +} + +_ = Swift::$foo + +_ = Swift::_ + +Swift::_ = 1 + +_ = Swift::#foo +// expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} +// expected-error@-2 {{expected identifier after module selector}} + +_ = #Swift::foo + +_ = Swift::{ 1 } +// expected-error@-1 {{expected identifier after module selector}} + +_ = Swift::.random() +// expected-error@-1 {{expected identifier after module selector}} + +_ = Swift::.main::random() +// expected-error@-1 {{expected identifier after module selector}} + +_ = .main::random() + +_ = Swift::super.foo() + +_ = Swift::(a, b) +// expected-error@-1 {{expected identifier after module selector}} + +_ = Swift::[a, b] +// expected-error@-1 {{expected identifier after module selector}} + +_ = Swift:: +// expected-error@-1 {{expected identifier after module selector}} +// expected-note@-2 {{remove extraneous whitespace after '::'}} {{12-+4:1=}} + +_ = x.Swift::y + +_ = x.Swift::1 +// expected-error@-1 {{expected identifier after module selector}} + +_ = x.Swift::self + +_ = x.Swift::Self.self + +_ = x.Swift::Type.self + +_ = x.Swift::Protocol.self + +_ = myArray.reduce(0, Swift::+) + +if Swift::#available(macOS 15, *) {} +// expected-error@-1 {{expected identifier after module selector}} +// expected-error@-2 {{expected '{' after 'if' condition}} + +func fn(_: Swift::Self) {} + +func fn(_: Swift::Any) {} + +func fn(_: Swift::Foo) {} + +func fn(_: Swift::(Int, String)) {} +// expected-error@-1 {{expected identifier after module selector}} + +func fn(_: Swift::[Int]) {} +// expected-error@-1 {{expected identifier after module selector}} + +func fn(_: Swift::_) {} + +func fn(_: Swift::) {} +// expected-error@-1 {{expected identifier after module selector}} + +func fn(_: Foo.Swift::Type) {} + +func fn(_: Foo.Swift::Protocol) {} + +func fn(_: Foo.Swift::Bar) {} + +func fn(_: Foo.Swift::self) {} + + +// ModuleSelectorSubmodule + +_ = Foundation::NSData::NSData() +// expected-error@-1 {{module selector cannot specify a submodule}} {{17-25=}} + +_ = Foundation::NSData::Fnord::NSData() +// expected-error@-1 {{module selector cannot specify a submodule}} {{17-32=}} + +_ = Foundation::NSData:: +Fnord::NSData() +// expected-error@-2 {{module selector cannot specify a submodule}} {{17-25=}} +// expected-error@-3 {{expected identifier after module selector}} +// expected-note@-4 {{remove extraneous whitespace after '::'}} {{25-+1:1=}} From be197845bc0c0df5af18d4f42b23fc418ad04a2d Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Thu, 8 May 2025 18:27:31 -0700 Subject: [PATCH 09/11] Allow `::` as an alias for `.` in scoped imports --- include/swift/AST/DiagnosticsParse.def | 2 ++ lib/Parse/ParseDecl.cpp | 8 +++++++- test/Parse/module_selector.swift | 20 ++++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def index 967dd5e5e3305..c840941db4bb9 100644 --- a/include/swift/AST/DiagnosticsParse.def +++ b/include/swift/AST/DiagnosticsParse.def @@ -101,6 +101,8 @@ NOTE(extra_whitespace_module_selector,none, "remove extraneous whitespace after '::'", ()) ERROR(module_selector_submodule_not_allowed,none, "module selector cannot specify a submodule", ()) +NOTE(replace_module_selector_with_member_lookup,none, + "replace '::' with '.'", ()) //------------------------------------------------------------------------------ // MARK: Lexer diagnostics diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 6747c6dc65514..bfbe1ead85914 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -6705,7 +6705,13 @@ ParserResult Parser::parseDeclImport(ParseDeclOptions Flags, .fixItRemove(Tok.getLoc()); return nullptr; } - HasNext = consumeIf(tok::period); + if (Tok.is(tok::colon_colon) + && (Kind == ImportKind::Module || importPath.size() > 1)) { + diagnose(Tok, diag::module_selector_submodule_not_allowed); + diagnose(Tok, diag::replace_module_selector_with_member_lookup) + .fixItReplace(Tok.getLoc(), "."); + } + HasNext = consumeIf(tok::period) || consumeIf(tok::colon_colon); } while (HasNext); if (Tok.is(tok::code_complete)) { diff --git a/test/Parse/module_selector.swift b/test/Parse/module_selector.swift index dbc0f3fb687ec..cfcc62adafc4e 100644 --- a/test/Parse/module_selector.swift +++ b/test/Parse/module_selector.swift @@ -5,6 +5,26 @@ // REQUIRES: swift_feature_ModuleSelector +// ModuleSelectorImports +import struct ModuleSelectorTestingKit::A + +import struct _::A +// expected-error@-1 {{'_' cannot be used as an identifier here}} +// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{15-16=`_`}} + +import struct ModuleSelectorTestingKit::Submodule::A +// expected-error@-1 {{module selector cannot specify a submodule}} +// expected-note@-2 {{replace '::' with '.'}} {{50-52=.}} + +import struct ModuleSelectorTestingKit.Submodule::A +// expected-error@-1 {{module selector cannot specify a submodule}} +// expected-note@-2 {{replace '::' with '.'}} {{49-51=.}} + +import ctypes::bits +// expected-error@-1 {{module selector cannot specify a submodule}} +// expected-note@-2 {{replace '::' with '.'}} {{14-16=.}} + + // ModuleSelectorCorrectCode extension ModuleSelectorTestingKit::A {} From 98a17d60b34fcd6ba088099f70ccbafbf29c4d10 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Wed, 6 Aug 2025 16:59:34 -0700 Subject: [PATCH 10/11] =?UTF-8?q?[NFC]=20[ASTGen]=20Don=E2=80=99t=20form?= =?UTF-8?q?=20PBDs=20without=20SourceLocs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A PatternBindingEntry formed from a MissingPatternSyntax has no valid SourceLocs in it, and a PatternBindingDecl containing only PatternBindingEntries with no valid SourceLocs trips an assertion during availability checking. (Generating dummy SourceLocs can cause invalid overlaps between AvailabilityScopes, so that’s not a workable solution.) The fix is to: • Refuse to generate a PatternBindingEntry from a PatternBindingSyntax with a MissingPatternSyntax (MissingPatternSyntaxes at nested positions don’t have this problem) • Refuse to generate a PatternBindingDecl with no PatternBindingEntries This ensures that the invalid AST nodes are never formed. No current test cases hit this problem, but certain invalid module selector tests can run into this situation when run with ASTGen. --- lib/ASTGen/Sources/ASTGen/Decls.swift | 34 +++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/lib/ASTGen/Sources/ASTGen/Decls.swift b/lib/ASTGen/Sources/ASTGen/Decls.swift index 4fc9d279cdcd9..f2bcef744b2f4 100644 --- a/lib/ASTGen/Sources/ASTGen/Decls.swift +++ b/lib/ASTGen/Sources/ASTGen/Decls.swift @@ -499,7 +499,15 @@ extension ASTGenVisitor { } } - func generate(patternBinding binding: PatternBindingSyntax, attrs: DeclAttributesResult, topLevelDecl: BridgedTopLevelCodeDecl?) -> BridgedPatternBindingEntry { + func generate(patternBinding binding: PatternBindingSyntax, attrs: DeclAttributesResult, topLevelDecl: BridgedTopLevelCodeDecl?) -> BridgedPatternBindingEntry? { + if binding.pattern.is(MissingPatternSyntax.self) { + // The availability checker requires declarations to have valid SourceLocs, but MissingPatternSyntax lowers to + // an implicit AnyPattern with invalid SourceLocs. A top-level MissingPatternSyntax could therefore cause us to + // construct an invalid AST. Drop the whole binding instead. + // No need to diagnose; SwiftParser should have already diagnosed the `MissingPatternSyntax`. + return nil + } + let pattern = generate(pattern: binding.pattern) let equalLoc = generateSourceLoc(binding.initializer?.equal) @@ -535,14 +543,17 @@ extension ASTGenVisitor { ) } - private func generateBindingEntries(for node: VariableDeclSyntax, attrs: DeclAttributesResult, topLevelDecl: BridgedTopLevelCodeDecl?) -> BridgedArrayRef { + private func generateBindingEntries(for node: VariableDeclSyntax, attrs: DeclAttributesResult, topLevelDecl: BridgedTopLevelCodeDecl?) -> BridgedArrayRef? { var propagatedType: BridgedTypeRepr? var entries: [BridgedPatternBindingEntry] = [] // Generate the bindings in reverse, keeping track of the TypeRepr to // propagate to earlier patterns if needed. for binding in node.bindings.reversed() { - var entry = self.generate(patternBinding: binding, attrs: attrs, topLevelDecl: topLevelDecl) + guard var entry = self.generate(patternBinding: binding, attrs: attrs, topLevelDecl: topLevelDecl) else { + // Missing pattern. Drop this binding. + continue + } // We can potentially propagate a type annotation back if we don't have an initializer, and are a bare NamedPattern. let canPropagateType = binding.initializer == nil && binding.pattern.is(IdentifierPatternSyntax.self) @@ -572,10 +583,17 @@ extension ASTGenVisitor { } entries.append(entry) } + + if entries.isEmpty { + // A VariableDeclSyntax is syntactically required to have at least one binding, so this can only happen if all + // of the bindings had missing patterns. + return nil + } + return entries.reversed().bridgedArray(in: self) } - func generate(variableDecl node: VariableDeclSyntax) -> BridgedDecl { + func generate(variableDecl node: VariableDeclSyntax) -> BridgedDecl? { let attrs = self.generateDeclAttributes(node, allowStatic: true) let introducer: BridgedVarDeclIntroducer switch node.bindingSpecifier.rawText { @@ -596,6 +614,12 @@ extension ASTGenVisitor { topLevelDecl = nil } + guard let entries = self.generateBindingEntries(for: node, attrs: attrs, topLevelDecl: topLevelDecl) else { + // No bindings with valid SourceLocs. A PatternBindingDecl generated from this would have an invalid SourceRange, + // violating availability checker invariants. Drop the PBD instead. + return nil + } + let decl = BridgedPatternBindingDecl.createParsed( self.ctx, declContext: topLevelDecl?.asDeclContext ?? self.declContext, @@ -604,7 +628,7 @@ extension ASTGenVisitor { staticSpelling: attrs.staticSpelling, introducerLoc: self.generateSourceLoc(node.bindingSpecifier), introducer: introducer, - entries: self.generateBindingEntries(for: node, attrs: attrs, topLevelDecl: topLevelDecl) + entries: entries ) if let topLevelDecl { let range = self.generateImplicitBraceRange(node) From fe22d37cb6294101d53a5dc54bb13dd9a3717f5e Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Wed, 13 Aug 2025 14:37:37 -0700 Subject: [PATCH 11/11] Update and test ASTGen for module selectors --- include/swift/AST/ASTBridging.h | 30 +- lib/AST/Bridging/DeclBridging.cpp | 17 +- lib/AST/Bridging/TypeReprBridging.cpp | 33 +- lib/ASTGen/Sources/ASTGen/ASTGen.swift | 90 +++- lib/ASTGen/Sources/ASTGen/DeclAttrs.swift | 35 +- lib/ASTGen/Sources/ASTGen/Exprs.swift | 79 ++-- lib/ASTGen/Sources/ASTGen/Literals.swift | 5 +- lib/ASTGen/Sources/ASTGen/SourceFile.swift | 1 + lib/ASTGen/Sources/ASTGen/Stmts.swift | 6 +- lib/ASTGen/Sources/ASTGen/Types.swift | 34 +- test/Parse/module_selector.swift | 507 +++++++++++++-------- 11 files changed, 525 insertions(+), 312 deletions(-) diff --git a/include/swift/AST/ASTBridging.h b/include/swift/AST/ASTBridging.h index 4ac2b1657c90f..048acdac2361d 100644 --- a/include/swift/AST/ASTBridging.h +++ b/include/swift/AST/ASTBridging.h @@ -146,14 +146,19 @@ class BridgedDeclNameRef { BRIDGED_INLINE swift::DeclNameRef unbridged() const; }; -SWIFT_NAME("BridgedDeclNameRef.createParsed(_:baseName:argumentLabels:)") -BridgedDeclNameRef BridgedDeclNameRef_createParsed(BridgedASTContext cContext, - swift::DeclBaseName baseName, - BridgedArrayRef cLabels); +SWIFT_NAME("BridgedDeclNameRef.createParsed(_:moduleSelector:baseName:" + "argumentLabels:)") +BridgedDeclNameRef +BridgedDeclNameRef_createParsed(BridgedASTContext cContext, + swift::Identifier cModuleSelector, + swift::DeclBaseName cBaseName, + BridgedArrayRef cLabels); -SWIFT_NAME("BridgedDeclNameRef.createParsed(_:)") +SWIFT_NAME("BridgedDeclNameRef.createParsed(_:moduleSelector:baseName:)") BridgedDeclNameRef -BridgedDeclNameRef_createParsed(swift::DeclBaseName baseName); +BridgedDeclNameRef_createParsed(BridgedASTContext cContext, + swift::Identifier cModuleSelector, + swift::DeclBaseName cBaseName); class BridgedDeclNameLoc { const void *_Nullable LocationInfo; @@ -2547,9 +2552,10 @@ BridgedOpaqueReturnTypeOfTypeAttr_createParsed( // MARK: TypeReprs //===----------------------------------------------------------------------===// -SWIFT_NAME("BridgedUnqualifiedIdentTypeRepr.createParsed(_:loc:name:)") +SWIFT_NAME("BridgedUnqualifiedIdentTypeRepr.createParsed(_:name:loc:)") BridgedUnqualifiedIdentTypeRepr BridgedUnqualifiedIdentTypeRepr_createParsed( - BridgedASTContext cContext, swift::SourceLoc loc, swift::Identifier id); + BridgedASTContext cContext, BridgedDeclNameRef cName, + BridgedDeclNameLoc cLoc); SWIFT_NAME( "BridgedArrayTypeRepr.createParsed(_:base:leftSquareLoc:rightSquareLoc:)") @@ -2583,8 +2589,8 @@ BridgedCompileTimeLiteralTypeRepr_createParsed(BridgedASTContext cContext, SWIFT_NAME("BridgedDeclRefTypeRepr.createParsed(_:base:name:nameLoc:" "genericArguments:angleRange:)") BridgedDeclRefTypeRepr BridgedDeclRefTypeRepr_createParsed( - BridgedASTContext cContext, BridgedTypeRepr cBase, swift::Identifier name, - swift::SourceLoc loc, BridgedArrayRef cGenericArguments, + BridgedASTContext cContext, BridgedTypeRepr cBase, BridgedDeclNameRef cName, + BridgedDeclNameLoc cLoc, BridgedArrayRef cGenericArguments, swift::SourceRange angleRange); SWIFT_NAME("BridgedDictionaryTypeRepr.createParsed(_:leftSquareLoc:keyType:" @@ -2609,8 +2615,8 @@ BridgedFunctionTypeRepr BridgedFunctionTypeRepr_createParsed( SWIFT_NAME("BridgedUnqualifiedIdentTypeRepr.createParsed(_:name:nameLoc:" "genericArgs:leftAngleLoc:rightAngleLoc:)") BridgedUnqualifiedIdentTypeRepr BridgedUnqualifiedIdentTypeRepr_createParsed( - BridgedASTContext cContext, swift::Identifier name, - swift::SourceLoc nameLoc, BridgedArrayRef genericArgs, + BridgedASTContext cContext, BridgedDeclNameRef cName, + BridgedDeclNameLoc cNameLoc, BridgedArrayRef genericArgs, swift::SourceLoc lAngleLoc, swift::SourceLoc rAngleLoc); SWIFT_NAME("BridgedOptionalTypeRepr.createParsed(_:base:questionLoc:)") diff --git a/lib/AST/Bridging/DeclBridging.cpp b/lib/AST/Bridging/DeclBridging.cpp index d826d6d4c9536..24a2ed7b2e9b0 100644 --- a/lib/AST/Bridging/DeclBridging.cpp +++ b/lib/AST/Bridging/DeclBridging.cpp @@ -32,17 +32,22 @@ using namespace swift; // MARK: DeclName //===----------------------------------------------------------------------===// -BridgedDeclNameRef BridgedDeclNameRef_createParsed(BridgedASTContext cContext, - DeclBaseName baseName, - BridgedArrayRef cLabels) { +BridgedDeclNameRef +BridgedDeclNameRef_createParsed(BridgedASTContext cContext, + swift::Identifier moduleSelector, + DeclBaseName baseName, + BridgedArrayRef cLabels) { ASTContext &context = cContext.unbridged(); auto labels = cLabels.unbridged(); - return DeclNameRef(DeclName(context, baseName, labels)); + return DeclNameRef(context, moduleSelector, baseName, labels); } -BridgedDeclNameRef BridgedDeclNameRef_createParsed(DeclBaseName baseName) { - return DeclNameRef(baseName); +BridgedDeclNameRef +BridgedDeclNameRef_createParsed(BridgedASTContext cContext, + swift::Identifier moduleSelector, + DeclBaseName baseName) { + return DeclNameRef(cContext.unbridged(), moduleSelector, baseName); } BridgedDeclNameLoc BridgedDeclNameLoc_createParsed(BridgedASTContext cContext, diff --git a/lib/AST/Bridging/TypeReprBridging.cpp b/lib/AST/Bridging/TypeReprBridging.cpp index 24e61b351872d..74ddc4691f016 100644 --- a/lib/AST/Bridging/TypeReprBridging.cpp +++ b/lib/AST/Bridging/TypeReprBridging.cpp @@ -33,20 +33,24 @@ using namespace swift; #define ABSTRACT_TYPEREPR(Id, Parent) TYPEREPR(Id, Parent) #include "swift/AST/TypeReprNodes.def" -BridgedUnqualifiedIdentTypeRepr -BridgedUnqualifiedIdentTypeRepr_createParsed(BridgedASTContext cContext, - SourceLoc loc, Identifier id) { +BridgedUnqualifiedIdentTypeRepr BridgedUnqualifiedIdentTypeRepr_createParsed( + BridgedASTContext cContext, + BridgedDeclNameRef cName, + BridgedDeclNameLoc cLoc) { return UnqualifiedIdentTypeRepr::create(cContext.unbridged(), - DeclNameLoc(loc), DeclNameRef(id)); + cLoc.unbridged(), + cName.unbridged()); } BridgedUnqualifiedIdentTypeRepr BridgedUnqualifiedIdentTypeRepr_createParsed( - BridgedASTContext cContext, Identifier name, SourceLoc nameLoc, - BridgedArrayRef genericArgs, SourceLoc lAngleLoc, SourceLoc rAngleLoc) { + BridgedASTContext cContext, + BridgedDeclNameRef cName, + BridgedDeclNameLoc cNameLoc, + BridgedArrayRef genericArgs, + SourceLoc lAngleLoc, SourceLoc rAngleLoc) { ASTContext &context = cContext.unbridged(); - auto Loc = DeclNameLoc(nameLoc); - auto Name = DeclNameRef(name); - return UnqualifiedIdentTypeRepr::create(context, Loc, Name, + return UnqualifiedIdentTypeRepr::create(context, cNameLoc.unbridged(), + cName.unbridged(), genericArgs.unbridged(), SourceRange{lAngleLoc, rAngleLoc}); } @@ -223,16 +227,17 @@ BridgedTupleTypeRepr_createParsed(BridgedASTContext cContext, } BridgedDeclRefTypeRepr BridgedDeclRefTypeRepr_createParsed( - BridgedASTContext cContext, BridgedTypeRepr cBase, Identifier name, - SourceLoc loc, BridgedArrayRef cGenericArguments, SourceRange angleRange) { + BridgedASTContext cContext, BridgedTypeRepr cBase, BridgedDeclNameRef cName, + BridgedDeclNameLoc cLoc, BridgedArrayRef cGenericArguments, + SourceRange angleRange) { ASTContext &context = cContext.unbridged(); auto genericArguments = cGenericArguments.unbridged(); assert(angleRange.isValid() || genericArguments.empty()); - return DeclRefTypeRepr::create(context, cBase.unbridged(), DeclNameLoc(loc), - DeclNameRef(name), genericArguments, - angleRange); + return DeclRefTypeRepr::create( + context, cBase.unbridged(), cLoc.unbridged(), + cName.unbridged(), genericArguments, angleRange); } BridgedCompositionTypeRepr diff --git a/lib/ASTGen/Sources/ASTGen/ASTGen.swift b/lib/ASTGen/Sources/ASTGen/ASTGen.swift index 86051f9f44dc2..15a531c470f68 100644 --- a/lib/ASTGen/Sources/ASTGen/ASTGen.swift +++ b/lib/ASTGen/Sources/ASTGen/ASTGen.swift @@ -14,7 +14,7 @@ import ASTBridging import BasicBridging import SwiftIfConfig // Needed to use BumpPtrAllocator -@_spi(BumpPtrAllocator) @_spi(RawSyntax) @_spi(Compiler) import SwiftSyntax +@_spi(BumpPtrAllocator) @_spi(ExperimentalLanguageFeatures) @_spi(RawSyntax) @_spi(Compiler) import SwiftSyntax import struct SwiftDiagnostics.Diagnostic @@ -205,7 +205,8 @@ extension ASTGenVisitor { /// source buffer. @inline(__always) func generateSourceLoc(_ node: some SyntaxProtocol) -> SourceLoc { - SourceLoc(at: node.positionAfterSkippingLeadingTrivia, in: self.base) + precondition(node.positionAfterSkippingLeadingTrivia.utf8Offset < 0x0000000100000000) + return SourceLoc(at: node.positionAfterSkippingLeadingTrivia, in: self.base) } /// Obtains the C++ start location of the node excluding leading trivia in the @@ -247,6 +248,91 @@ extension ASTGenVisitor { ) } + /// Obtains the bridged declaration based name and bridged source location from a token. + func generateDeclBaseName(_ token: TokenSyntax) -> (baseName: DeclBaseName, sourceLoc: SourceLoc) { + let baseName: DeclBaseName + switch token.keywordKind { + case .`init`: + baseName = .createConstructor() + case .deinit: + baseName = .createDestructor() + case .subscript: + baseName = .createSubscript() + default: + baseName = .init(self.generateIdentifier(token)) + } + let baseNameLoc = self.generateSourceLoc(token) + return (baseName, baseNameLoc) + } + + /// Obtains the bridged module name and bridged source location from a module selector. + func generateModuleSelector(_ node: ModuleSelectorSyntax?) -> (moduleName: Identifier, sourceLoc: SourceLoc) { + let moduleName = self.self.generateIdentifierAndSourceLoc(node?.moduleName) + return (moduleName: moduleName.identifier, sourceLoc: moduleName.sourceLoc) + } + + func generateDeclNameRef( + moduleSelector: ModuleSelectorSyntax?, + baseName: TokenSyntax, + arguments: ( + leftParen: TokenSyntax, + labels: some Collection, + rightParen: TokenSyntax + )? = Optional<(leftParen: TokenSyntax, labels: [TokenSyntax], rightParen: TokenSyntax)>.none + ) -> (name: BridgedDeclNameRef, loc: BridgedDeclNameLoc) { + let moduleSelectorLoc = self.generateModuleSelector(moduleSelector) + let baseNameLoc = self.generateDeclBaseName(baseName) + + // Create the name itself. + let nameRef: BridgedDeclNameRef + if let arguments { + let bridgedLabels: BridgedArrayRef + if arguments.labels.isEmpty { + bridgedLabels = BridgedArrayRef() + } else { + let labels = arguments.labels.lazy.map { + self.generateIdentifier($0) + } + bridgedLabels = labels.bridgedArray(in: self) + } + nameRef = .createParsed( + self.ctx, + moduleSelector: moduleSelectorLoc.moduleName, + baseName: baseNameLoc.baseName, + argumentLabels: bridgedLabels + ) + } else { + nameRef = .createParsed(self.ctx, moduleSelector: moduleSelectorLoc.moduleName, baseName: baseNameLoc.baseName) + } + + // Create the location. Complication: if the argument list has no labels, the paren locs aren't provided either. + // FIXME: This is silly but I'm pretty sure it's load-bearing. + let nameLoc: BridgedDeclNameLoc + if let arguments, !arguments.labels.isEmpty { + let labelLocs = arguments.labels.lazy.map { + self.generateSourceLoc($0) + } + let bridgedLabelLocs = labelLocs.bridgedArray(in: self) + + nameLoc = .createParsed( + self.ctx, + moduleSelectorLoc: moduleSelectorLoc.sourceLoc, + baseNameLoc: baseNameLoc.sourceLoc, + lParenLoc: self.generateSourceLoc(arguments.leftParen), + argumentLabelLocs: bridgedLabelLocs, + rParenLoc: self.generateSourceLoc(arguments.rightParen) + ) + } else { + nameLoc = .createParsed( + self.ctx, + moduleSelectorLoc: moduleSelectorLoc.sourceLoc, + baseNameLoc: baseNameLoc.sourceLoc + ) + } + + return (name: nameRef, loc: nameLoc) + } + /// Obtains a C++ source range from a pair of token nodes. @inline(__always) func generateSourceRange(start: TokenSyntax, end: TokenSyntax) -> SourceRange { diff --git a/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift b/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift index db463abab5347..65057ef444285 100644 --- a/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift +++ b/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift @@ -118,7 +118,7 @@ extension ASTGenVisitor { let attrKind: swift.DeclAttrKind? do { let bridgedOptional = BridgedOptionalDeclAttrKind(from: attrName.bridged) - attrKind = if bridgedOptional.hasValue { + attrKind = if identTy.moduleSelector == nil && bridgedOptional.hasValue { bridgedOptional.value } else { nil @@ -469,7 +469,8 @@ extension ASTGenVisitor { let features = args.compactMap(in: self) { arg -> Identifier? in guard arg.label == nil, let declNameExpr = arg.expression.as(DeclReferenceExprSyntax.self), - declNameExpr.argumentNames == nil + declNameExpr.argumentNames == nil, + declNameExpr.moduleSelector == nil else { // TODO: Diagnose. return nil @@ -1046,6 +1047,10 @@ extension ASTGenVisitor { return nil } + if arg.declName.moduleSelector != nil { + // TODO: Diagnose; module selector is meaningless at this position. + } + let type = self.generate(type: arg.type) let member = self.generateDeclNameRef(declReferenceExpr: arg.declName) @@ -1123,7 +1128,8 @@ extension ASTGenVisitor { let loc = self.generateSourceLoc(descriptorExpr) if let declRefExpr = descriptorExpr.as(DeclReferenceExprSyntax.self), - declRefExpr.argumentNames == nil + declRefExpr.argumentNames == nil, + declRefExpr.moduleSelector == nil { return generateLifetimeDescriptor( nameToken: declRefExpr.baseName, @@ -1214,7 +1220,10 @@ extension ASTGenVisitor { if node.argumentNames != nil { // TODO: Diagnose } - guard node.argumentNames == nil else { + if node.moduleSelector != nil { + // TODO: Diagnose + } + guard node.argumentNames == nil && node.moduleSelector == nil else { return nil } switch node.baseName.rawText { @@ -1274,7 +1283,11 @@ extension ASTGenVisitor { if let arg = arg.as(DeclReferenceExprSyntax.self) { name = self.generateDeclNameRef(declReferenceExpr: arg).name } else if arg.is(DiscardAssignmentExprSyntax.self) { - name = BridgedDeclNameRef.createParsed(.init(self.ctx.getIdentifier("_"))) + name = BridgedDeclNameRef.createParsed( + self.ctx, + moduleSelector: nil, + baseName: .init(self.ctx.getIdentifier("_")) + ) } else { // TODO: Diagnose fatalError("expected name") @@ -2095,7 +2108,8 @@ extension ASTGenVisitor { func generatePropertyName(expr node: ExprSyntax) -> Identifier? { guard let node = node.as(DeclReferenceExprSyntax.self), - node.argumentNames == nil + node.argumentNames == nil, + node.moduleSelector == nil else { // TODO: Diagnose. return nil @@ -2186,11 +2200,12 @@ extension ASTGenVisitor { // FIXME: Should be normal LabeledExprListSyntax arguments. // FIXME: Error handling let type: BridgedTypeRepr? = self.generateSingleAttrOption(attribute: node, { token in - let nameLoc = self.generateIdentifierAndSourceLoc(token) + // FIXME: Module selector? + let nameRef = self.generateDeclNameRef(moduleSelector: nil, baseName: token) return BridgedUnqualifiedIdentTypeRepr.createParsed( self.ctx, - loc: nameLoc.sourceLoc, - name: nameLoc.identifier + name: nameRef.name, + loc: nameRef.loc ).asTypeRepr }) guard let type else { @@ -2360,7 +2375,7 @@ extension ASTGenVisitor { _ valueGeneratorFunction: (TokenSyntax) -> R? ) -> R? { return generateConsumingAttrOption(args: &args, label: nil) { - if let declRefExpr = $0.as(DeclReferenceExprSyntax.self), declRefExpr.argumentNames == nil { + if let declRefExpr = $0.as(DeclReferenceExprSyntax.self), declRefExpr.argumentNames == nil, declRefExpr.moduleSelector == nil { return valueGeneratorFunction(declRefExpr.baseName) } else if let discardExpr = $0.as(DiscardAssignmentExprSyntax.self) { return valueGeneratorFunction(discardExpr.wildcard) diff --git a/lib/ASTGen/Sources/ASTGen/Exprs.swift b/lib/ASTGen/Sources/ASTGen/Exprs.swift index bd69b2b3a6054..8dbe3a5db51d3 100644 --- a/lib/ASTGen/Sources/ASTGen/Exprs.swift +++ b/lib/ASTGen/Sources/ASTGen/Exprs.swift @@ -520,57 +520,17 @@ extension ASTGenVisitor { func generateDeclNameRef(declReferenceExpr node: DeclReferenceExprSyntax) -> ( name: BridgedDeclNameRef, loc: BridgedDeclNameLoc ) { - let baseName: DeclBaseName - switch node.baseName.keywordKind { - case .`init`: - baseName = .createConstructor() - case .deinit: - baseName = .createDestructor() - case .subscript: - baseName = .createSubscript() - default: - baseName = .init(self.generateIdentifier(node.baseName)) - } - let baseNameLoc = self.generateSourceLoc(node.baseName) - - if let argumentClause = node.argumentNames { - if argumentClause.arguments.isEmpty { - return ( - name: .createParsed( - self.ctx, - baseName: baseName, - argumentLabels: BridgedArrayRef() - ), - loc: .createParsed(baseNameLoc) - ) - } else { - let labels = argumentClause.arguments.lazy.map { - self.generateIdentifier($0.name) - } - let labelLocs = argumentClause.arguments.lazy.map { - self.generateSourceLoc($0.name) - } - return ( - name: .createParsed( - self.ctx, - baseName: baseName, - argumentLabels: labels.bridgedArray(in: self) - ), - loc: .createParsed( - self.ctx, - baseNameLoc: baseNameLoc, - lParenLoc: self.generateSourceLoc(argumentClause.leftParen), - argumentLabelLocs: labelLocs.bridgedArray(in: self), - rParenLoc: self.generateSourceLoc(argumentClause.rightParen) - ) + return self.generateDeclNameRef( + moduleSelector: node.moduleSelector, + baseName: node.baseName, + arguments: node.argumentNames.map { argumentClause in + ( + leftParen: argumentClause.leftParen, + labels: argumentClause.arguments.lazy.map { $0.name }, + rightParen: argumentClause.rightParen ) } - } else { - return ( - name: .createParsed(baseName), - loc: .createParsed(baseNameLoc) - ) - } + ) } func generateEditorPlaceholderExpr(token: TokenSyntax) -> BridgedEditorPlaceholderExpr { @@ -646,12 +606,18 @@ extension ASTGenVisitor { if node.argumentNames != nil { // TODO: Diagnose. } + if node.moduleSelector != nil { + // TODO: Diagnose. + } return generateEditorPlaceholderExpr(token: node.baseName).asExpr } if node.baseName.rawTokenKind == .dollarIdentifier { if node.argumentNames != nil { // TODO: Diagnose. } + if node.moduleSelector != nil { + // TODO: Diagnose. + } return generateDollarIdentifierExpr(token: node.baseName) } let nameAndLoc = generateDeclNameRef(declReferenceExpr: node) @@ -826,6 +792,7 @@ extension ASTGenVisitor { func generate(freestandingMacroExpansion node: some FreestandingMacroExpansionSyntax) -> FreestandingMacroExpansionInfo { let poundLoc = self.generateSourceLoc(node.pound) + let moduleSelectorLoc = self.generateModuleSelector(node.moduleSelector) let nameLoc = self.generateIdentifierAndSourceLoc(node.macroName) let leftAngleLoc: SourceLoc @@ -858,8 +825,16 @@ extension ASTGenVisitor { return FreestandingMacroExpansionInfo( poundLoc: poundLoc, - macroNameRef: .createParsed(.init(nameLoc.identifier)), - macroNameLoc: .createParsed(nameLoc.sourceLoc), + macroNameRef: .createParsed( + self.ctx, + moduleSelector: moduleSelectorLoc.moduleName, + baseName: .init(nameLoc.identifier) + ), + macroNameLoc: .createParsed( + self.ctx, + moduleSelectorLoc: moduleSelectorLoc.sourceLoc, + baseNameLoc: nameLoc.sourceLoc + ), leftAngleLoc: leftAngleLoc, genericArgs: genericArgs.lazy.bridgedArray(in: self), rightAngleLoc: rightAngleLoc, @@ -1332,7 +1307,7 @@ extension ASTGenVisitor { return .createParsed( self.ctx, - name: .createParsed(.init(name)), + name: .createParsed(self.ctx, moduleSelector: nil, baseName: .init(name)), kind: kind, loc: .createParsed(nameLoc) ); diff --git a/lib/ASTGen/Sources/ASTGen/Literals.swift b/lib/ASTGen/Sources/ASTGen/Literals.swift index 7f2a1c2e481a9..c66168a13e96b 100644 --- a/lib/ASTGen/Sources/ASTGen/Literals.swift +++ b/lib/ASTGen/Sources/ASTGen/Literals.swift @@ -76,12 +76,15 @@ extension ASTGenVisitor { // Name reference to `appendLiteral(_:)` let appendLiteral = BridgedDeclNameRef.createParsed( self.ctx, + moduleSelector: nil, baseName: .init(self.ctx.getIdentifier("appendLiteral")), argumentLabels: CollectionOfOne(Identifier()).bridgedArray(in: self) ) // Name reference to `appendInterpolation`. Arguments labels are not determined yet. let appendInterpolation = BridgedDeclNameRef.createParsed( - .init(self.ctx.getIdentifier("appendInterpolation")) + self.ctx, + moduleSelector: nil, + baseName: .init(self.ctx.getIdentifier("appendInterpolation")) ) // Total byte length of "literal" segments. diff --git a/lib/ASTGen/Sources/ASTGen/SourceFile.swift b/lib/ASTGen/Sources/ASTGen/SourceFile.swift index f545445df088d..01d8fd6a1e5ff 100644 --- a/lib/ASTGen/Sources/ASTGen/SourceFile.swift +++ b/lib/ASTGen/Sources/ASTGen/SourceFile.swift @@ -78,6 +78,7 @@ extension Parser.ExperimentalFeatures { mapFeature(.OldOwnershipOperatorSpellings, to: .oldOwnershipOperatorSpellings) mapFeature(.KeyPathWithMethodMembers, to: .keypathWithMethodMembers) mapFeature(.DefaultIsolationPerFile, to: .defaultIsolationPerFile) + mapFeature(.ModuleSelector, to: .moduleSelector) } } diff --git a/lib/ASTGen/Sources/ASTGen/Stmts.swift b/lib/ASTGen/Sources/ASTGen/Stmts.swift index c97d8d558e3c4..db3bbc465f17c 100644 --- a/lib/ASTGen/Sources/ASTGen/Stmts.swift +++ b/lib/ASTGen/Sources/ASTGen/Stmts.swift @@ -221,7 +221,11 @@ extension ASTGenVisitor { let identifier = pat.boundName if identifier != nil { // For `if let foo { }` Create a `foo` expression as the initializer. - let ref = BridgedDeclNameRef.createParsed(.init(identifier)) + let ref = BridgedDeclNameRef.createParsed( + self.ctx, + moduleSelector: nil, + baseName: .init(identifier) + ) let loc = BridgedDeclNameLoc.createParsed(self.generateSourceLoc(node.pattern)) initializer = BridgedUnresolvedDeclRefExpr.createParsed( diff --git a/lib/ASTGen/Sources/ASTGen/Types.swift b/lib/ASTGen/Sources/ASTGen/Types.swift index 600b48244b735..67ef52e218347 100644 --- a/lib/ASTGen/Sources/ASTGen/Types.swift +++ b/lib/ASTGen/Sources/ASTGen/Types.swift @@ -84,10 +84,10 @@ extension ASTGenVisitor { ).asTypeRepr } - let id = self.generateIdentifier(node.name) + let nameRef = self.generateDeclNameRef(moduleSelector: node.moduleSelector, baseName: node.name) guard let generics = node.genericArgumentClause else { - return BridgedUnqualifiedIdentTypeRepr.createParsed(ctx, loc: loc, name: id).asTypeRepr + return BridgedUnqualifiedIdentTypeRepr.createParsed(ctx, name: nameRef.name, loc: nameRef.loc).asTypeRepr } let genericArguments = generics.arguments.lazy.map { @@ -96,8 +96,8 @@ extension ASTGenVisitor { return BridgedUnqualifiedIdentTypeRepr.createParsed( self.ctx, - name: id, - nameLoc: loc, + name: nameRef.name, + nameLoc: nameRef.loc, genericArgs: genericArguments.bridgedArray(in: self), leftAngleLoc: self.generateSourceLoc(generics.leftAngle), rightAngleLoc: self.generateSourceLoc(generics.rightAngle) @@ -117,7 +117,7 @@ extension ASTGenVisitor { } func generate(memberType node: MemberTypeSyntax) -> BridgedDeclRefTypeRepr { - let (name, nameLoc) = self.generateIdentifierAndSourceLoc(node.name) + let nameRef = self.generateDeclNameRef(moduleSelector: node.moduleSelector, baseName: node.name) let genericArguments: BridgedArrayRef let angleRange: SourceRange @@ -135,8 +135,8 @@ extension ASTGenVisitor { return BridgedDeclRefTypeRepr.createParsed( self.ctx, base: self.generate(type: node.baseType), - name: name, - nameLoc: nameLoc, + name: nameRef.name, + nameLoc: nameRef.loc, genericArguments: genericArguments, angleRange: angleRange ) @@ -318,8 +318,12 @@ extension ASTGenVisitor { // warning: using 'class' keyword to define a class-constrained protocol is deprecated; use 'AnyObject' instead return .createParsed( self.ctx, - loc: self.generateSourceLoc(node.classKeyword), - name: self.ctx.getIdentifier("AnyObject") + name: BridgedDeclNameRef.createParsed( + self.ctx, + moduleSelector: nil, + baseName: .init(self.ctx.getIdentifier("AnyObject")) + ), + loc: BridgedDeclNameLoc.createParsed(self.generateSourceLoc(node.classKeyword)) ) } @@ -528,11 +532,11 @@ extension ASTGenVisitor { // 'Foo.bar(_:baz:)' break } - let name = self.generateIdentifierAndSourceLoc(node.baseName) + let nameRef = self.generateDeclNameRef(declReferenceExpr: node) return BridgedUnqualifiedIdentTypeRepr .createParsed( self.ctx, - name: name.identifier, - nameLoc: name.sourceLoc, + name: nameRef.name, + nameLoc: nameRef.loc, genericArgs: genericArgs.arguments, leftAngleLoc: genericArgs.range.start, rightAngleLoc: genericArgs.range.end @@ -551,12 +555,12 @@ extension ASTGenVisitor { // Function name. E.g. 'Foo.bar(_:baz:)' break } - let name = self.generateIdentifierAndSourceLoc(node.declName.baseName) + let nameRef = self.generateDeclNameRef(declReferenceExpr: node.declName) return BridgedDeclRefTypeRepr.createParsed( self.ctx, base: base, - name: name.identifier, - nameLoc: name.sourceLoc, + name: nameRef.name, + nameLoc: nameRef.loc, genericArguments: genericArgs.arguments, angleRange: genericArgs.range ).asTypeRepr diff --git a/test/Parse/module_selector.swift b/test/Parse/module_selector.swift index cfcc62adafc4e..831793af76f81 100644 --- a/test/Parse/module_selector.swift +++ b/test/Parse/module_selector.swift @@ -1,28 +1,29 @@ -// RUN: %target-typecheck-verify-swift -sdk %clang-importer-sdk -module-name main -I %S/Inputs -enable-experimental-feature ModuleSelector -parse +// RUN: %target-typecheck-verify-swift -sdk %clang-importer-sdk -module-name main -I %S/Inputs -enable-experimental-feature ModuleSelector -parse -verify-additional-prefix legacy- +// RUN: %target-typecheck-verify-swift -sdk %clang-importer-sdk -module-name main -I %S/Inputs -enable-experimental-feature ModuleSelector -parse -verify-additional-prefix new- -enable-experimental-feature ParserASTGen // Make sure the lack of the experimental flag disables the feature: // RUN: not %target-typecheck-verify-swift -sdk %clang-importer-sdk -module-name main -I %S/Inputs 2>/dev/null -// REQUIRES: swift_feature_ModuleSelector +// REQUIRES: swift_feature_ModuleSelector, swift_feature_ParserASTGen // ModuleSelectorImports import struct ModuleSelectorTestingKit::A import struct _::A // expected-error@-1 {{'_' cannot be used as an identifier here}} -// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{15-16=`_`}} +// expected-legacy-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{15-16=`_`}} import struct ModuleSelectorTestingKit::Submodule::A -// expected-error@-1 {{module selector cannot specify a submodule}} -// expected-note@-2 {{replace '::' with '.'}} {{50-52=.}} +// expected-legacy-error@-1 {{module selector cannot specify a submodule}} expected-new-error@-1 {{unexpected code 'Submodule::' in import}} +// expected-legacy-note@-2 {{replace '::' with '.'}} {{50-52=.}} import struct ModuleSelectorTestingKit.Submodule::A -// expected-error@-1 {{module selector cannot specify a submodule}} -// expected-note@-2 {{replace '::' with '.'}} {{49-51=.}} +// expected-legacy-error@-1 {{module selector cannot specify a submodule}} expected-new-error@-1 {{submodule cannot be imported using module selector}} +// expected-legacy-note@-2 {{replace '::' with '.'}} {{49-51=.}} expected-new-note@-2 {{replace '::' with '.'}} {{49-51=}} {{49-49=.}} import ctypes::bits -// expected-error@-1 {{module selector cannot specify a submodule}} -// expected-note@-2 {{replace '::' with '.'}} {{14-16=.}} +// expected-legacy-error@-1 {{module selector cannot specify a submodule}} expected-new-error@-1 {{submodule cannot be imported using module selector}} +// expected-legacy-note@-2 {{replace '::' with '.'}} {{14-16=.}} expected-new-note@-2 {{replace '::' with '.'}} {{14-16=}} {{14-14=.}} // ModuleSelectorCorrectCode @@ -62,7 +63,7 @@ extension A: @retroactive Swift::Equatable { extension ModuleSelectorIncorrectAttrNames { // An attribute with a module selector *must* be a custom attribute and should be parsed as such. @main::available(macOS 10.15, *) var use1: String { "foo" } - // expected-error@-1 {{expected ',' separator}} + // expected-legacy-error@-1 {{expected ',' separator}} expected-new-error@-1 {{unexpected code '10.15, *' in attribute}} @main::available var use2 @@ -75,7 +76,7 @@ extension ModuleSelectorIncorrectAttrNames { // module selectors when looking ahead to distinguish declarations from // expressions. @main::available(macOS 10.15, *) var use1: String { "foo" } -// expected-error@-1 {{expected ',' separator}} +// expected-legacy-error@-1 {{expected ',' separator}} expected-new-error@-1 {{unexpected code '10.15, *' in attribute}} // ModuleSelectorWhitespace @@ -89,16 +90,16 @@ _ = Swift :: print _ = Swift:: print -// expected-error@-2 {{expected identifier after module selector}} -// expected-note@-3 {{remove extraneous whitespace after '::'}} {{12-+1:1=}} +// expected-legacy-error@-2 {{expected identifier after module selector}} expected-new-error@-2 {{expected identifier}} +// expected-legacy-note@-3 {{remove extraneous whitespace after '::'}} {{12-+1:1=}} expected-new-note@-3 {{insert identifier}} {{12-12=<#identifier#>}} _ = Swift ::print _ = Swift :: print -// expected-error@-2 {{expected identifier after module selector}} -// expected-note@-3 {{remove extraneous whitespace after '::'}} {{13-+1:1=}} +// expected-legacy-error@-2 {{expected identifier after module selector}} expected-new-error@-2 {{expected identifier}} +// expected-legacy-note@-3 {{remove extraneous whitespace after '::'}} {{13-+1:1=}} expected-new-note@-3 {{insert identifier}} {{13-13=<#identifier#>}} _ = Swift :: print @@ -106,75 +107,91 @@ _ = Swift _ = Swift :: print -// expected-error@-2 {{expected identifier after module selector}} -// expected-note@-3 {{remove extraneous whitespace after '::'}} {{3-+1:1=}} +// expected-legacy-error@-2 {{expected identifier after module selector}} expected-new-error@-2 {{expected identifier}} +// expected-legacy-note@-3 {{remove extraneous whitespace after '::'}} {{3-+1:1=}} expected-new-note@-3 {{insert identifier}} {{3-3=<#identifier#>}} // ModuleSelectorIncorrectFuncSignature func main::decl1() {} -// expected-error@-1 {{expected '(' in argument list of function declaration}} {{none}} -// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{10-10=;}} -// expected-error@-3 {{expected module name in module selector}} {{none}} +// expected-legacy-error@-1 {{expected '(' in argument list of function declaration}} {{none}} expected-new-error@-1 {{unexpected code '::decl1' before parameter clause}} +// expected-legacy-error@-2 {{consecutive statements on a line must be separated by ';'}} {{10-10=;}} +// expected-legacy-error@-3 {{expected module name in module selector}} {{none}} func decl1( main::p1: Swift::A -// expected-error@-2 {{expected parameter name followed by ':'}} {{none}} +// expected-legacy-error@-2 {{expected parameter name followed by ':'}} {{none}} expected-new-error@-1 {{unexpected code '::p1' in parameter}} ) {} // Round-tripping failures: func decl1( main::p1: ::A -// expected-error@-2 {{expected parameter name followed by ':'}} {{none}} +// expected-legacy-error@-2 {{expected parameter name followed by ':'}} {{none}} expected-new-error@-1 {{unexpected code '::p1' in parameter}} +// expected-new-error@-2 {{expected module name in module selector}} +// expected-new-note@-3 {{insert module name}} {{13-13=<#identifier#>}} ) {} func decl1( main::p1: Swift:: -// expected-error@-2 {{expected parameter name followed by ':'}} {{none}} +// expected-legacy-error@-2 {{expected parameter name followed by ':'}} {{none}} expected-new-error@-1 {{unexpected code '::p1' in parameter}} +// expected-new-error@-2 {{expected identifier in type}} +// expected-new-note@-3 {{insert identifier}} {{20-20=<#identifier#>}} ) {} func decl1( main::label p2: Swift::inout A -// expected-error@-2 {{expected parameter name followed by ':'}} {{none}} +// expected-legacy-error@-2 {{expected parameter name followed by ':'}} {{none}} expected-new-error@-1 {{unexpected code '::label p2' in parameter}} +// expected-new-error@-2 {{expected ',' in parameter}} +// expected-new-note@-3 {{insert ','}} {{31-32=}} {{32-32=, }} +// expected-new-error@-4 {{expected identifier and ':' in parameter}} +// expected-new-note@-5 {{insert identifier and ':'}} {{32-32=<#identifier#>}} ) {} func decl1( label main::p3: @Swift::escaping () -> A -// expected-error@-1 {{expected parameter name followed by ':'}} {{none}} -// expected-error@-2 {{expected ',' separator}} {{13-13=,}} -// expected-error@-3 {{expected ':' following argument label and parameter name}} {{none}} +// expected-legacy-error@-1 {{expected parameter name followed by ':'}} {{none}} expected-new-error@-1 {{unexpected code '::p3' in parameter}} +// expected-legacy-error@-2 {{expected ',' separator}} {{13-13=,}} +// expected-legacy-error@-3 {{expected ':' following argument label and parameter name}} {{none}} ) {} func testModuleSelectorIncorrectBindingDecls() { let main::decl1a = "a" - // expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{11-11=;}} - // expected-error@-2 {{expected module name in module selector}} + // expected-new-error@-1 {{expected '=' in variable}} + // expected-legacy-error@-2 {{consecutive statements on a line must be separated by ';'}} {{11-11=;}} expected-new-note@-2 {{insert '='}} {{11-11= = }} + // expected-error@-3 {{expected module name in module selector}} + // expected-new-note@-4 {{insert module name}} {{11-11=<#identifier#>}} // Found by mutation testing: let let::decl1a = "a" - // expected-error@-1 {{'let' cannot appear nested inside another 'var' or 'let' pattern}} - // expected-error@-2 {{expected pattern}} + // expected-legacy-error@-1 {{'let' cannot appear nested inside another 'var' or 'let' pattern}} expected-new-error@-1 {{expected pattern in value binding pattern}} + // expected-legacy-error@-2 {{expected pattern}} expected-new-note@-2 {{insert pattern}} {{10-10=<#pattern#> }} + // expected-new-error@-3 {{expected '=' in variable}} + // expected-new-note@-4 {{insert '='}} {{10-10== }} + // expected-new-error@-5 {{expected module name in module selector}} + // expected-new-note@-6 {{insert module name}} {{10-10=<#identifier#>}} var main::decl1b = "b" - // expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{11-11=;}} - // expected-error@-2 {{expected module name in module selector}} + // expected-new-error@-1 {{expected '=' in variable}} + // expected-legacy-error@-2 {{consecutive statements on a line must be separated by ';'}} {{11-11=;}} expected-new-note@-2 {{insert '='}} {{11-11= = }} + // expected-error@-3 {{expected module name in module selector}} + // expected-new-note@-4 {{insert module name}} {{11-11=<#identifier#>}} let (main::decl1c, Swift::decl1d) = ("c", "d") - // expected-error@-1 {{expected ',' separator}} {{12-12=,}} - // expected-error@-2 {{expected pattern}} + // expected-legacy-error@-1 {{expected ',' separator}} {{12-12=,}} expected-new-error@-1 {{unexpected code '::decl1c, Swift::decl1d' in tuple pattern}} + // expected-legacy-error@-2 {{expected pattern}} if let (main::decl1e, Swift::decl1f) = Optional(("e", "f")) {} - // expected-error@-1 {{expected ',' separator}} {{15-15=,}} - // expected-error@-2 {{expected module name in module selector}} + // expected-legacy-error@-1 {{expected ',' separator}} {{15-15=,}} expected-new-error@-1 {{unexpected code '::decl1e, Swift::decl1f' in tuple}} + // expected-legacy-error@-2 {{expected module name in module selector}} guard let (main::decl1g, Swift::decl1h) = Optional(("g", "h")) else { return } - // expected-error@-1 {{expected ',' separator}} {{18-18=,}} - // expected-error@-2 {{expected module name in module selector}} + // expected-legacy-error@-1 {{expected ',' separator}} {{18-18=,}} expected-new-error@-1 {{unexpected code '::decl1g, Swift::decl1h' in tuple}} + // expected-legacy-error@-2 {{expected module name in module selector}} switch Optional(main::decl1g) { case Optional.some(let Swift::decl1i): - // expected-error@-1 {{expected ',' separator}} {{31-31=,}} - // expected-error@-2 {{expected module name in module selector}} + // expected-legacy-error@-1 {{expected ',' separator}} {{31-31=,}} expected-new-error@-1 {{unexpected code '::decl1i' in function call}} + // expected-legacy-error@-2 {{expected module name in module selector}} break case .none: break @@ -182,8 +199,8 @@ func testModuleSelectorIncorrectBindingDecls() { switch Optional(main::decl1g) { case let Optional.some(Swift::decl1j): - // expected-error@-1 {{expected ',' separator}} {{31-31=,}} - // expected-error@-2 {{expected module name in module selector}} + // expected-legacy-error@-1 {{expected ',' separator}} {{31-31=,}} expected-new-error@-1 {{unexpected code '::decl1j' in function call}} + // expected-legacy-error@-2 {{expected module name in module selector}} break case .none: break @@ -191,19 +208,19 @@ func testModuleSelectorIncorrectBindingDecls() { switch Optional(main::decl1g) { case let Swift::decl1k?: - // expected-error@-1 {{expected ':' after 'case'}} {{none}} - // expected-error@-2 {{expected module name in module selector}} - // expected-error@-3 {{consecutive statements on a line must be separated by ';'}} {{26-26=;}} - // expected-error@-4 {{expected expression}} + // expected-legacy-error@-1 {{expected ':' after 'case'}} {{none}} expected-new-error@-1 {{unexpected code '::decl1k?' in switch case}} + // expected-legacy-error@-2 {{expected module name in module selector}} + // expected-legacy-error@-3 {{consecutive statements on a line must be separated by ';'}} {{26-26=;}} + // expected-legacy-error@-4 {{expected expression}} break case .none: break } for main::decl1l in "lll" {} - // expected-error@-1 {{expected 'in' after for-each pattern}} {{none}} - // expected-error@-2 {{expected module name in module selector}} {{none}} - // expected-error@-3 {{expected '{' to start the body of for-each loop}} + // expected-legacy-error@-1 {{expected 'in' after for-each pattern}} {{none}} expected-new-error@-1 {{unexpected code '::decl1l' in 'for' statement}} + // expected-legacy-error@-2 {{expected module name in module selector}} {{none}} + // expected-legacy-error@-3 {{expected '{' to start the body of for-each loop}} } @@ -211,110 +228,117 @@ func testModuleSelectorIncorrectBindingDecls() { // This gets radically misinterpreted as two statements followed by some invalid code. "lll".forEach { [Swift::magnitude] main::elem in print(elem) - // expected-error@-1 {{expected expression}} - // expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{13-13=;}} + // expected-legacy-error@-1 {{expected expression}} expected-new-error@-1 {{unexpected code 'in print(elem)' in closure}} + // expected-legacy-error@-2 {{consecutive statements on a line must be separated by ';'}} {{13-13=;}} } "lll".forEach { (main::elem) in print(elem) } -// expected-error@-1 {{expected parameter name followed by ':'}} {{none}} -// expected-error@-2 {{expected ',' separator}} {{22-22=,}} +// expected-legacy-error@-1 {{expected parameter name followed by ':'}} {{none}} expected-new-error@-1 {{unexpected code '::elem' in parameter clause}} +// expected-legacy-error@-2 {{expected ',' separator}} {{22-22=,}} "lll".forEach { (main::elem) -> Void in print(elem) } -// expected-error@-1 {{expected parameter name followed by ':'}} {{none}} -// expected-error@-2 {{expected ',' separator}} {{22-22=,}} +// expected-legacy-error@-1 {{expected parameter name followed by ':'}} {{none}} expected-new-error@-1 {{unexpected code '::elem' in parameter clause}} +// expected-legacy-error@-2 {{expected ',' separator}} {{22-22=,}} "lll".forEach { (main::elem: Character) -> Void in print(elem) } -// expected-error@-1 {{expected parameter name followed by ':'}} -// expected-error@-2 {{expected ',' separator}} {{22-22=,}} +// expected-legacy-error@-1 {{expected parameter name followed by ':'}} expected-new-error@-1 {{unexpected code '::elem: Character' in parameter clause}} +// expected-legacy-error@-2 {{expected ',' separator}} {{22-22=,}} // ModuleSelectorIncorrectTypeDecls enum main::decl2 {} -// expected-error@-1 {{expected '{' in enum}} +// expected-legacy-error@-1 {{expected '{' in enum}} expected-new-error@-1 {{unexpected code '::decl2' in enum}} enum decl2_substitute { - // expected-note@-1 {{in declaration of 'decl2_substitute'}} + // expected-legacy-note@-1 {{in declaration of 'decl2_substitute'}} case Swift::decl2a - // expected-error@-1 {{expected declaration}} - // expected-error@-2 {{consecutive declarations on a line must be separated by ';'}} {{13-13=;}} + // expected-legacy-error@-1 {{expected declaration}} expected-new-error@-1 {{unexpected code '::decl2a' in enum}} + // expected-legacy-error@-2 {{consecutive declarations on a line must be separated by ';'}} {{13-13=;}} } struct main::decl3 {} -// expected-error@-1 {{expected '{' in struct}} +// expected-legacy-error@-1 {{expected '{' in struct}} expected-new-error@-1 {{unexpected code '::decl3' in struct}} class main::decl4 {} -// expected-error@-1 {{expected '{' in class}} +// expected-legacy-error@-1 {{expected '{' in class}} expected-new-error@-1 {{unexpected code '::decl4' in class}} typealias main::decl5 = Swift::Bool -// expected-error@-1 {{expected '=' in type alias declaration}} +// expected-legacy-error@-1 {{expected '=' in type alias declaration}} expected-new-error@-1 {{unexpected code '::decl5' in typealias declaration}} protocol main::decl6 {} -// expected-error@-1 {{expected '{' in protocol type}} +// expected-legacy-error@-1 {{expected '{' in protocol type}} expected-new-error@-1 {{unexpected code '::decl6' in protocol}} protocol decl6_substitute { - // expected-note@-1 {{in declaration of 'decl6_substitute'}} + // expected-legacy-note@-1 {{in declaration of 'decl6_substitute'}} associatedtype Swift::decl6a - // expected-error@-1 {{expected declaration}} - // expected-error@-2 {{consecutive declarations on a line must be separated by ';'}} {{23-23=;}} + // expected-legacy-error@-1 {{expected declaration}} expected-new-error@-1 {{unexpected code '::decl6a' in protocol}} + // expected-legacy-error@-2 {{consecutive declarations on a line must be separated by ';'}} {{23-23=;}} } // ModuleSelectorIncorrectGlobalVarDecls let main::decl7 = 7 -// expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{9-9=;}} -// expected-error@-2 {{expected module name in module selector}} +// expected-legacy-error@-1 {{consecutive statements on a line must be separated by ';'}} {{9-9=;}} expected-new-error@-1 {{expected '=' in variable}} +// expected-new-note@-2 {{insert '='}} {{9-9= = }} +// expected-error@-3 {{expected module name in module selector}} +// expected-new-note@-4 {{insert module name}} {{9-9=<#identifier#>}} var main::decl8 = 8 { -// expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{9-9=;}} -// expected-error@-2 {{expected module name in module selector}} -// expected-error@-3 {{consecutive statements on a line must be separated by ';'}} {{20-20=;}} -// expected-error@-4 {{top-level statement cannot begin with a closure expression}} +// expected-legacy-error@-1 {{consecutive statements on a line must be separated by ';'}} {{9-9=;}} expected-new-error@-1 {{expected '=' in variable}} +// expected-new-note@-2 {{insert '='}} {{9-9= = }} +// expected-error@-3 {{expected module name in module selector}} +// expected-new-note@-4 {{insert module name}} {{9-9=<#identifier#>}} +// expected-legacy-error@-5 {{consecutive statements on a line must be separated by ';'}} {{20-20=;}} +// expected-legacy-error@-6 {{top-level statement cannot begin with a closure expression}} willSet(Swift::newValue) {} + // expected-new-error@-1 {{unexpected code '::newValue' in accessor}} didSet(Foo::oldValue) {} + // expected-new-error@-1 {{unexpected code '::oldValue' in accessor}} } var decl8_willSet = 8 { willSet(Swift::newValue) {} -// expected-error@-1 {{expected ')' after willSet parameter name}} -// expected-note@-2 {{to match this opening '('}} -// expected-error@-3 {{expected '{' to start 'willSet' definition}} +// expected-legacy-error@-1 {{expected ')' after willSet parameter name}} expected-new-error@-1 {{unexpected code '::newValue' in accessor}} +// expected-legacy-note@-2 {{to match this opening '('}} +// expected-legacy-error@-3 {{expected '{' to start 'willSet' definition}} didSet(Foo::oldValue) {} +// expected-new-error@-1 {{unexpected code '::oldValue' in accessor}} } var decl8_didSet = 8 { willSet(newValue) {} didSet(Foo::oldValue) {} - // expected-error@-1 {{expected ')' after didSet parameter name}} - // expected-note@-2 {{to match this opening '('}} - // expected-error@-3 {{expected '{' to start 'didSet' definition}} + // expected-legacy-error@-1 {{expected ')' after didSet parameter name}} expected-new-error@-1 {{unexpected code '::oldValue' in accessor}} + // expected-legacy-note@-2 {{to match this opening '('}} + // expected-legacy-error@-3 {{expected '{' to start 'didSet' definition}} } // ModuleSelectorIncorrectNestedDecls struct Parent { - // expected-note@-1 {{in declaration of 'Parent'}} + // expected-legacy-note@-1 {{in declaration of 'Parent'}} func main::decl1() {} - // expected-error@-1 {{expected '(' in argument list of function declaration}} - // expected-error@-2 {{consecutive declarations on a line must be separated by ';'}} {{12-12=;}} - // expected-error@-3 {{expected declaration}} + // expected-legacy-error@-1 {{expected '(' in argument list of function declaration}} expected-new-error@-1 {{unexpected code '::decl1' before parameter clause}} + // expected-legacy-error@-2 {{consecutive declarations on a line must be separated by ';'}} {{12-12=;}} + // expected-legacy-error@-3 {{expected declaration}} enum main::decl2 {} - // expected-error@-1 {{expected '{' in enum}} + // expected-legacy-error@-1 {{expected '{' in enum}} expected-new-error@-1 {{unexpected code '::decl2' in enum}} enum decl2_substitute { - // expected-note@-1 {{in declaration of 'decl2_substitute'}} + // expected-legacy-note@-1 {{in declaration of 'decl2_substitute'}} case Swift::decl2a - // expected-error@-1 {{consecutive declarations on a line must be separated by ';'}} {{15-15=;}} - // expected-error@-2 {{expected declaration}} + // expected-legacy-error@-1 {{consecutive declarations on a line must be separated by ';'}} {{15-15=;}} expected-new-error@-1 {{unexpected code '::decl2a' in enum}} + // expected-legacy-error@-2 {{expected declaration}} } struct main::decl3 {} -// expected-error@-1 {{expected '{' in struct}} +// expected-legacy-error@-1 {{expected '{' in struct}} expected-new-error@-1 {{unexpected code '::decl3' in struct}} class main::decl4 {} -// expected-error@-1 {{expected '{' in class}} +// expected-legacy-error@-1 {{expected '{' in class}} expected-new-error@-1 {{unexpected code '::decl4' in class}} typealias main::decl5 = Swift::Bool -// expected-error@-1 {{expected '=' in type alias declaration}} +// expected-legacy-error@-1 {{expected '=' in type alias declaration}} expected-new-error@-1 {{unexpected code '::decl5' in typealias declaration}} } @@ -326,39 +350,45 @@ struct CreatesDeclExpectation { // ModuleSelectorIncorrectRuntimeBaseAttr @_swift_native_objc_runtime_base(main::BaseClass) -// expected-error@-1 {{expected ')' in '_swift_native_objc_runtime_base' attribute}} -// expected-error@-2 {{expected declaration}} +// expected-legacy-error@-1 {{expected ')' in '_swift_native_objc_runtime_base' attribute}} FIXME: Should be diagnosed in ASTGen +// expected-legacy-error@-2 {{expected declaration}} class C1 {} // ModuleSelectorOperatorDecls infix operator <<<<< : Swift::AdditionPrecedence -// expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{29-29=;}} -// expected-error@-2 {{expected module name in module selector}} +// expected-legacy-error@-1 {{consecutive statements on a line must be separated by ';'}} {{29-29=;}} expected-new-error@-1 {{consecutive statements on a line must be separated by newline or ';'}} +// expected-new-note@-2 {{insert newline}} {{29-29=\n}} +// expected-new-note@-3 {{insert ';'}} {{29-29=;}} +// expected-error@-4 {{expected module name in module selector}} +// expected-new-note@-5 {{insert module name}} {{29-29=<#identifier#>}} precedencegroup main::PG1 {} -// expected-error@-1 {{expected '{' after name of precedence group}} +// expected-legacy-error@-1 {{expected '{' after name of precedence group}} expected-new-error@-1 {{unexpected code '::PG1' in precedencegroup}} precedencegroup PG1_substitute { higherThan: Swift::AdditionPrecedence -// expected-error@-1 {{expected operator attribute identifier in precedence group body}} +// expected-legacy-error@-1 {{expected operator attribute identifier in precedence group body}} expected-new-error@-1 {{unexpected code '::AdditionPrecedence' in precedencegroup}} } // ModuleSelectorIllFormedModuleNames var a: ::Int // expected-error@-1 {{expected module name in module selector}} +// expected-new-note@-2 {{insert module name}} {{8-8=<#identifier#>}} var b: (::Int) // expected-error@-1 {{expected module name in module selector}} +// expected-new-note@-2 {{insert module name}} {{9-9=<#identifier#>}} var c: *::Int -// expected-error@-1 {{expected type}} -// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} -// expected-error@-3 {{expected module name in module selector}} +// expected-legacy-error@-1 {{expected type}} expected-new-error@-1 {{expected type in type annotation}} +// expected-new-note@-2 {{insert type}} {{8-8=<#type#>}} +// expected-legacy-error@-3 {{consecutive statements on a line must be separated by ';'}} expected-new-error@-3 {{unexpected code '*::Int' before variable}} +// expected-legacy-error@-4 {{expected module name in module selector}} var d: _::Int // expected-error@-1 {{'_' cannot be used as an identifier here}} -// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{8-9=`_`}} +// expected-legacy-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{8-9=`_`}} var e: Self::Int // expected-error@-1 {{keyword 'Self' cannot be used as an identifier here}} @@ -369,7 +399,14 @@ var f: self::Int // expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{8-12=`self`}} var g: inout::Int -// expected-error@-1 {{expected module name in module selector}} +// expected-new-error@-1 {{expected type in type annotation}} +// expected-new-note@-2 {{insert type}} {{8-8=<#type#>}} +// expected-new-error@-3 {{expected pattern in variable}} +// expected-new-note@-4 {{insert pattern}} {{13-13=<#pattern#> }} +// expected-new-error@-5 {{expected '=' in variable}} +// expected-new-note@-6 {{insert '='}} {{13-13== }} +// expected-legacy-error@-7 {{expected module name in module selector}} expected-new-error@-7 {{expected module name in module selector}} +// expected-new-note@-8 {{insert module name}} {{13-13=<#identifier#>}} var h: Any::Int // expected-error@-1 {{keyword 'Any' cannot be used as an identifier here}} @@ -377,22 +414,25 @@ var h: Any::Int var aArray: [::Int] // expected-error@-1 {{expected module name in module selector}} +// expected-new-note@-2 {{insert module name}} {{14-14=<#identifier#>}} var bArray: [(::Int)] // expected-error@-1 {{expected module name in module selector}} +// expected-new-note@-2 {{insert module name}} {{15-15=<#identifier#>}} var cArray: [*::Int] -// expected-error@-1 {{expected element type}} -// expected-error@-2 {{expected ']' in array type}} -// expected-note@-3 {{to match this opening '['}} -// expected-error@-4 {{consecutive statements on a line must be separated by ';'}} {{14-14=;}} -// expected-error@-5 {{expected module name in module selector}} -// expected-error@-6 {{consecutive statements on a line must be separated by ';'}} {{20-20=;}} -// expected-error@-7 {{expected expression}} +// expected-legacy-error@-1 {{expected element type}} expected-new-error@-1 {{expected type in array type}} +// expected-new-note@-2 {{insert type}} {{14-14=<#type#>}} +// expected-legacy-error@-3 {{expected ']' in array type}} +// expected-legacy-note@-4 {{to match this opening '['}} +// expected-legacy-error@-5 {{consecutive statements on a line must be separated by ';'}} {{14-14=;}} expected-new-error@-5 {{unexpected code '*::Int' in array type}} +// expected-legacy-error@-6 {{expected module name in module selector}} +// expected-legacy-error@-7 {{consecutive statements on a line must be separated by ';'}} {{20-20=;}} +// expected-legacy-error@-8 {{expected expression}} var dArray: [_::Int] // expected-error@-1 {{'_' cannot be used as an identifier here}} -// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{14-15=`_`}} +// expected-legacy-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{14-15=`_`}} var eArray: [Self::Int] // expected-error@-1 {{keyword 'Self' cannot be used as an identifier here}} @@ -403,7 +443,15 @@ var fArray: [self::Int] // expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{14-18=`self`}} var gArray: [inout::Int] -// expected-error@-1 {{expected module name in module selector}} +// expected-new-error@-1 {{expected type and ']' to end array type}} +// expected-new-note@-2 {{insert type and ']'}} {{14-14=<#type#>}} {{14-14=]}} +// expected-new-error@-3 {{expected pattern in variable}} +// expected-new-note@-4 {{insert pattern}} {{19-19=<#pattern#> }} +// expected-new-error@-5 {{expected '=' in variable}} +// expected-new-note@-6 {{insert '='}} {{19-19== }} +// expected-error@-7 {{expected module name in module selector}} +// expected-new-note@-8 {{insert module name}} {{19-19=<#identifier#>}} +// expected-new-error@-9 {{unexpected code ']' before variable}} var hArray: [Any::Int] // expected-error@-1 {{keyword 'Any' cannot be used as an identifier here}} @@ -411,16 +459,19 @@ var hArray: [Any::Int] var aIndex: String.::Index // expected-error@-1 {{expected module name in module selector}} +// expected-new-note@-2 {{insert module name}} {{20-20=<#identifier#>}} // FIXME: This gets interpreted as a single `.*` operator; may not be ideal. var cIndex: String.*::Index -// expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{19-19=;}} -// expected-error@-2 {{expected expression after unary operator}} -// expected-error@-3 {{expected module name in module selector}} +// expected-legacy-error@-1 {{consecutive statements on a line must be separated by ';'}} {{19-19=;}} expected-new-error@-1 {{consecutive statements on a line must be separated by newline or ';'}} +// expected-new-note@-2 {{insert newline}} {{19-19=\n}} +// expected-new-note@-3 {{insert ';'}} {{19-19=;}} +// expected-legacy-error@-4 {{expected expression after unary operator}} expected-new-error@-4 {{unexpected code '.*::Index' before variable}} +// expected-legacy-error@-5 {{expected module name in module selector}} var dIndex: String._::Index // expected-error@-1 {{'_' cannot be used as an identifier here}} -// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{20-21=`_`}} +// expected-legacy-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{20-21=`_`}} var eIndex: String.Self::Index // expected-error@-1 {{keyword 'Self' cannot be used as an identifier here}} @@ -431,9 +482,11 @@ var fIndex: String.self::Index // expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{20-24=`self`}} var gIndex: String.inout::Index -// expected-error@-1 {{expected identifier in dotted type}} -// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{20-20=;}} -// expected-error@-3 {{expected expression}} +// expected-legacy-error@-1 {{expected identifier in dotted type}} expected-new-error@-1 {{expected '=' in variable}} +// expected-new-note@-2 {{insert '='}} {{25-25= = }} +// expected-legacy-error@-3 {{consecutive statements on a line must be separated by ';'}} {{20-20=;}} +// expected-legacy-error@-4 {{expected expression}} expected-new-error@-4 {{expected module name in module selector}} +// expected-new-note@-5 {{insert module name}} {{25-25=<#identifier#>}} var hIndex: String.Any::Index // expected-error@-1 {{keyword 'Any' cannot be used as an identifier here}} @@ -442,22 +495,24 @@ var hIndex: String.Any::Index func inExpr() { ::print() // expected-error@-1 {{expected module name in module selector}} +// expected-new-note@-2 {{insert module name}} {{-1:16-+0:3=}} {{-1:16-16=\n <#identifier#>}} } func inExpr() { (::print()) // expected-error@-1 {{expected module name in module selector}} +// expected-new-note@-2 {{insert module name}} {{4-4=<#identifier#>}} } func inExpr() { *::print() -// expected-error@-1 {{expected module name in module selector}} +// expected-legacy-error@-1 {{expected module name in module selector}} expected-new-error@-1 {{unexpected code '*::print()' in function}} } func inExpr() { _::print() // expected-error@-1 {{'_' cannot be used as an identifier here}} -// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{3-4=`_`}} +// expected-legacy-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{3-4=`_`}} } func inExpr() { @@ -474,7 +529,12 @@ func inExpr() { func inExpr() { inout::print() -// expected-error@-1 {{expected expression}} +// expected-legacy-error@-1 {{expected expression}} expected-new-error@-1 {{expected pattern in variable}} +// expected-new-note@-2 {{insert pattern}} {{8-8=<#pattern#> }} +// expected-new-error@-3 {{expected '=' in variable}} +// expected-new-note@-4 {{insert '='}} {{8-8== }} +// expected-new-error@-5 {{expected module name in module selector}} +// expected-new-note@-6 {{insert module name}} {{8-8=<#identifier#>}} } func inExpr() { @@ -486,23 +546,29 @@ func inExpr() { func inExpr() { _ = 1.::magnitude // expected-error@-1 {{expected module name in module selector}} +// expected-new-note@-2 {{insert module name}} {{9-9=<#identifier#>}} } func inExpr() { _ = (1.::magnitude) // expected-error@-1 {{expected module name in module selector}} +// expected-new-note@-2 {{insert module name}} {{10-10=<#identifier#>}} } // FIXME: This gets interpreted as a single `.*` operator; may not be ideal. func inExpr() { _ = 1.*::magnitude -// expected-error@-1 {{expected module name in module selector}} +// expected-new-error@-1 {{consecutive statements on a line must be separated by newline or ';'}} +// expected-new-note@-2 {{insert newline}} {{10-10=\n }} +// expected-new-note@-3 {{insert ';'}} {{10-10=;}} +// expected-error@-4 {{expected module name in module selector}} +// expected-new-note@-5 {{insert module name}} {{10-10=<#identifier#>}} } func inExpr() { _ = 1._::magnitude // expected-error@-1 {{'_' cannot be used as an identifier here}} -// expected-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{9-10=`_`}} +// expected-legacy-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{9-10=`_`}} } func inExpr() { @@ -519,8 +585,11 @@ func inExpr() { func inExpr() { _ = 1.inout::magnitude -// expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{14-14=;}} -// expected-error@-2 {{expected module name in module selector}} +// expected-legacy-error@-1 {{consecutive statements on a line must be separated by ';'}} {{14-14=;}} expected-new-error@-1 {{consecutive statements on a line must be separated by newline or ';'}} +// expected-new-note@-2 {{insert newline}} {{14-14=\n }} +// expected-new-note@-3 {{insert ';'}} {{14-14=;}} +// expected-error@-4 {{expected module name in module selector}} +// expected-new-note@-5 {{insert module name}} {{14-14=<#identifier#>}} } func inExpr() { @@ -532,33 +601,33 @@ func inExpr() { // ModuleSelectorAttrs @_spi(main::Private) -// expected-error@-1 {{expected ')' in '_spi' attribute}} {{none}} -// expected-error@-2 {{expected declaration}} +// expected-legacy-error@-1 {{expected ')' in '_spi' attribute}} {{none}} FIXME: 'main::Private' should be diagnosed in ASTGen +// expected-legacy-error@-2 {{expected declaration}} public struct BadImplementsAttr: CustomStringConvertible {} @_implements(main::CustomStringConvertible, Swift::description) -// expected-error@-1 {{expected ')' in '_implements' attribute}} -// expected-note@-2 {{to match this opening '('}} -// expected-error@-3 {{expected declaration}} +// expected-legacy-error@-1 {{expected ')' in '_implements' attribute}} FIXME: 'Swift::description' should be diagnosed in ASTGen +// expected-legacy-note@-2 {{to match this opening '('}} +// expected-legacy-error@-3 {{expected declaration}} public var stringValue: String { fatalError() } @_specialize(target: main::fn(), spi: Swift::Private, where T == Swift::Int) -// expected-error@-1 {{missing ',' in '_specialize' attribute}} {{none}} -// expected-error@-2 {{missing ',' in '_specialize' attribute}} {{none}} +// expected-legacy-error@-1 {{missing ',' in '_specialize' attribute}} {{none}} FIXME: 'main::fn()' should be diagnosed in ASTGen +// expected-legacy-error@-2 {{missing ',' in '_specialize' attribute}} {{none}} expected-new-error@-2 {{unexpected code '::Private, where T == Swift::Int' in attribute}} public func fn() -> T { fatalError() } func fn(_: @isolated(Swift::any) () -> Void) {} -// expected-error@-1 {{expected 'any' as the isolation kind}} -// expected-error@-2 {{expected ')' after isolation kind}} {{none}} -// expected-note@-3 {{to match this opening '('}} -// expected-error@-4 {{expected module name in module selector}} -// expected-error@-5 {{consecutive statements on a line must be separated by ';'}} {{44-44=;}} -// expected-error@-6 {{expected expression}} -// expected-error@-7 {{cannot have more than one parameter list}} FIXME: wat? +// expected-legacy-error@-1 {{expected 'any' as the isolation kind}} expected-new-error@-1 {{unexpected code '::any' in attribute}} +// expected-legacy-error@-2 {{expected ')' after isolation kind}} {{none}} +// expected-legacy-note@-3 {{to match this opening '('}} +// expected-legacy-error@-4 {{expected module name in module selector}} +// expected-legacy-error@-5 {{consecutive statements on a line must be separated by ';'}} {{44-44=;}} +// expected-legacy-error@-6 {{expected expression}} +// expected-legacy-error@-7 {{cannot have more than one parameter list}} FIXME: wat? @_documentation(metadata: Swift::GroupName) -// expected-error@-1 {{expected ',' separator}} {{32-32=,}} -// expected-error@-2 {{'_documentation' attribute expected 'visibility' or 'metadata' argument}} +// expected-legacy-error@-1 {{expected ',' separator}} {{32-32=,}} expected-new-error@-1 {{unexpected code '::GroupName' in attribute}} +// expected-legacy-error@-2 {{'_documentation' attribute expected 'visibility' or 'metadata' argument}} func fn() {} @derivative(of: Swift::Foo.Swift::Bar.Swift::baz(), wrt: quux) @@ -570,73 +639,90 @@ let x = Swift::do { 1 } let x = Swift:: do { 1 } -// expected-error@-2 {{expected identifier after module selector}} -// expected-note@-3 {{remove extraneous whitespace after '::'}} {{16-+1:1=}} +// expected-legacy-error@-2 {{expected identifier after module selector}} expected-new-error@-2 {{expected identifier in variable}} +// expected-legacy-note@-3 {{remove extraneous whitespace after '::'}} {{16-+1:1=}} expected-new-note@-3 {{insert identifier}} {{16-16=<#identifier#>}} let x = Swift::if y { 1 } else { 0 } -// expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{18-18=;}} -// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{26-26=;}} -// expected-error@-3 {{expected expression}} +// expected-legacy-error@-1 {{consecutive statements on a line must be separated by ';'}} {{18-18=;}} expected-new-error@-1 {{consecutive statements on a line must be separated by newline or ';'}} +// expected-new-note@-2 {{insert newline}} {{18-19= \n}} +// expected-new-note@-3 {{insert ';'}} {{18-19=}} {{19-19=; }} +// expected-legacy-error@-4 {{consecutive statements on a line must be separated by ';'}} {{26-26=;}} expected-new-error@-4 {{consecutive statements on a line must be separated by newline or ';'}} +// expected-new-note@-5 {{insert newline}} {{26-27= \n}} +// expected-new-note@-6 {{insert ';'}} {{26-27=}} {{27-27=;}} +// expected-legacy-error@-7 {{expected expression}} expected-new-error@-7 {{unexpected code 'else { 0 }' before variable}} let x = Swift:: if y { 1 } else { 0 } -// expected-error@-2 {{expected identifier after module selector}} -// expected-note@-3 {{remove extraneous whitespace after '::'}} {{16-+1:1=}} +// expected-legacy-error@-2 {{expected identifier after module selector}} expected-new-error@-2 {{expected identifier in variable}} +// expected-legacy-note@-3 {{remove extraneous whitespace after '::'}} {{16-+1:1=}} expected-new-note@-3 {{insert identifier}} {{16-16=<#identifier#>}} let x = Swift::switch y { -// expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{22-22=;}} -// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{24-24=;}} - // expected-error@-3 {{top-level statement cannot begin with a closure expression}} +// expected-legacy-error@-1 {{consecutive statements on a line must be separated by ';'}} {{22-22=;}} expected-new-error@-1 {{consecutive statements on a line must be separated by newline or ';'}} +// expected-new-note@-2 {{insert newline}} {{22-23= \n}} +// expected-new-note@-3 {{insert ';'}} {{22-23=}} {{23-23=; }} +// expected-legacy-error@-4 {{consecutive statements on a line must be separated by ';'}} {{24-24=;}} expected-new-error@-4 {{consecutive statements on a line must be separated by newline or ';'}} +// expected-new-note@-5 {{insert newline}} {{24-25= \n}} +// expected-new-note@-6 {{insert ';'}} {{24-25=}} {{25-25=; }} + // expected-legacy-error@-7 {{top-level statement cannot begin with a closure expression}} case true: 1 -// expected-error@-1 {{'case' label can only appear inside a 'switch' statement}} +// expected-legacy-error@-1 {{'case' label can only appear inside a 'switch' statement}} expected-new-error@-1 {{'case' can only appear inside a 'switch' statement or 'enum' declaration}} case false: 0 -// expected-error@-1 {{'case' label can only appear inside a 'switch' statement}} +// expected-legacy-error@-1 {{'case' label can only appear inside a 'switch' statement}} expected-new-error@-1 {{'case' can only appear inside a 'switch' statement or 'enum' declaration}} } let x = Swift:: -// expected-error@-1 {{expected identifier after module selector}} -// expected-note@-2 {{remove extraneous whitespace after '::'}} {{16-+3:1=}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier in variable}} +// expected-legacy-note@-2 {{remove extraneous whitespace after '::'}} {{16-+3:1=}} expected-new-note@-2 {{insert identifier}} {{16-16=<#identifier#>}} switch y { case true: 1 case false: 0 } fn(Swift::&x) -// expected-error@-1 {{expected identifier after module selector}} -// expected-error@-2 {{expected ',' separator}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier in function call}} +// expected-new-note@-2 {{insert identifier}} {{11-11=<#identifier#>}} +// expected-legacy-error@-3 {{expected ',' separator}} expected-new-error@-3 {{unexpected code '&x' in function call}} _ = Swift::\main::Foo.BarKit::bar -// expected-error@-1 {{expected identifier after module selector}} -// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier}} +// expected-new-note@-2 {{insert identifier}} {{12-12=<#identifier#>}} +// expected-legacy-error@-3 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} _ = \main::Foo.BarKit::bar _ = Swift::-x -// expected-error@-1 {{expected identifier after module selector}} -// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier}} +// expected-new-note@-2 {{insert identifier}} {{12-12=<#identifier#>}} +// expected-legacy-error@-3 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} _ = Swift::1 -// expected-error@-1 {{expected identifier after module selector}} -// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier}} +// expected-new-note@-2 {{insert identifier}} {{12-12=<#identifier#>}} +// expected-legacy-error@-3 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} _ = Swift::1.0 -// expected-error@-1 {{expected identifier after module selector}} -// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier}} +// expected-new-note@-2 {{insert identifier}} {{12-12=<#identifier#>}} +// expected-legacy-error@-3 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} func fn() { _ = Swift::@"fnord" - // expected-error@-1 {{expected identifier after module selector}} - // expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{14-14=;}} - // expected-error@-3 {{string literals in Swift are not preceded by an '@' sign}} + // expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier}} + // expected-new-note@-2 {{insert identifier}} {{14-14=<#identifier#>}} + // expected-legacy-error@-3 {{consecutive statements on a line must be separated by ';'}} {{14-14=;}} + // expected-error@-4 {{string literals in Swift are not preceded by an '@' sign}} + // expected-new-note@-5 {{remove '@'}} {{14-15=}} } _ = Swift::"fnord" -// expected-error@-1 {{expected identifier after module selector}} -// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier}} +// expected-new-note@-2 {{insert identifier}} {{12-12=<#identifier#>}} +// expected-legacy-error@-3 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} _ = Swift::/fnord/ -// expected-error@-1 {{expected identifier after module selector}} -// expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier}} +// expected-new-note@-2 {{insert identifier}} {{12-12=<#identifier#>}} +// expected-legacy-error@-3 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} _ = Swift::nil @@ -652,12 +738,12 @@ func fn() { } @attached(extension, names: Swift::deinit) macro m() -// expected-error@-1 {{unknown introduced name kind 'Swift'}} -// expected-error@-2 {{expected '{' for deinitializer}} +// expected-legacy-error@-1 {{unknown introduced name kind 'Swift'}} FIXME: 'Swift::' should be diagnosed by ASTGen +// expected-legacy-error@-2 {{expected '{' for deinitializer}} @attached(extension, names: Swift::subscript) macro m() -// expected-error@-1 {{unknown introduced name kind 'Swift'}} -// expected-error@-2 {{expected '(' for subscript parameters}} +// expected-legacy-error@-1 {{unknown introduced name kind 'Swift'}} FIXME: 'Swift::' should be diagnosed by ASTGen +// expected-legacy-error@-2 {{expected '(' for subscript parameters}} _ = Swift::Self @@ -665,49 +751,62 @@ _ = Swift::Any _ = { _ = Swift::$0 - // expected-error@-1 {{expected identifier after module selector}} - // expected-error@-2 {{consecutive statements on a line must be separated by ';'}} {{14-14=;}} + // expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier}} + // expected-new-note@-2 {{insert identifier}} {{14-14=<#identifier#>}} + // expected-legacy-error@-3 {{consecutive statements on a line must be separated by ';'}} {{14-14=;}} } _ = Swift::$foo +// FIXME: Legacy parser considers `_` a keyword; new parser probably should too _ = Swift::_ +// expected-new-error@-1 {{expected identifier}} +// expected-new-note@-2 {{insert identifier}} {{12-12=<#identifier#>}} Swift::_ = 1 +// expected-new-error@-1 {{expected identifier}} +// expected-new-note@-2 {{insert identifier}} {{8-8=<#identifier#>}} _ = Swift::#foo -// expected-error@-1 {{consecutive statements on a line must be separated by ';'}} {{12-12=;}} -// expected-error@-2 {{expected identifier after module selector}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier}} +// expected-new-note@-2 {{insert identifier}} {{12-12=<#identifier#>}} +// expected-legacy-error@-3 {{consecutive statements on a line must be separated by ';'}} _ = #Swift::foo _ = Swift::{ 1 } -// expected-error@-1 {{expected identifier after module selector}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier in function call}} +// expected-new-note@-2 {{insert identifier}} {{12-12=<#identifier#> }} _ = Swift::.random() -// expected-error@-1 {{expected identifier after module selector}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier in member access}} +// expected-new-note@-2 {{insert identifier}} {{12-12=<#identifier#>}} _ = Swift::.main::random() -// expected-error@-1 {{expected identifier after module selector}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier in member access}} +// expected-new-note@-2 {{insert identifier}} {{12-12=<#identifier#>}} _ = .main::random() _ = Swift::super.foo() _ = Swift::(a, b) -// expected-error@-1 {{expected identifier after module selector}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier in function call}} +// expected-new-note@-2 {{insert identifier}} {{12-12=<#identifier#>}} _ = Swift::[a, b] -// expected-error@-1 {{expected identifier after module selector}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier in subscript}} +// expected-new-note@-2 {{insert identifier}} {{12-12=<#identifier#>}} _ = Swift:: -// expected-error@-1 {{expected identifier after module selector}} -// expected-note@-2 {{remove extraneous whitespace after '::'}} {{12-+4:1=}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier}} +// expected-legacy-note@-2 {{remove extraneous whitespace after '::'}} {{12-+4:1=}} expected-new-note@-2 {{insert identifier}} {{12-12=<#identifier#>}} _ = x.Swift::y _ = x.Swift::1 -// expected-error@-1 {{expected identifier after module selector}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier in member access}} +// expected-new-note@-2 {{insert identifier}} {{14-14=<#identifier#>}} _ = x.Swift::self @@ -720,8 +819,9 @@ _ = x.Swift::Protocol.self _ = myArray.reduce(0, Swift::+) if Swift::#available(macOS 15, *) {} -// expected-error@-1 {{expected identifier after module selector}} -// expected-error@-2 {{expected '{' after 'if' condition}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier in 'if' statement}} +// expected-new-note@-2 {{insert identifier}} {{11-11=<#identifier#> }} +// expected-legacy-error@-3 {{expected '{' after 'if' condition}} expected-new-error@-3 {{unexpected code '#available(macOS 15, *)' in 'if' statement}} func fn(_: Swift::Self) {} @@ -730,15 +830,24 @@ func fn(_: Swift::Any) {} func fn(_: Swift::Foo) {} func fn(_: Swift::(Int, String)) {} -// expected-error@-1 {{expected identifier after module selector}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier in type}} +// expected-new-note@-2 {{insert identifier}} {{19-19=<#identifier#>}} +// expected-new-error@-3 {{unexpected code '(Int, String)' in parameter clause}} func fn(_: Swift::[Int]) {} -// expected-error@-1 {{expected identifier after module selector}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier in type}} +// expected-new-note@-2 {{insert identifier}} {{19-19=<#identifier#>}} +// expected-new-error@-3 {{unexpected code '[Int]' in parameter clause}} +// FIXME: Legacy parser considers `_` a keyword; new parser probably should too func fn(_: Swift::_) {} +// expected-new-error@-1 {{expected identifier in type}} +// expected-new-note@-2 {{insert identifier}} {{19-19=<#identifier#>}} +// expected-new-error@-3 {{unexpected code '_' in parameter clause}} func fn(_: Swift::) {} -// expected-error@-1 {{expected identifier after module selector}} +// expected-legacy-error@-1 {{expected identifier after module selector}} expected-new-error@-1 {{expected identifier in type}} +// expected-new-note@-2 {{insert identifier}} {{19-19=<#identifier#>}} func fn(_: Foo.Swift::Type) {} @@ -752,13 +861,13 @@ func fn(_: Foo.Swift::self) {} // ModuleSelectorSubmodule _ = Foundation::NSData::NSData() -// expected-error@-1 {{module selector cannot specify a submodule}} {{17-25=}} +// expected-legacy-error@-1 {{module selector cannot specify a submodule}} {{17-25=}} expected-new-error@-1 {{unexpected code 'NSData::' in module selector}} _ = Foundation::NSData::Fnord::NSData() -// expected-error@-1 {{module selector cannot specify a submodule}} {{17-32=}} +// expected-legacy-error@-1 {{module selector cannot specify a submodule}} {{17-32=}} expected-new-error@-1 {{unexpected code 'NSData::Fnord::' in module selector}} _ = Foundation::NSData:: Fnord::NSData() -// expected-error@-2 {{module selector cannot specify a submodule}} {{17-25=}} -// expected-error@-3 {{expected identifier after module selector}} -// expected-note@-4 {{remove extraneous whitespace after '::'}} {{25-+1:1=}} +// expected-legacy-error@-2 {{module selector cannot specify a submodule}} {{17-25=}} expected-new-error@-2 {{unexpected code 'NSData::' in module selector}} +// expected-legacy-error@-3 {{expected identifier after module selector}} expected-new-error@-3 {{expected identifier}} +// expected-legacy-note@-4 {{remove extraneous whitespace after '::'}} {{25-+1:1=}} expected-new-note@-4 {{insert identifier}} {{25-25=<#identifier#>}}