diff --git a/include/swift/AST/ASTBridging.h b/include/swift/AST/ASTBridging.h index 4e64241bdf7d4..9932b2a9741e1 100644 --- a/include/swift/AST/ASTBridging.h +++ b/include/swift/AST/ASTBridging.h @@ -146,21 +146,29 @@ 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; - size_t NumArgumentLabels; + uint32_t NumArgumentLabels; + bool HasModuleSelectorLoc; public: - BridgedDeclNameLoc() : LocationInfo(nullptr), NumArgumentLabels(0) {} + BridgedDeclNameLoc() + : LocationInfo(nullptr), NumArgumentLabels(0), HasModuleSelectorLoc(false) + {} BRIDGED_INLINE BridgedDeclNameLoc(swift::DeclNameLoc loc); @@ -941,11 +949,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 +1285,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:)") @@ -2544,9 +2555,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:)") @@ -2580,8 +2592,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:" @@ -2606,8 +2618,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/include/swift/AST/ASTBridgingImpl.h b/include/swift/AST/ASTBridgingImpl.h index 06aed90209ee8..adfb9c7f39619 100644 --- a/include/swift/AST/ASTBridgingImpl.h +++ b/include/swift/AST/ASTBridgingImpl.h @@ -60,10 +60,12 @@ swift::DeclNameRef BridgedDeclNameRef::unbridged() const { BridgedDeclNameLoc::BridgedDeclNameLoc(swift::DeclNameLoc loc) : LocationInfo(loc.LocationInfo), - NumArgumentLabels(loc.NumArgumentLabels) {} + NumArgumentLabels(loc.NumArgumentLabels), + HasModuleSelectorLoc(loc.HasModuleSelectorLoc) {} swift::DeclNameLoc BridgedDeclNameLoc::unbridged() const { - return swift::DeclNameLoc(LocationInfo, NumArgumentLabels); + return swift::DeclNameLoc(LocationInfo, NumArgumentLabels, + HasModuleSelectorLoc); } //===----------------------------------------------------------------------===// 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/AST/Decl.h b/include/swift/AST/Decl.h index 85d8f2b98222c..b9ce067a4d4ea 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -3038,11 +3038,10 @@ class ValueDecl : public Decl { return Name.getBaseIdentifier(); } - /// Generates a DeclNameRef referring to this declaration with as much - /// specificity as possible. - DeclNameRef createNameRef() const { - return DeclNameRef(Name); - } + /// Generates a DeclNameRef referring to this declaration. + /// + /// \param moduleSelector If true, the name ref includes the module name. + DeclNameRef createNameRef(bool moduleSelector = false) const; /// Retrieve the C declaration name that names this function, or empty /// string if it has none. diff --git a/include/swift/AST/DeclNameLoc.h b/include/swift/AST/DeclNameLoc.h index 494a4ae721faf..85dbb946c3108 100644 --- a/include/swift/AST/DeclNameLoc.h +++ b/include/swift/AST/DeclNameLoc.h @@ -35,61 +35,69 @@ class DeclNameLoc { /// Source location information. /// - /// If \c NumArgumentLabels == 0, this is the SourceLoc for the base name. - /// Otherwise, it points to an array of SourceLocs, which contains: + /// If \c NumArgumentLabels == 0 and \c !HasModuleSelectorLoc, this is the + /// SourceLoc for the base name. Otherwise, it points to an array of + /// SourceLocs, which contains: /// * The base name location + /// * The module selector location /// * The left parentheses location /// * The right parentheses location /// * The locations of each of the argument labels. const void *LocationInfo; /// The number of argument labels stored in the name. - unsigned NumArgumentLabels; + uint32_t NumArgumentLabels; + bool HasModuleSelectorLoc; enum { BaseNameIndex = 0, - LParenIndex = 1, - RParenIndex = 2, - FirstArgumentLabelIndex = 3, + ModuleSelectorIndex = 1, + LParenIndex = 2, + RParenIndex = 3, + FirstArgumentLabelIndex = 4, }; /// Retrieve a pointer to either the only source location that was /// stored or to the array of source locations that was stored. SourceLoc const * getSourceLocs() const { - if (NumArgumentLabels == 0) + if (NumArgumentLabels == 0 && !HasModuleSelectorLoc) return reinterpret_cast(&LocationInfo); return reinterpret_cast(LocationInfo); } - DeclNameLoc(const void *LocationInfo, unsigned NumArgumentLabels) - : LocationInfo(LocationInfo), NumArgumentLabels(NumArgumentLabels) {} + DeclNameLoc(const void *LocationInfo, unsigned NumArgumentLabels, + bool HasModuleSelectorLoc) + : LocationInfo(LocationInfo), NumArgumentLabels(NumArgumentLabels), + HasModuleSelectorLoc(HasModuleSelectorLoc) {} public: /// Create an invalid declaration name location. - DeclNameLoc() : DeclNameLoc(nullptr, 0) {} + DeclNameLoc() : DeclNameLoc(nullptr, 0, false) {} /// Create declaration name location information for a base name. explicit DeclNameLoc(SourceLoc baseNameLoc) - : DeclNameLoc(baseNameLoc.getOpaquePointerValue(), 0) {} + : DeclNameLoc(baseNameLoc.getOpaquePointerValue(), 0, false) {} explicit DeclNameLoc(ASTContext &ctx, SourceLoc moduleSelectorLoc, SourceLoc baseNameLoc) - : DeclNameLoc(baseNameLoc) { } + : DeclNameLoc(ctx, moduleSelectorLoc, baseNameLoc, + SourceLoc(), {}, SourceLoc()) { } /// Create declaration name location information for a compound /// name. DeclNameLoc(ASTContext &ctx, SourceLoc baseNameLoc, SourceLoc lParenLoc, ArrayRef argumentLabelLocs, - SourceLoc rParenLoc); + SourceLoc rParenLoc) + : DeclNameLoc(ctx, SourceLoc(), baseNameLoc, + lParenLoc, argumentLabelLocs, rParenLoc) { } DeclNameLoc(ASTContext &ctx, SourceLoc moduleSelectorLoc, SourceLoc baseNameLoc, SourceLoc lParenLoc, ArrayRef argumentLabelLocs, - SourceLoc rParenLoc) - : DeclNameLoc(ctx, baseNameLoc, lParenLoc, argumentLabelLocs, rParenLoc) { } + SourceLoc rParenLoc); /// Whether the location information is valid. bool isValid() const { return getBaseNameLoc().isValid(); } @@ -125,11 +133,12 @@ class DeclNameLoc { } SourceLoc getModuleSelectorLoc() const { - return SourceLoc(); + if (!HasModuleSelectorLoc) return SourceLoc(); + return getSourceLocs()[ModuleSelectorIndex]; } SourceLoc getStartLoc() const { - return getBaseNameLoc(); + return HasModuleSelectorLoc ? getModuleSelectorLoc() : getBaseNameLoc(); } SourceLoc getEndLoc() const { @@ -138,9 +147,7 @@ class DeclNameLoc { /// Retrieve the complete source range for this declaration name. SourceRange getSourceRange() const { - if (NumArgumentLabels == 0) return getBaseNameLoc(); - - return SourceRange(getBaseNameLoc(), getRParenLoc()); + return SourceRange(getStartLoc(), getEndLoc()); } }; diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def index 58ef352b0a138..454d28fb8a59d 100644 --- a/include/swift/AST/DiagnosticsParse.def +++ b/include/swift/AST/DiagnosticsParse.def @@ -93,6 +93,17 @@ 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", ()) +NOTE(replace_module_selector_with_member_lookup,none, + "replace '::' with '.'", ()) + //------------------------------------------------------------------------------ // MARK: Lexer diagnostics //------------------------------------------------------------------------------ @@ -2199,5 +2210,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/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index d0ae00504ae86..ed734eb08848b 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -1193,6 +1193,16 @@ ERROR(cannot_find_type_in_cast_expression,none, "type-casting operator expects a type on its right-hand side (got: %kind0)", (const ValueDecl *)) ERROR(cannot_find_type_in_scope_did_you_mean,none, "cannot find type %0 in scope; did you mean to use '%1'?", (DeclNameRef, StringRef)) +ERROR(type_not_in_module,none, + "type %0 is not imported through module %1", (DeclName, Identifier)) +ERROR(decl_not_in_module,none, + "declaration %0 is not imported through module %1", (DeclName, Identifier)) +NOTE(note_change_module_selector,none, + "did you mean module %0?", (Identifier)) +NOTE(note_remove_module_selector,none, + "did you mean the local declaration?", ()) +NOTE(note_add_explicit_self_with_module_selector,none, + "did you mean the member of 'self'?", ()) NOTE(note_typo_candidate_implicit_member,none, "did you mean the implicitly-synthesized %kindbase0?", (const ValueDecl *)) NOTE(note_remapped_type,none, diff --git a/include/swift/AST/Identifier.h b/include/swift/AST/Identifier.h index 7efec38a97bab..d18c9cf2f0f55 100644 --- a/include/swift/AST/Identifier.h +++ b/include/swift/AST/Identifier.h @@ -738,39 +738,87 @@ void simple_display(llvm::raw_ostream &out, DeclName name); /// An in-source reference to another declaration, including qualification /// information. class DeclNameRef { - DeclName FullName; + friend class ASTContext; + + /// Contains the name and module for a DeclNameRef with a module selector. + struct alignas(Identifier) SelectiveDeclNameRef : llvm::FoldingSetNode { + Identifier moduleSelector; // Note: currently can never be empty(). + DeclName fullName; + + SelectiveDeclNameRef(Identifier moduleSelector, DeclName fullName) + : moduleSelector(moduleSelector), fullName(fullName) { } + + /// Uniquing for the ASTContext. + static void Profile(llvm::FoldingSetNodeID &id, Identifier moduleSelector, + DeclName fullName); + + void Profile(llvm::FoldingSetNodeID &id) { + Profile(id, moduleSelector, fullName); + } + + // Make vanilla new/delete illegal for SelectiveDeclNameRef. + void * _Nullable operator new(size_t Bytes) = delete; + void operator delete(void *_Nonnull Data) = delete; + + // Only allow allocation of SelectiveDeclNameRef using the allocator + // in ASTContext or by doing a placement new. + void *_Nullable operator new(size_t Bytes, const ASTContext &C, + unsigned Alignment = alignof(SelectiveDeclNameRef)); + void *_Nullable operator new(size_t Bytes, void *_Nonnull Mem) { + assert(Mem); + return Mem; + } + }; + + llvm::PointerUnion storage; + + explicit DeclNameRef(void *_Nullable Opaque) + : storage(decltype(storage)::getFromOpaqueValue(Opaque)) { } + + void initialize(ASTContext &C, Identifier moduleScope, DeclName fullName); public: static DeclNameRef createSubscript(); static DeclNameRef createConstructor(); + static DeclNameRef createSelf(const ASTContext &ctx); - DeclNameRef() : FullName() { } + DeclNameRef() : storage(DeclName()) { } - void *_Nullable getOpaqueValue() const { return FullName.getOpaqueValue(); } + void *_Nullable getOpaqueValue() const { + return storage.getOpaqueValue(); + } static DeclNameRef getFromOpaqueValue(void *_Nullable p); explicit DeclNameRef(ASTContext &C, Identifier moduleSelector, - DeclName fullName) - : FullName(fullName) { } + DeclName fullName) { + initialize(C, moduleSelector, fullName); + } explicit DeclNameRef(ASTContext &C, Identifier moduleSelector, - DeclBaseName baseName, ArrayRef argLabels) - : FullName(C, baseName, argLabels) { } + DeclBaseName baseName, ArrayRef argLabels) { + initialize(C, moduleSelector, DeclName(C, baseName, argLabels)); + } explicit DeclNameRef(DeclName FullName) - : FullName(FullName) { } + : storage(FullName) { } bool hasModuleSelector() const { - return false; + return storage.is(); } Identifier getModuleSelector() const { - return Identifier(); + if (!hasModuleSelector()) + return Identifier(); + + return storage.get()->moduleSelector; } /// The name of the declaration being referenced. DeclName getFullName() const { - return FullName; + if (!hasModuleSelector()) + return storage.get(); + + return storage.get()->fullName; } /// The base name of the declaration being referenced. @@ -885,7 +933,7 @@ class DeclNameRef { }; inline DeclNameRef DeclNameRef::getFromOpaqueValue(void *_Nullable p) { - return DeclNameRef(DeclName::getFromOpaqueValue(p)); + return DeclNameRef(p); } inline DeclNameRef DeclNameRef::withoutArgumentLabels(ASTContext &C) const { @@ -1069,7 +1117,7 @@ namespace llvm { static inline swift::DeclNameRef getFromVoidPointer(void *_Nullable ptr) { return swift::DeclNameRef::getFromOpaqueValue(ptr); } - enum { NumLowBitsAvailable = PointerLikeTypeTraits::NumLowBitsAvailable }; + enum { NumLowBitsAvailable = PointerLikeTypeTraits::NumLowBitsAvailable - 1 }; }; // DeclNameRefs hash just like DeclNames. diff --git a/include/swift/AST/ModuleNameLookup.h b/include/swift/AST/ModuleNameLookup.h index 9713b8cffd88c..b8154c15e94c1 100644 --- a/include/swift/AST/ModuleNameLookup.h +++ b/include/swift/AST/ModuleNameLookup.h @@ -44,14 +44,14 @@ enum class ResolutionKind { void simple_display(llvm::raw_ostream &out, ResolutionKind kind); -/// Performs a lookup into the given module and it's imports. +/// Performs a lookup into the given module and its imports. /// -/// If 'moduleOrFile' is a ModuleDecl, we search the module and it's +/// If 'moduleOrFile' is a ModuleDecl, we search the module and its /// public imports. If 'moduleOrFile' is a SourceFile, we search the /// file's parent module, the module's public imports, and the source /// file's private imports. /// -/// \param moduleOrFile The module or file unit whose imports to search. +/// \param moduleOrFile The module or file unit to search, including imports. /// \param name The name to look up. /// \param[out] decls Any found decls will be added to this vector. /// \param lookupKind Whether this lookup is qualified or unqualified. diff --git a/include/swift/AST/NameLookup.h b/include/swift/AST/NameLookup.h index 262f41f7c5bf1..74840cc7cb347 100644 --- a/include/swift/AST/NameLookup.h +++ b/include/swift/AST/NameLookup.h @@ -33,7 +33,7 @@ namespace swift { class ASTContext; -class DeclName; +class DeclNameRef; class Type; class TypeDecl; class ValueDecl; @@ -486,6 +486,14 @@ class UsableFilteringDeclConsumer final : public VisibleDeclConsumer { /// \returns true if any declarations were removed, false otherwise. bool removeOverriddenDecls(SmallVectorImpl &decls); +/// Remove any declarations in the given set that do not match the +/// module selector, if it is not empty. +/// +/// \returns true if any declarations were removed, false otherwise. +bool removeOutOfModuleDecls(SmallVectorImpl &decls, + Identifier moduleSelector, + const DeclContext *dc); + /// Remove any declarations in the given set that are shadowed by /// other declarations in that set. /// @@ -561,6 +569,7 @@ void tryExtractDirectlyReferencedNominalTypes( /// Once name lookup has gathered a set of results, perform any necessary /// steps to prune the result set before returning it to the caller. void pruneLookupResultSet(const DeclContext *dc, NLOptions options, + Identifier moduleSelector, SmallVectorImpl &decls); /// Do nothing if debugClient is null. @@ -764,12 +773,12 @@ class ASTScope : public ASTAllocated { /// /// \param stopAfterInnermostBraceStmt If lookup should consider /// local declarations inside the innermost syntactic scope only. - static void lookupLocalDecls(SourceFile *, DeclName, SourceLoc, + static void lookupLocalDecls(SourceFile *, DeclNameRef, SourceLoc, bool stopAfterInnermostBraceStmt, ABIRole roleFilter, SmallVectorImpl &); - static void lookupLocalDecls(SourceFile *sf, DeclName name, SourceLoc loc, + static void lookupLocalDecls(SourceFile *sf, DeclNameRef name, SourceLoc loc, bool stopAfterInnermostBraceStmt, SmallVectorImpl &results) { lookupLocalDecls(sf, name, loc, stopAfterInnermostBraceStmt, @@ -777,7 +786,7 @@ class ASTScope : public ASTAllocated { } /// Returns the result if there is exactly one, nullptr otherwise. - static ValueDecl *lookupSingleLocalDecl(SourceFile *, DeclName, SourceLoc); + static ValueDecl *lookupSingleLocalDecl(SourceFile *, DeclNameRef, SourceLoc); /// Entry point to record the visible statement labels from the given /// point. diff --git a/include/swift/AST/NameLookupRequests.h b/include/swift/AST/NameLookupRequests.h index 31336795de502..98610d10d7493 100644 --- a/include/swift/AST/NameLookupRequests.h +++ b/include/swift/AST/NameLookupRequests.h @@ -490,7 +490,21 @@ class LookupInModuleRequest private: friend SimpleRequest; - // Evaluation. + /// Performs a lookup into the given module and its imports. + /// + /// If 'moduleOrFile' is a ModuleDecl, we search the module and its + /// public imports. If 'moduleOrFile' is a SourceFile, we search the + /// file's parent module, the module's public imports, and the source + /// file's private imports. + /// + /// \param evaluator The request evaluator. + /// \param moduleOrFile The module or file unit to search, including imports. + /// \param name The name to look up. + /// \param lookupKind Whether this lookup is qualified or unqualified. + /// \param resolutionKind What sort of decl is expected. + /// \param moduleScopeContext The top-level context from which the lookup is + /// being performed, for checking access. This must be either a + /// FileUnit or a Module. QualifiedLookupResult evaluate(Evaluator &evaluator, const DeclContext *moduleOrFile, DeclName name, NLKind lookupKind, namelookup::ResolutionKind resolutionKind, 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 45cc0123dc403..3d180f060da9f 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) @@ -764,6 +763,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 @@ -1055,7 +1065,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, @@ -1799,6 +1809,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, @@ -1811,6 +1834,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, @@ -1822,6 +1848,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; @@ -1829,6 +1858,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. /// @@ -1852,7 +1884,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/include/swift/Sema/CSFix.h b/include/swift/Sema/CSFix.h index f7c8fcb46ccbf..c6f0d7787fcb4 100644 --- a/include/swift/Sema/CSFix.h +++ b/include/swift/Sema/CSFix.h @@ -186,6 +186,10 @@ enum class FixKind : uint8_t { /// no access control. AllowInaccessibleMember, + /// If a module selector prevented us from selecting a member, pretend that it + /// was not specified. + AllowMemberFromWrongModule, + /// Allow KeyPaths to use AnyObject as root type AllowAnyObjectKeyPathRoot, @@ -1938,6 +1942,25 @@ class AllowInaccessibleMember final : public AllowInvalidMemberRef { } }; +class AllowMemberFromWrongModule final : public AllowInvalidMemberRef { + AllowMemberFromWrongModule(ConstraintSystem &cs, Type baseType, + ValueDecl *member, DeclNameRef name, + ConstraintLocator *locator) + : AllowInvalidMemberRef(cs, FixKind::AllowMemberFromWrongModule, baseType, + member, name, locator) {} + +public: + std::string getName() const override { + return "allow reference to member from wrong module"; + } + + bool diagnose(const Solution &solution, bool asNote = false) const override; + + static AllowMemberFromWrongModule *create(ConstraintSystem &cs, Type baseType, + ValueDecl *member, DeclNameRef name, + ConstraintLocator *locator); +}; + class AllowAnyObjectKeyPathRoot final : public ConstraintFix { AllowAnyObjectKeyPathRoot(ConstraintSystem &cs, ConstraintLocator *locator) diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index b973a840cee87..cd86806ace69a 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -2062,6 +2062,9 @@ struct MemberLookupResult { /// 'accesses' attributes of the init accessor and therefore canno /// t be referenced in its body. UR_UnavailableWithinInitAccessor, + + /// The module selector in the `DeclNameRef` does not match this candidate. + UR_WrongModule }; /// This is a list of considered (but rejected) candidates, along with a diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 643f3b7b9e650..1f7d38e80dea0 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -634,6 +634,7 @@ struct ASTContext::Implementation { llvm::DenseMap BuiltinUnboundGenericTypes; llvm::FoldingSet BuiltinVectorTypes; llvm::FoldingSet CompoundNames; + llvm::FoldingSet SelectiveNameRefs; llvm::DenseMap OpenedElementEnvironments; llvm::FoldingSet IndexSubsets; llvm::FoldingSet @@ -6183,6 +6184,44 @@ DeclName::DeclName(ASTContext &C, DeclBaseName baseName, initialize(C, baseName, names); } +// Only allow allocation of SelectiveDeclNameRefs using the allocator in +// ASTContext. +void *DeclNameRef::SelectiveDeclNameRef:: +operator new(size_t Bytes, const ASTContext &C, unsigned Alignment) { + return C.Allocate(Bytes, Alignment); +} + +void DeclNameRef::SelectiveDeclNameRef::Profile(llvm::FoldingSetNodeID &id, + Identifier moduleSelector, + DeclName fullName) { + assert(!moduleSelector.empty() && + "Looking up SelectiveDeclNameRef with empty module?"); + id.AddPointer(moduleSelector.getAsOpaquePointer()); + id.AddPointer(fullName.getOpaqueValue()); +} + +void DeclNameRef::initialize(ASTContext &C, Identifier moduleSelector, + DeclName fullName) { + if (moduleSelector.empty()) { + storage = fullName; + return; + } + + llvm::FoldingSetNodeID id; + SelectiveDeclNameRef::Profile(id, moduleSelector, fullName); + + void *insert = nullptr; + if (SelectiveDeclNameRef *selectiveRef + = C.getImpl().SelectiveNameRefs.FindNodeOrInsertPos(id, insert)) { + storage = selectiveRef; + return; + } + + auto selectiveRef = new (C) SelectiveDeclNameRef(moduleSelector, fullName); + storage = selectiveRef; + C.getImpl().SelectiveNameRefs.InsertNode(selectiveRef, insert); +} + /// Find the implementation of the named type in the given module. static NominalTypeDecl *findUnderlyingTypeInModule(ASTContext &ctx, Identifier name, diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 25f9d49c6c4eb..b58e45c14bc10 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); diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp index a07eaf612e628..caefa8b4c1c04 100644 --- a/lib/AST/Attr.cpp +++ b/lib/AST/Attr.cpp @@ -2104,10 +2104,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; @@ -2116,11 +2117,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)); } @@ -2476,12 +2478,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) { @@ -2503,6 +2508,7 @@ SpecializeAttr *SpecializeAttr::create(ASTContext &Ctx, SourceLoc atLoc, TrailingWhereClause *clause, bool exported, SpecializationKind kind, DeclNameRef targetFunctionName, + DeclNameLoc targetFunctionNameLoc, ArrayRef spiGroups, ArrayRef availableAttrs, GenericSignature specializedSignature) { @@ -2526,7 +2532,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, @@ -2539,8 +2546,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( @@ -2554,7 +2561,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; @@ -2567,6 +2575,7 @@ SpecializedAttr *SpecializedAttr::create(ASTContext &Ctx, SourceLoc atLoc, TrailingWhereClause *clause, bool exported, SpecializationKind kind, DeclNameRef targetFunctionName, + DeclNameLoc targetFunctionNameLoc, ArrayRef spiGroups, ArrayRef availableAttrs, GenericSignature specializedSignature) { @@ -2590,7 +2599,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, @@ -2604,7 +2614,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( @@ -2618,7 +2629,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/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/AST/Decl.cpp b/lib/AST/Decl.cpp index c216580950107..bc4ae92449647 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -2929,6 +2929,14 @@ SourceRange TopLevelCodeDecl::getSourceRange() const { return Body? Body->getSourceRange() : SourceRange(); } +DeclNameRef ValueDecl::createNameRef(bool moduleSelector) const { + if (moduleSelector) + return DeclNameRef(getASTContext(), getModuleContext()->getName(), + getName()); + + return DeclNameRef(getName()); +} + static bool isPolymorphic(const AbstractStorageDecl *storage) { if (storage->shouldUseObjCDispatch()) return true; diff --git a/lib/AST/DeclNameLoc.cpp b/lib/AST/DeclNameLoc.cpp index 3c37eb5e0cb83..5e1b50c0a0dc4 100644 --- a/lib/AST/DeclNameLoc.cpp +++ b/lib/AST/DeclNameLoc.cpp @@ -20,16 +20,24 @@ using namespace swift; -DeclNameLoc::DeclNameLoc(ASTContext &ctx, SourceLoc baseNameLoc, +DeclNameLoc::DeclNameLoc(ASTContext &ctx, SourceLoc moduleSelectorLoc, + SourceLoc baseNameLoc, SourceLoc lParenLoc, ArrayRef argumentLabelLocs, SourceLoc rParenLoc) - : NumArgumentLabels(argumentLabelLocs.size()) { - assert(NumArgumentLabels > 0 && "Use other constructor"); + : NumArgumentLabels(argumentLabelLocs.size()), + HasModuleSelectorLoc(moduleSelectorLoc.isValid()) +{ + if (NumArgumentLabels == 0 && !HasModuleSelectorLoc) { + LocationInfo = baseNameLoc.getOpaquePointerValue(); + return; + } // Copy the location information into permanent storage. - auto storedLocs = ctx.Allocate(NumArgumentLabels + 3); + auto storedLocs = + ctx.Allocate(FirstArgumentLabelIndex + NumArgumentLabels); storedLocs[BaseNameIndex] = baseNameLoc; + storedLocs[ModuleSelectorIndex] = moduleSelectorLoc; storedLocs[LParenIndex] = lParenLoc; storedLocs[RParenIndex] = rParenLoc; std::memcpy(storedLocs.data() + FirstArgumentLabelIndex, diff --git a/lib/AST/Identifier.cpp b/lib/AST/Identifier.cpp index 1cb2c3838d67d..ee2cc69279d6c 100644 --- a/lib/AST/Identifier.cpp +++ b/lib/AST/Identifier.cpp @@ -220,6 +220,10 @@ llvm::raw_ostream &DeclName::printPretty(llvm::raw_ostream &os) const { return print(os, /*skipEmptyArgumentNames=*/!isSpecial()); } +DeclNameRef DeclNameRef::createSelf(const ASTContext &ctx) { + return DeclNameRef(ctx.Id_self); +} + void DeclNameRef::dump() const { llvm::errs() << *this << "\n"; } diff --git a/lib/AST/ModuleNameLookup.cpp b/lib/AST/ModuleNameLookup.cpp index cd5915b468fd0..a0f80e9ed8904 100644 --- a/lib/AST/ModuleNameLookup.cpp +++ b/lib/AST/ModuleNameLookup.cpp @@ -51,10 +51,21 @@ class ModuleNameLookup { resolutionKind(resolutionKind), respectAccessControl(!ctx.isAccessControlDisabled()) {} - /// Performs a qualified lookup into the given module and, if necessary, its - /// reexports. + /// Performs the qualified lookup requested by \p LookupStrategy into the + /// given module and, if necessary, its reexports. /// - /// The results are appended to \p decls. + /// If 'moduleOrFile' is a ModuleDecl, we search the module and it's + /// public imports. If 'moduleOrFile' is a SourceFile, we search the + /// file's parent module, the module's public imports, and the source + /// file's private imports. + /// + /// \param[out] decls Results are appended to this vector. + /// \param moduleOrFile The module or file unit to search, including imports. + /// \param accessPath The access path that was imported; if not empty, only + /// the named declaration will be imported. + /// \param moduleScopeContext The top-level context from which the lookup is + /// being performed, for checking access. This must be either a + /// FileUnit or a Module. void lookupInModule(SmallVectorImpl &decls, const DeclContext *moduleOrFile, ImportPath::Access accessPath, @@ -77,6 +88,10 @@ class LookupByName : public ModuleNameLookup { const NLKind lookupKind; public: + /// \param ctx The AST context that the lookup will be performed in. + /// \param name The name that will be looked up. + /// \param lookupKind Whether this lookup is qualified or unqualified. + /// \param resolutionKind What sort of decl is expected. LookupByName(ASTContext &ctx, ResolutionKind resolutionKind, DeclName name, NLKind lookupKind) : Super(ctx, resolutionKind), name(name), @@ -89,6 +104,10 @@ class LookupByName : public ModuleNameLookup { return true; } + /// \param module The module to search for declarations in. + /// \param path The access path that was imported; if not empty, only the + /// named declaration will be imported. + /// \param[out] localDecls Results are appended to this vector. void doLocalLookup(ModuleDecl *module, ImportPath::Access path, OptionSet flags, SmallVectorImpl &localDecls) { diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index 0243e3e15d8e6..614d31e8d3ed8 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -361,6 +361,42 @@ enum class ConstructorComparison { Better, }; +bool swift::removeOutOfModuleDecls(SmallVectorImpl &decls, + Identifier moduleSelector, + const DeclContext *dc) { + if (moduleSelector.empty()) + return false; + + ASTContext &ctx = dc->getASTContext(); + + // FIXME: Should we look this up relative to dc? + // We'd need a new ResolutionKind. + // FIXME: How can we diagnose this? + ModuleDecl *visibleFrom = ctx.getLoadedModule(moduleSelector); + if (!visibleFrom) { + LLVM_DEBUG(llvm::dbgs() << "no module " << moduleSelector << "\n"); + decls.clear(); + return true; + } + + bool initialCount = decls.size(); + decls.erase( + std::remove_if(decls.begin(), decls.end(), [&](ValueDecl *decl) -> bool { + bool inScope = ctx.getImportCache().isImportedBy(decl->getModuleContext(), + visibleFrom); + + LLVM_DEBUG(decl->dumpRef(llvm::dbgs())); + LLVM_DEBUG(llvm::dbgs() << ": " << decl->getModuleContext()->getName() + << (inScope ? " is " : " is NOT ") + << "selected by " << visibleFrom->getName() + << "\n"); + + return !inScope; + }), + decls.end()); + return initialCount != decls.size(); +} + /// Determines whether \p ctor1 is a "better" initializer than \p ctor2. static ConstructorComparison compareConstructors(ConstructorDecl *ctor1, ConstructorDecl *ctor2, @@ -2471,14 +2507,17 @@ bool namelookup::isInABIAttr(SourceFile *sourceFile, SourceLoc loc) { } void namelookup::pruneLookupResultSet(const DeclContext *dc, NLOptions options, + Identifier moduleSelector, SmallVectorImpl &decls) { // If we're supposed to remove overridden declarations, do so now. if (options & NL_RemoveOverridden) removeOverriddenDecls(decls); // If we're supposed to remove shadowed/hidden declarations, do so now. - if (options & NL_RemoveNonVisible) + if (options & NL_RemoveNonVisible) { + removeOutOfModuleDecls(decls, moduleSelector, dc); removeShadowedDecls(decls, dc); + } ModuleDecl *M = dc->getParentModule(); filterForDiscriminator(decls, M->getDebugClient()); @@ -2790,7 +2829,7 @@ QualifiedLookupRequest::evaluate(Evaluator &eval, const DeclContext *DC, } } - pruneLookupResultSet(DC, options, decls); + pruneLookupResultSet(DC, options, member.getModuleSelector(), decls); if (auto *debugClient = DC->getParentModule()->getDebugClient()) { debugClient->finishLookupInNominals(DC, typeDecls, member.getFullName(), options, decls); @@ -2842,7 +2881,7 @@ ModuleQualifiedLookupRequest::evaluate(Evaluator &eval, const DeclContext *DC, } } - pruneLookupResultSet(DC, options, decls); + pruneLookupResultSet(DC, options, member.getModuleSelector(), decls); if (auto *debugClient = DC->getParentModule()->getDebugClient()) { debugClient->finishLookupInModule(DC, module, member.getFullName(), @@ -2910,7 +2949,7 @@ AnyObjectLookupRequest::evaluate(Evaluator &evaluator, const DeclContext *dc, decls.push_back(decl); } - pruneLookupResultSet(dc, options, decls); + pruneLookupResultSet(dc, options, member.getModuleSelector(), decls); if (auto *debugClient = dc->getParentModule()->getDebugClient()) { debugClient->finishLookupInAnyObject(dc, member.getFullName(), options, decls); diff --git a/lib/AST/UnqualifiedLookup.cpp b/lib/AST/UnqualifiedLookup.cpp index 51820b41a9ca8..74ffb8828b362 100644 --- a/lib/AST/UnqualifiedLookup.cpp +++ b/lib/AST/UnqualifiedLookup.cpp @@ -249,8 +249,9 @@ void UnqualifiedLookupFactory::performUnqualifiedLookup() { } if (Loc.isValid() && DC->getParentSourceFile()) { - // Operator lookup is always global, for the time being. - if (!Name.isOperator()) + // Operator lookup is always global, for the time being. Unqualified lookups + // with module selectors always start at global scope. + if (!Name.isOperator() && !Name.hasModuleSelector()) lookInASTScopes(); } else { assert((DC->isModuleScopeContext() || !DC->getParentSourceFile()) && @@ -382,7 +383,8 @@ ValueDecl *UnqualifiedLookupFactory::lookupBaseDecl(const DeclContext *baseDC) c return nullptr; auto selfDecl = ASTScope::lookupSingleLocalDecl(DC->getParentSourceFile(), - DeclName(Ctx.Id_self), Loc); + DeclNameRef::createSelf(Ctx), + Loc); if (!selfDecl) { return nullptr; } @@ -471,11 +473,24 @@ void UnqualifiedLookupFactory::setAsideUnavailableResults( } void UnqualifiedLookupFactory::addImportedResults(const DeclContext *const dc) { + assert(dc); + using namespace namelookup; SmallVector CurModuleResults; auto resolutionKind = isOriginallyTypeLookup ? ResolutionKind::TypesOnly : isOriginallyMacroLookup ? ResolutionKind::MacrosOnly : ResolutionKind::Overloadable; + auto moduleToLookIn = dc; + if (Name.hasModuleSelector()) + // FIXME: Should we look this up relative to dc? + // We'd need a new ResolutionKind. + moduleToLookIn = + dc->getASTContext().getLoadedModule(Name.getModuleSelector()); + + // If we didn't find the module, it obviously can't have any results. + if (!moduleToLookIn) + return; + auto nlOptions = NL_UnqualifiedDefault; if (options.contains(Flags::IncludeUsableFromInline)) nlOptions |= NL_IncludeUsableFromInline; @@ -483,7 +498,7 @@ void UnqualifiedLookupFactory::addImportedResults(const DeclContext *const dc) { nlOptions |= NL_ExcludeMacroExpansions; if (options.contains(Flags::ABIProviding)) nlOptions |= NL_ABIProviding; - lookupInModule(dc, Name.getFullName(), CurModuleResults, + lookupInModule(moduleToLookIn, Name.getFullName(), CurModuleResults, NLKind::UnqualifiedLookup, resolutionKind, dc, Loc, nlOptions); @@ -893,14 +908,14 @@ namespace { class ASTScopeDeclConsumerForLocalLookup : public AbstractASTScopeDeclConsumer { - DeclName name; + DeclNameRef name; bool stopAfterInnermostBraceStmt; ABIRole roleFilter; SmallVectorImpl &results; public: ASTScopeDeclConsumerForLocalLookup( - DeclName name, bool stopAfterInnermostBraceStmt, + DeclNameRef name, bool stopAfterInnermostBraceStmt, ABIRole roleFilter, SmallVectorImpl &results) : name(name), stopAfterInnermostBraceStmt(stopAfterInnermostBraceStmt), roleFilter(roleFilter), results(results) {} @@ -911,6 +926,8 @@ class ASTScopeDeclConsumerForLocalLookup bool consume(ArrayRef values, NullablePtr baseDC) override { + if (name.hasModuleSelector()) return false; + for (auto *value: values) { bool foundMatch = false; if (auto *varDecl = dyn_cast(value)) { @@ -924,7 +941,7 @@ class ASTScopeDeclConsumerForLocalLookup }); } - if (!foundMatch && value->getName().matchesRef(name) + if (!foundMatch && value->getName().matchesRef(name.getFullName()) && hasCorrectABIRole(value)) results.push_back(value); } @@ -951,7 +968,7 @@ class ASTScopeDeclConsumerForLocalLookup /// Lookup that only finds local declarations and does not trigger /// interface type computation. -void ASTScope::lookupLocalDecls(SourceFile *sf, DeclName name, SourceLoc loc, +void ASTScope::lookupLocalDecls(SourceFile *sf, DeclNameRef name, SourceLoc loc, bool stopAfterInnermostBraceStmt, ABIRole roleFilter, SmallVectorImpl &results) { @@ -960,7 +977,7 @@ void ASTScope::lookupLocalDecls(SourceFile *sf, DeclName name, SourceLoc loc, ASTScope::unqualifiedLookup(sf, loc, consumer); } -ValueDecl *ASTScope::lookupSingleLocalDecl(SourceFile *sf, DeclName name, +ValueDecl *ASTScope::lookupSingleLocalDecl(SourceFile *sf, DeclNameRef name, SourceLoc loc) { SmallVector result; ASTScope::lookupLocalDecls(sf, name, loc, 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 0d7f49b4d03ef..7a0a9386950af 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 @@ -468,7 +468,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 @@ -767,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) ) } @@ -1044,6 +1046,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) @@ -1121,7 +1127,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, @@ -1212,7 +1219,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 { @@ -1272,7 +1282,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") @@ -1908,7 +1922,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] = [] @@ -1921,7 +1935,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) ) @@ -1941,7 +1956,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] = [] @@ -1953,7 +1968,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), @@ -2017,7 +2032,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) ) @@ -2091,7 +2107,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 @@ -2182,11 +2199,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 { @@ -2356,7 +2374,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/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) 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/lib/Parse/Lexer.cpp b/lib/Parse/Lexer.cpp index 4529466531afd..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': @@ -2762,9 +2765,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] == ':' && LangOpts.hasFeature(Feature::ModuleSelector)) { + CurPtr++; + return formToken(tok::colon_colon, TokStart); + } + return formToken(tok::colon, TokStart); + case '#': { // Try lex a raw string literal. auto *Diags = getTokenDiags(); @@ -2873,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 78de6ddde3484..e4c59e5345696 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,13 +677,13 @@ 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 | - DeclNameFlag::AllowLowercaseAndUppercaseSelf); + DeclNameFlag::AllowLowercaseAndUppercaseSelf | + DeclNameFlag::ModuleSelectorUnsupported); } } if (ParamLabel == "spiModule") { @@ -893,13 +893,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 +932,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; } @@ -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(); } @@ -1148,9 +1150,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(); } @@ -1158,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(), @@ -1807,11 +1810,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; } @@ -1822,8 +1824,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; } @@ -2441,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; @@ -3013,7 +3015,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); })) { @@ -3568,6 +3570,7 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc LParenLoc = consumeAttributeLParen(); DeclNameRef replacedFunction; + DeclNameLoc replacedFunctionLoc; { // Parse 'for'. if (Tok.getText() != "for") { @@ -3582,15 +3585,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 ')'. @@ -3604,7 +3604,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; } @@ -4247,11 +4248,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) { @@ -4272,7 +4277,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; @@ -4284,7 +4289,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) { @@ -4348,7 +4353,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(); @@ -4423,9 +4428,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. @@ -5758,6 +5764,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; @@ -6673,7 +6681,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)) { @@ -10287,8 +10301,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)) { @@ -10301,9 +10316,11 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name, return makeParserCodeCompletionResult(); } - (void)parseIdentifier(groupName, groupLoc, - diag::operator_decl_expected_precedencegroup, - /*diagnoseDollarPrefix=*/false); + // 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 @@ -10318,7 +10335,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)) { @@ -10337,7 +10354,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}); } @@ -10348,6 +10365,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)) { @@ -10355,7 +10373,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()); @@ -10377,7 +10394,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); @@ -10596,14 +10614,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 }, + DeclNameFlag::ModuleSelectorUnsupported); + 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..fa15815b1d38d 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: @@ -2142,14 +2150,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 +2191,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 +2201,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 +2236,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 +2249,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; @@ -2251,23 +2279,109 @@ 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(); + } + } + + auto colonColonLoc = 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; 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()); 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); @@ -2285,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. @@ -2300,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( @@ -2327,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(); @@ -2371,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; @@ -2382,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); @@ -2412,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); @@ -2698,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 { @@ -3047,8 +3181,14 @@ 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 | + DeclNameFlag::ModuleSelectorUnsupported); + + 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. @@ -3191,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. @@ -3212,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, @@ -3321,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; @@ -3338,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/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/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/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index bedf63acf1118..99b8f934a0c5f 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -7460,12 +7460,13 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType, case ConversionRestrictionKind::CGFloatToDouble: case ConversionRestrictionKind::DoubleToCGFloat: { - DeclName name(ctx, DeclBaseName::createConstructor(), Identifier()); + // OK: Implicit conversion, no module selector to drop here. + DeclNameRef initRef(ctx, /*module selector=*/Identifier(), + DeclBaseName::createConstructor(), { Identifier() }); ConstructorDecl *decl = nullptr; SmallVector candidates; - dc->lookupQualified(toType->getAnyNominal(), - DeclNameRef(name), SourceLoc(), + dc->lookupQualified(toType->getAnyNominal(), initRef, SourceLoc(), NL_QualifiedDefault, candidates); for (auto *candidate : candidates) { auto *ctor = cast(candidate); diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 525c8ec622840..e9e97fad8478d 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -1776,7 +1776,7 @@ class VarDeclMultipleReferencesChecker : public ASTWalker { if (name.isSimpleName(varDecl->getName()) && loc.isValid()) { auto *otherDecl = ASTScope::lookupSingleLocalDecl(DC->getParentSourceFile(), - name.getFullName(), loc); + name, loc); if (otherDecl == varDecl) ++count; } @@ -6349,10 +6349,7 @@ bool InaccessibleMemberFailure::diagnoseAsError() { if (baseExpr) { auto *locator = getConstraintLocator(baseExpr, ConstraintLocator::Member); - const auto &solution = getSolution(); - if (llvm::any_of(solution.Fixes, [&locator](const ConstraintFix *fix) { - return fix->getLocator() == locator; - })) + if (hasFixFor(getSolution(), locator)) return false; } @@ -6372,6 +6369,54 @@ bool InaccessibleMemberFailure::diagnoseAsError() { return true; } +bool MemberFromWrongModuleFailure::diagnoseAsError() { + auto anchor = getRawAnchor(); + // Let's try to avoid over-diagnosing chains of wrong-module + // members e.g.: + // + // struct A { + // struct B { + // struct C {} + // } + // } + // + // _ = A.Other::B.Other::C() + Expr *baseExpr = nullptr; + DeclNameLoc nameLoc; + if (auto *UDE = getAsExpr(anchor)) { + baseExpr = UDE->getBase(); + nameLoc = UDE->getNameLoc(); + } else if (auto *UME = getAsExpr(anchor)) { + nameLoc = UME->getNameLoc(); + } else if (auto *SE = getAsExpr(anchor)) { + baseExpr = SE->getBase(); + } else if (auto *call = getAsExpr(anchor)) { + baseExpr = call->getFn(); + } + + if (baseExpr) { + auto *locator = getConstraintLocator(baseExpr, ConstraintLocator::Member); + if (hasFixFor(getSolution(), locator)) + return false; + } + + auto modSelLoc = nameLoc.getModuleSelectorLoc(); + auto loc = nameLoc.isValid() ? nameLoc.getStartLoc() : ::getLoc(anchor); + + emitDiagnosticAt(loc, diag::decl_not_in_module, Member->getName(), + Name.getModuleSelector()); + + Identifier actualModuleName = Member->getModuleContext()->getName(); + assert(actualModuleName != Name.getModuleSelector() && + "Module selector failure on member in same module?"); + emitDiagnosticAt(loc, diag::note_change_module_selector, actualModuleName) + .fixItReplace(modSelLoc, actualModuleName.str()); + + emitDiagnosticAt(Member, diag::decl_declared_here, Member); + + return true; +} + SourceLoc AnyObjectKeyPathRootFailure::getLoc() const { auto anchor = getAnchor(); diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 5c65d8a23c067..d20036b6ddb7f 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -1644,6 +1644,27 @@ class InaccessibleMemberFailure final : public FailureDiagnostic { bool diagnoseAsError() override; }; +/// Diagnose an attempt to reference member from the wrong module with a module +/// selector, e.g. +/// +/// ```swift +/// import Foo +/// import Bar +/// +/// SomeType.Bar::methodDefinedInFoo() +/// ``` +class MemberFromWrongModuleFailure final : public FailureDiagnostic { + ValueDecl *Member; + DeclNameRef Name; + +public: + MemberFromWrongModuleFailure(const Solution &solution, DeclNameRef name, + ValueDecl *member, ConstraintLocator *locator) + : FailureDiagnostic(solution, locator), Member(member), Name(name) {} + + bool diagnoseAsError() override; +}; + /// Diagnose an attempt to reference member marked as `mutating` /// on immutable base e.g. `let` variable: /// diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index 816e2b28d9e7e..3e5b195103026 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1210,6 +1210,21 @@ AllowInaccessibleMember::create(ConstraintSystem &cs, Type baseType, AllowInaccessibleMember(cs, baseType, member, name, locator); } +bool AllowMemberFromWrongModule::diagnose(const Solution &solution, + bool asNote) const { + MemberFromWrongModuleFailure failure(solution, getMemberName(), getMember(), + getLocator()); + return failure.diagnose(asNote); +} + +AllowMemberFromWrongModule * +AllowMemberFromWrongModule::create(ConstraintSystem &cs, Type baseType, + ValueDecl *member, DeclNameRef name, + ConstraintLocator *locator) { + return new (cs.getAllocator()) + AllowMemberFromWrongModule(cs, baseType, member, name, locator); +} + bool AllowAnyObjectKeyPathRoot::diagnose(const Solution &solution, bool asNote) const { AnyObjectKeyPathRootFailure failure(solution, getLocator()); diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index d1791809bc69b..e3e6f9fbd3dc6 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -897,7 +897,7 @@ TypeVarRefCollector::walkToExprPre(Expr *expr) { auto loc = declRef->getLoc(); if (name.isSimpleName() && loc.isValid()) { auto *SF = CS.DC->getParentSourceFile(); - auto *D = ASTScope::lookupSingleLocalDecl(SF, name.getFullName(), loc); + auto *D = ASTScope::lookupSingleLocalDecl(SF, name, loc); inferTypeVars(D); } } @@ -3853,10 +3853,9 @@ namespace { componentTypeVars.push_back(memberTy); auto lookupName = kind == KeyPathExpr::Component::Kind::UnresolvedMember - ? DeclNameRef( - component.getUnresolvedDeclName()) // FIXME: type change - // needed - : component.getDeclRef().getDecl()->createNameRef(); + ? component.getUnresolvedDeclName() + : component.getDeclRef().getDecl()->createNameRef( + /*modSel=*/true); auto refKind = component.getFunctionRefInfo(); CS.addValueMemberConstraint(base, lookupName, memberTy, CurDC, @@ -5290,10 +5289,14 @@ ResolvedMemberResult swift::resolveValueMember(DeclContext &DC, Type BaseTy, ResolvedMemberResult Result; ConstraintSystem CS(&DC, std::nullopt); + // OK: By contract, `Name` should be derived from an existing Decl, not a + // name written by the user in source code. So when used as intended, we won't + // be dropping a module selector here. + DeclNameRef NameRef(Name); // Look up all members of BaseTy with the given Name. MemberLookupResult LookupResult = - CS.performMemberLookup(ConstraintKind::ValueMember, DeclNameRef(Name), - BaseTy, FunctionRefInfo::singleBaseNameApply(), + CS.performMemberLookup(ConstraintKind::ValueMember, NameRef, BaseTy, + FunctionRefInfo::singleBaseNameApply(), CS.getConstraintLocator({}), false); // Keep track of all the unviable members. diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 7831807b5279d..36b24cc251d07 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -8567,6 +8567,9 @@ ConstraintSystem::simplifyConstructionConstraint( // variable T. T2 is the result type provided via the construction // constraint itself. addValueMemberConstraint(MetatypeType::get(valueType, getASTContext()), + // OK: simplifyConstructionConstraint() is only used + // for `T(...)` init calls, not `T.init(...)` calls, + // so there's no module selector on `init`. DeclNameRef::createConstructor(), memberType, useDC, functionRefInfo, @@ -10190,8 +10193,8 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, // high. if (auto *args = getArgumentList(memberLocator)) { SmallVector scratch; - memberName.getFullName() = DeclName(ctx, memberName.getBaseName(), - args->getArgumentLabels(scratch)); + memberName = memberName.withArgumentLabels( + ctx, args->getArgumentLabels(scratch)); } } @@ -10856,8 +10859,8 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, } // If we have no viable or unviable candidates, and we're generating, - // diagnostics, rerun the query with inaccessible members included, so we can - // include them in the unviable candidates list. + // diagnostics, rerun the query with various excluded members included, so we + // can include them in the unviable candidates list. if (result.ViableCandidates.empty() && result.UnviableCandidates.empty() && includeInaccessibleMembers) { NameLookupOptions lookupOptions = @@ -10866,7 +10869,8 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, // Local function that looks up additional candidates using the given lookup // options, recording the results as unviable candidates. auto lookupUnviable = - [&](NameLookupOptions lookupOptions, + [&](DeclNameRef memberName, + NameLookupOptions lookupOptions, MemberLookupResult::UnviableReason reason) -> bool { auto lookup = TypeChecker::lookupMember(DC, instanceTy, memberName, memberLoc, lookupOptions); @@ -10890,9 +10894,20 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, return !lookup.empty(); }; + // Look for members that were excluded because of a module selector. + if (memberName.hasModuleSelector()) { + DeclNameRef unqualifiedMemberName{memberName.getFullName()}; + + if (lookupUnviable(unqualifiedMemberName, + lookupOptions, + MemberLookupResult::UR_WrongModule)) + return result; + } + // Ignore access control so we get candidates that might have been missed // before. - if (lookupUnviable(lookupOptions | NameLookupFlags::IgnoreAccessControl, + if (lookupUnviable(memberName, + lookupOptions | NameLookupFlags::IgnoreAccessControl, MemberLookupResult::UR_Inaccessible)) return result; } @@ -11093,6 +11108,11 @@ static ConstraintFix *fixMemberRef( : nullptr; } + case MemberLookupResult::UR_WrongModule: + assert(choice.isDecl()); + return AllowMemberFromWrongModule::create(cs, baseTy, choice.getDecl(), + memberName, locator); + case MemberLookupResult::UR_Inaccessible: assert(choice.isDecl()); return AllowInaccessibleMember::create(cs, baseTy, choice.getDecl(), @@ -16022,6 +16042,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint( case FixKind::AllowInvalidInitRef: case FixKind::AllowClosureParameterDestructuring: case FixKind::AllowInaccessibleMember: + case FixKind::AllowMemberFromWrongModule: case FixKind::AllowAnyObjectKeyPathRoot: case FixKind::AllowMultiArgFuncKeyPathMismatch: case FixKind::TreatKeyPathSubscriptIndexAsHashable: diff --git a/lib/Sema/PreCheckTarget.cpp b/lib/Sema/PreCheckTarget.cpp index bac50536fe31c..b5fa95790e2f9 100644 --- a/lib/Sema/PreCheckTarget.cpp +++ b/lib/Sema/PreCheckTarget.cpp @@ -558,8 +558,7 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, } } - DeclName lookupName(context, Name.getBaseName(), lookupLabels); - LookupName = DeclNameRef(lookupName); + LookupName = Name.withArgumentLabels(context, lookupLabels); } // Perform standard value name lookup. @@ -576,8 +575,7 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, // First, look for a local binding in scope. if (Loc.isValid() && !Name.isOperator()) { - ASTScope::lookupLocalDecls(DC->getParentSourceFile(), - LookupName.getFullName(), Loc, + ASTScope::lookupLocalDecls(DC->getParentSourceFile(), LookupName, Loc, /*stopAfterInnermostBraceStmt=*/false, ResultValues); for (auto *localDecl : ResultValues) { @@ -637,6 +635,52 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, return errorResult(); } + // Is there an incorrect module selector? + if (Name.hasModuleSelector()) { + auto anyModuleName = DeclNameRef(LookupName.getFullName()); + auto anyModuleResults = TypeChecker::lookupUnqualified(DC, anyModuleName, + Loc, + lookupOptions); + if (!anyModuleResults.empty()) { + Context.Diags.diagnose(UDRE->getNameLoc(), diag::decl_not_in_module, + LookupName.getFullName(), + LookupName.getModuleSelector()); + + SourceLoc moduleSelectorLoc = UDRE->getNameLoc().getModuleSelectorLoc(); + + for (auto result : anyModuleResults) { + ValueDecl * decl = result.getValueDecl(); + Identifier moduleName = decl->getModuleContext()->getName(); + + if (moduleName != Name.getModuleSelector()) { + SmallString<64> replacement; + if (decl->isInstanceMember()) + replacement += "self."; + replacement += moduleName.str(); + + Context.Diags.diagnose(moduleSelectorLoc, + diag::note_change_module_selector, + moduleName) + .fixItReplace(moduleSelectorLoc, replacement); + } else { + // It's just something we need to pick up contextually. + if (decl->getDeclContext()->getLocalContext()) + decl->diagnose(diag::note_remove_module_selector) + .fixItRemoveChars(moduleSelectorLoc, + UDRE->getNameLoc().getBaseNameLoc()); + + if (decl->isInstanceMember()) + Context.Diags.diagnose(moduleSelectorLoc, + diag::note_add_explicit_self_with_module_selector) + .fixItInsert(moduleSelectorLoc, "self."); + } + } + + // FIXME: Can we recover by assuming the first/best result is correct? + return new (Context) ErrorExpr(UDRE->getSourceRange()); + } + } + // Try ignoring access control. NameLookupOptions relookupOptions = lookupOptions; relookupOptions |= NameLookupFlags::IgnoreAccessControl; @@ -2081,8 +2125,9 @@ VarDecl *PreCheckTarget::getImplicitSelfDeclForSuperContext(SourceLoc Loc) { // Do an actual lookup for 'self' in case it shows up in a capture list. auto *methodSelf = methodContext->getImplicitSelfDecl(); - auto *lookupSelf = ASTScope::lookupSingleLocalDecl(DC->getParentSourceFile(), - Ctx.Id_self, Loc); + auto *lookupSelf = ASTScope::lookupSingleLocalDecl( + DC->getParentSourceFile(), + DeclNameRef::createSelf(Ctx), Loc); if (lookupSelf && lookupSelf != methodSelf) { // FIXME: This is the wrong diagnostic for if someone manually declares a // variable named 'self' using backticks. diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index ffa49dc5736f8..0a8c32ad21219 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -3240,10 +3240,11 @@ SynthesizeMainFunctionRequest::evaluate(Evaluator &evaluator, } CS.addDisjunctionConstraint(typeEqualityConstraints, locator); - CS.addValueMemberConstraint( - nominal->getInterfaceType(), DeclNameRef(context.Id_main), - Type(mainType), declContext, FunctionRefInfo::singleBaseNameApply(), {}, - locator); + CS.addValueMemberConstraint(nominal->getInterfaceType(), + DeclNameRef(context.Id_main), // OK: Generated + Type(mainType), declContext, + FunctionRefInfo::singleBaseNameApply(), {}, + locator); } FuncDecl *mainFunction = nullptr; @@ -3808,6 +3809,28 @@ static void lookupReplacedDecl(DeclNameRef replacedDeclName, results); } +static void +diagnoseCandidatesEliminatedByModuleSelector(DeclNameRefWithLoc replacedDeclName, + DeclAttribute *attr, + const ValueDecl *replacement, + DiagnosticEngine &Diags) { + if (replacedDeclName.Name.getModuleSelector().empty()) + return; + + // Look up without the module selector + SmallVector results; + lookupReplacedDecl(DeclNameRef(replacedDeclName.Name.getFullName()), + attr, replacement, results); + + auto selectorLoc = replacedDeclName.Loc.getModuleSelectorLoc(); + + for (auto candidate : results) + Diags.diagnose(selectorLoc, diag::note_change_module_selector, + candidate->getModuleContext()->getBaseIdentifier()) + .fixItReplace(selectorLoc, + candidate->getModuleContext()->getBaseIdentifier().str()); +} + /// Remove any argument labels from the interface type of the given value that /// are extraneous from the type system's point of view, producing the /// type to compare against for the purposes of dynamic replacement. @@ -3827,14 +3850,14 @@ static Type getDynamicComparisonType(ValueDecl *value) { return interfaceType->removeArgumentLabels(numArgumentLabels); } -static FuncDecl *findSimilarAccessor(DeclNameRef replacedVarName, +static FuncDecl *findSimilarAccessor(DeclNameRefWithLoc replacedVarName, const AccessorDecl *replacement, DeclAttribute *attr, ASTContext &ctx, bool forDynamicReplacement) { // Retrieve the replaced abstract storage decl. SmallVector results; - lookupReplacedDecl(replacedVarName, attr, replacement, results); + lookupReplacedDecl(replacedVarName.Name, attr, replacement, results); // Filter out any accessors that won't work. if (!results.empty()) { @@ -3867,15 +3890,19 @@ static FuncDecl *findSimilarAccessor(DeclNameRef replacedVarName, if (results.empty()) { Diags.diagnose(attr->getLocation(), diag::dynamic_replacement_accessor_not_found, - replacedVarName); + replacedVarName.Name); attr->setInvalid(); + + diagnoseCandidatesEliminatedByModuleSelector(replacedVarName, attr, + replacement, Diags); + return nullptr; } if (results.size() > 1) { Diags.diagnose(attr->getLocation(), diag::dynamic_replacement_accessor_ambiguous, - replacedVarName); + replacedVarName.Name); for (auto result : results) { Diags.diagnose(result, diag::dynamic_replacement_accessor_ambiguous_candidate, @@ -3917,7 +3944,7 @@ static FuncDecl *findSimilarAccessor(DeclNameRef replacedVarName, return origAccessor; } -static FuncDecl *findReplacedAccessor(DeclNameRef replacedVarName, +static FuncDecl *findReplacedAccessor(DeclNameRefWithLoc replacedVarName, const AccessorDecl *replacement, DeclAttribute *attr, ASTContext &ctx) { @@ -3925,7 +3952,7 @@ static FuncDecl *findReplacedAccessor(DeclNameRef replacedVarName, /*forDynamicReplacement*/ true); } -static FuncDecl *findTargetAccessor(DeclNameRef replacedVarName, +static FuncDecl *findTargetAccessor(DeclNameRefWithLoc replacedVarName, const AccessorDecl *replacement, DeclAttribute *attr, ASTContext &ctx) { @@ -3934,7 +3961,7 @@ static FuncDecl *findTargetAccessor(DeclNameRef replacedVarName, } static AbstractFunctionDecl * -findSimilarFunction(DeclNameRef replacedFunctionName, +findSimilarFunction(DeclNameRefWithLoc replacedFunctionName, const AbstractFunctionDecl *base, DeclAttribute *attr, DiagnosticEngine *Diags, bool forDynamicReplacement) { @@ -3942,7 +3969,7 @@ findSimilarFunction(DeclNameRef replacedFunctionName, // Any modification to attr must be guarded by a null check on TC. // SmallVector lookupResults; - lookupReplacedDecl(replacedFunctionName, attr, base, lookupResults); + lookupReplacedDecl(replacedFunctionName.Name, attr, base, lookupResults); SmallVector candidates; for (auto *result : lookupResults) { @@ -3963,7 +3990,9 @@ findSimilarFunction(DeclNameRef replacedFunctionName, forDynamicReplacement ? diag::dynamic_replacement_function_not_found : diag::specialize_target_function_not_found, - replacedFunctionName); + replacedFunctionName.Name); + diagnoseCandidatesEliminatedByModuleSelector(replacedFunctionName, attr, + base, *Diags); } attr->setInvalid(); @@ -4029,7 +4058,7 @@ findSimilarFunction(DeclNameRef replacedFunctionName, forDynamicReplacement ? diag::dynamic_replacement_function_of_type_not_found : diag::specialize_target_function_of_type_not_found, - replacedFunctionName, + replacedFunctionName.Name, base->getInterfaceType()->getCanonicalType()); for (auto *result : matches) { @@ -4045,7 +4074,7 @@ findSimilarFunction(DeclNameRef replacedFunctionName, } static AbstractFunctionDecl * -findReplacedFunction(DeclNameRef replacedFunctionName, +findReplacedFunction(DeclNameRefWithLoc replacedFunctionName, const AbstractFunctionDecl *replacement, DynamicReplacementAttr *attr, DiagnosticEngine *Diags) { return findSimilarFunction(replacedFunctionName, replacement, attr, Diags, @@ -4053,7 +4082,7 @@ findReplacedFunction(DeclNameRef replacedFunctionName, } static AbstractFunctionDecl * -findTargetFunction(DeclNameRef targetFunctionName, +findTargetFunction(DeclNameRefWithLoc targetFunctionName, const AbstractFunctionDecl *base, AbstractSpecializeAttr * attr, DiagnosticEngine *diags) { return findSimilarFunction(targetFunctionName, base, attr, diags, @@ -5706,13 +5735,15 @@ DynamicallyReplacedDeclRequest::evaluate(Evaluator &evaluator, } auto &Ctx = VD->getASTContext(); + DeclNameRefWithLoc nameWithLoc{attr->getReplacedFunctionName(), + attr->getReplacedFunctionNameLoc(), + std::nullopt}; if (auto *AD = dyn_cast(VD)) { - return findReplacedAccessor(attr->getReplacedFunctionName(), AD, attr, Ctx); + return findReplacedAccessor(nameWithLoc, AD, attr, Ctx); } if (auto *AFD = dyn_cast(VD)) { - return findReplacedFunction(attr->getReplacedFunctionName(), AFD, - attr, &Ctx.Diags); + return findReplacedFunction(nameWithLoc, AFD, attr, &Ctx.Diags); } if (auto *SD = dyn_cast(VD)) { @@ -5735,8 +5766,10 @@ SpecializeAttrTargetDeclRequest::evaluate(Evaluator &evaluator, auto &ctx = vd->getASTContext(); - auto targetFunctionName = attr->getTargetFunctionName(); - if (!targetFunctionName) + DeclNameRefWithLoc targetFunctionName{attr->getTargetFunctionName(), + attr->getTargetFunctionNameLoc(), + std::nullopt}; + if (!targetFunctionName.Name) return nullptr; if (auto *ad = dyn_cast(vd)) { diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index fc7fd1d563df9..20c5e71191353 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -574,8 +574,8 @@ BodyInitKindRequest::evaluate(Evaluator &evaluator, auto loc = declRef->getLoc(); if (name.isSimpleName(ctx.Id_self)) { auto *otherSelfDecl = - ASTScope::lookupSingleLocalDecl(Decl->getParentSourceFile(), - name.getFullName(), loc); + ASTScope::lookupSingleLocalDecl(Decl->getParentSourceFile(), name, + loc); if (otherSelfDecl == Decl->getImplicitSelfDecl()) myKind = BodyInitKind::Delegating; } diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index a290483e08c72..f3b27cea71e35 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -731,7 +731,8 @@ CheckRedeclarationRequest::evaluate(Evaluator &eval, ValueDecl *current, else roleFilter = currentIsABIOnly ? ABIRole::ProvidesABI : ABIRole::ProvidesAPI; - ASTScope::lookupLocalDecls(currentFile, current->getBaseName(), + ASTScope::lookupLocalDecls(currentFile, + DeclNameRef(current->getBaseName()), current->getLoc(), /*stopAfterInnermostBraceStmt=*/true, roleFilter, otherDefinitions); diff --git a/lib/Sema/TypeCheckNameLookup.cpp b/lib/Sema/TypeCheckNameLookup.cpp index 7d4853b9d3738..dca7c2c9fdabb 100644 --- a/lib/Sema/TypeCheckNameLookup.cpp +++ b/lib/Sema/TypeCheckNameLookup.cpp @@ -60,6 +60,7 @@ namespace { class LookupResultBuilder { LookupResult &Result; DeclContext *DC; + Identifier ModuleSelector; NameLookupOptions Options; /// The vector of found declarations. @@ -72,8 +73,9 @@ namespace { public: LookupResultBuilder(LookupResult &result, DeclContext *dc, - NameLookupOptions options) - : Result(result), DC(dc), Options(options) { + Identifier moduleSelector, NameLookupOptions options) + : Result(result), DC(dc), ModuleSelector(moduleSelector), Options(options) + { if (dc->getASTContext().isAccessControlDisabled()) Options |= NameLookupFlags::IgnoreAccessControl; } @@ -83,6 +85,11 @@ namespace { removeOverriddenDecls(FoundDecls); removeOverriddenDecls(FoundOuterDecls); + // Remove any declarations excluded by the module selector from the + // found-declarations set. + removeOutOfModuleDecls(FoundDecls, ModuleSelector, DC); + removeOutOfModuleDecls(FoundOuterDecls, ModuleSelector, DC); + // Remove any shadowed declarations from the found-declarations set. removeShadowedDecls(FoundDecls, DC); removeShadowedDecls(FoundOuterDecls, DC); @@ -290,7 +297,7 @@ LookupResult TypeChecker::lookupUnqualified(DeclContext *dc, DeclNameRef name, UnqualifiedLookupRequest{descriptor}, {}); LookupResult result; - LookupResultBuilder builder(result, dc, options); + LookupResultBuilder builder(result, dc, name.getModuleSelector(), options); for (auto idx : indices(lookup.allResults())) { const auto &found = lookup[idx]; // Determine which type we looked through to find this result. @@ -381,7 +388,7 @@ LookupResult TypeChecker::lookupMember(DeclContext *dc, // Make sure we've resolved implicit members, if we need them. namelookup::installSemanticMembersIfNeeded(type, name); - LookupResultBuilder builder(result, dc, options); + LookupResultBuilder builder(result, dc, name.getModuleSelector(), options); SmallVector lookupResults; dc->lookupQualified(type, name, loc, subOptions, lookupResults); diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index 7b32dc99b585f..a78fa09600412 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -1592,8 +1592,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; } } @@ -1699,15 +1700,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; } diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index c20b71c676f7f..3f3a64f013c50 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -1492,6 +1492,33 @@ static Type diagnoseUnknownType(const TypeResolution &resolution, return ErrorType::get(ctx); } + // Is there an incorrect module selector? + if (repr->getNameRef().hasModuleSelector()) { + auto anyModuleName = DeclNameRef(repr->getNameRef().getFullName()); + auto anyModuleResults = + TypeChecker::lookupUnqualifiedType(dc, anyModuleName, + repr->getLoc(), lookupOptions); + if (!anyModuleResults.empty()) { + diags.diagnose(repr->getNameLoc(), diag::type_not_in_module, + repr->getNameRef().getFullName(), + repr->getNameRef().getModuleSelector()); + + SourceLoc moduleSelectorLoc = repr->getNameLoc().getModuleSelectorLoc(); + + for (auto result : anyModuleResults) { + TypeDecl * decl = static_cast(result.getValueDecl()); + Identifier moduleName = decl->getModuleContext()->getName(); + + diags.diagnose(moduleSelectorLoc, diag::note_change_module_selector, + moduleName) + .fixItReplace(moduleSelectorLoc, moduleName.str()); + } + + // FIXME: Can we recover by assuming the first/best result is correct? + return ErrorType::get(ctx); + } + } + // Try ignoring access control. NameLookupOptions relookupOptions = lookupOptions; relookupOptions |= NameLookupFlags::IgnoreAccessControl; @@ -1583,6 +1610,32 @@ static Type diagnoseUnknownType(const TypeResolution &resolution, return ErrorType::get(ctx); } + // Is there an incorrect module selector? + if (repr->getNameRef().hasModuleSelector()) { + auto anyModuleName = DeclNameRef(repr->getNameRef().getFullName()); + auto anyModuleResults = TypeChecker::lookupMemberType( + dc, parentType, anyModuleName, repr->getLoc(), lookupOptions); + if (anyModuleResults) { + diags.diagnose(repr->getNameLoc(), diag::type_not_in_module, + repr->getNameRef().getFullName(), + repr->getNameRef().getModuleSelector()); + + SourceLoc moduleSelectorLoc = repr->getNameLoc().getModuleSelectorLoc(); + + for (auto result : anyModuleResults) { + TypeDecl * decl = result.Member; + Identifier moduleName = decl->getModuleContext()->getName(); + + diags.diagnose(moduleSelectorLoc, diag::note_change_module_selector, + moduleName) + .fixItReplace(moduleSelectorLoc, moduleName.str()); + } + + // FIXME: Can we recover by assuming the first/best result is correct? + return ErrorType::get(ctx); + } + } + // Try ignoring access control. NameLookupOptions relookupOptions = lookupOptions; relookupOptions |= NameLookupFlags::IgnoreAccessControl; diff --git a/test/NameLookup/Inputs/ModuleSelectorTestingKit.swiftinterface b/test/NameLookup/Inputs/ModuleSelectorTestingKit.swiftinterface new file mode 100644 index 0000000000000..631b3ecbf5898 --- /dev/null +++ b/test/NameLookup/Inputs/ModuleSelectorTestingKit.swiftinterface @@ -0,0 +1,42 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: -module-name ModuleSelectorTestingKit -swift-version 5 + +import Swift + +// These types are identical; we just use them to test with different scope +// selectors. + +public struct A { + public init(value: Swift.Int) + public dynamic mutating func negate() + public var magnitude: Swift.UInt +} + +public struct B { + public init(value: Swift.Int) + public dynamic mutating func negate() + public var magnitude: Swift.UInt +} + +public struct C { + public init(value: Int) + public dynamic mutating func negate() + public var magnitude: Swift.UInt +} + +public struct D { + public init(value: Int) + public dynamic mutating func negate() + public var magnitude: Swift.UInt +} + +@propertyWrapper +public struct available { + public init() {} + public var wrappedValue: Int { 0 } +} + +@_functionBuilder +public struct MyBuilder { + public static func buildBlock() +} diff --git a/test/NameLookup/module_selector.swift b/test/NameLookup/module_selector.swift index 0efc97316ec2c..ddbfce6afba71 100644 --- a/test/NameLookup/module_selector.swift +++ b/test/NameLookup/module_selector.swift @@ -1,3 +1,358 @@ -// 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 +// RUN: %target-typecheck-verify-swift -sdk %clang-importer-sdk -module-name main -I %S/Inputs -enable-experimental-feature ModuleSelector -enable-experimental-feature ParserASTGen -// REQUIRES: swift_feature_ModuleSelector +// REQUIRES: swift_feature_ModuleSelector, swift_feature_ParserASTGen + +// FIXME: This test doesn't really cover: +// +// * Whether X::foo finds foos in X's re-exports +// * Whether we handle access paths correctly +// * Interaction with ClangImporter +// * Cross-import overlays +// * Key paths +// * Key path dynamic member lookup +// * Custom type attributes (and coverage of type attrs generally is sparse) +// * Macros +// +// It also might not cover all combinations of name lookup paths and inputs. + +import ModuleSelectorTestingKit + +import ctypes.bits +import struct ModuleSelectorTestingKit::A + +let magnitude: Never = fatalError() + +// Test correct code using `A` + +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 + // expected-error@-1 {{cannot convert value of type 'Never' to specified type 'Int.Magnitude' (aka 'UInt')}} + + _ = (fn, 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:)? +} + +// Test resolution of main:: using `B` + +extension main::B {} +// expected-error@-1 {{type 'B' is not imported through module 'main'}} +// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{11-15=ModuleSelectorTestingKit}} + +extension B: @retroactive main::Equatable { + // expected-error@-1 {{type 'Equatable' is not imported through module 'main'}} + // expected-note@-2 {{did you mean module 'Swift'?}} {{27-31=Swift}} + + @_implements(main::Equatable, ==(_:_:)) + // expected-error@-1 {{type 'Equatable' is not imported through module 'main'}} + // expected-note@-2 {{did you mean module 'Swift'?}} {{16-20=Swift}} + + public static func equals(_: main::B, _: main::B) -> main::Bool { + // expected-error@-1 2{{type 'B' is not imported through module 'main'}} + // expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{32-36=ModuleSelectorTestingKit}} + // expected-note@-3 {{did you mean module 'ModuleSelectorTestingKit'?}} {{44-48=ModuleSelectorTestingKit}} + // expected-error@-4 {{type 'Bool' is not imported through module 'main'}} + // expected-note@-5 {{did you mean module 'Swift'?}} {{56-60=Swift}} + main::fatalError() // no-error -- not typechecking function bodies + } + + // FIXME: Add tests with autodiff @_differentiable(jvp:vjp:) and + // @_derivative(of:) + + @_dynamicReplacement(for: main::negate()) + // expected-error@-1 {{replaced function 'main::negate()' could not be found}} + // expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{29-33=ModuleSelectorTestingKit}} + + mutating func myNegate() { + let fn: (main::Int, main::Int) -> main::Int = + // expected-error@-1 3{{type 'Int' is not imported through module 'main'}} + // expected-note@-2 {{did you mean module 'Swift'?}} {{14-18=Swift}} + // expected-note@-3 {{did you mean module 'Swift'?}} {{25-29=Swift}} + // expected-note@-4 {{did you mean module 'Swift'?}} {{39-43=Swift}} + (main::+) + // FIXME: should fail???? + + let magnitude: Int.main::Magnitude = main::magnitude + // expected-error@-1 {{type 'Magnitude' is not imported through module 'main'}} + // expected-note@-2 {{did you mean module 'Swift'?}} {{24-28=Swift}} + + _ = (fn, magnitude) + + if main::Bool.main::random() { + // expected-error@-1 {{declaration 'Bool' is not imported through module 'main'}} + // expected-note@-2 {{did you mean module 'Swift'?}} {{8-12=Swift}} + + main::negate() + // expected-error@-1 {{declaration 'negate' is not imported through module 'main'}} + // expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{7-11=self.ModuleSelectorTestingKit}} + } + else { + self = main::B(value: .main::min) + // expected-error@-1 {{declaration 'B' is not imported through module 'main'}} + // expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{14-18=ModuleSelectorTestingKit}} + // expected-error@-3 {{cannot infer contextual base in reference to member 'main::min'}} + + self = B.main::init(value: .min) + // expected-error@-1 {{declaration 'init(value:)' is not imported through module 'main'}} + // expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{16-20=ModuleSelectorTestingKit}} + } + + self.main::myNegate() + + main::fatalError() + // expected-error@-1 {{declaration 'fatalError' is not imported through module 'main'}} + // expected-note@-2 {{did you mean module 'Swift'?}} {{5-9=Swift}} + } + + // FIXME: Can we test @convention(witness_method:)? +} + +// Test resolution of ModuleSelectorTestingKit:: using `C` + +extension ModuleSelectorTestingKit::C {} + +extension C: @retroactive ModuleSelectorTestingKit::Equatable { + // expected-error@-1 {{type 'Equatable' is not imported through module 'ModuleSelectorTestingKit'}} + // expected-note@-2 {{did you mean module 'Swift'?}} {{27-51=Swift}} + + @_implements(ModuleSelectorTestingKit::Equatable, ==(_:_:)) + // expected-error@-1 {{type 'Equatable' is not imported through module 'ModuleSelectorTestingKit'}} + // expected-note@-2 {{did you mean module 'Swift'?}} {{16-40=Swift}} + + public static func equals(_: ModuleSelectorTestingKit::C, _: ModuleSelectorTestingKit::C) -> ModuleSelectorTestingKit::Bool { + // expected-error@-1 {{type 'Bool' is not imported through module 'ModuleSelectorTestingKit'}} + // expected-note@-2 {{did you mean module 'Swift'?}} {{96-120=Swift}} + + ModuleSelectorTestingKit::fatalError() // no-error -- not typechecking function bodies + } + + // FIXME: Add tests with autodiff @_differentiable(jvp:vjp:) and + // @_derivative(of:) + + @_dynamicReplacement(for: ModuleSelectorTestingKit::negate()) + + mutating func myNegate() { + // expected-note@-1 {{'myNegate()' declared here}} + + let fn: (ModuleSelectorTestingKit::Int, ModuleSelectorTestingKit::Int) -> ModuleSelectorTestingKit::Int = + // expected-error@-1 3{{type 'Int' is not imported through module 'ModuleSelectorTestingKit'}} + // expected-note@-2 {{did you mean module 'Swift'?}} {{14-38=Swift}} + // expected-note@-3 {{did you mean module 'Swift'?}} {{45-69=Swift}} + // expected-note@-4 {{did you mean module 'Swift'?}} {{79-103=Swift}} + (ModuleSelectorTestingKit::+) + // FIXME: should fail???? + + let magnitude: Int.ModuleSelectorTestingKit::Magnitude = ModuleSelectorTestingKit::magnitude + // expected-error@-1 {{type 'Magnitude' is not imported through module 'ModuleSelectorTestingKit'}} + // expected-note@-2 {{did you mean module 'Swift'?}} {{24-48=Swift}} + + _ = (fn, magnitude) + + if ModuleSelectorTestingKit::Bool.ModuleSelectorTestingKit::random() { + // expected-error@-1 {{declaration 'Bool' is not imported through module 'ModuleSelectorTestingKit'}} + // expected-note@-2 {{did you mean module 'Swift'?}} {{8-32=Swift}} + + ModuleSelectorTestingKit::negate() + // expected-error@-1 {{declaration 'negate' is not imported through module 'ModuleSelectorTestingKit'}} + // expected-note@-2 {{did you mean the member of 'self'?}} {{7-7=self.}} + } + else { + self = ModuleSelectorTestingKit::C(value: .ModuleSelectorTestingKit::min) + // expected-error@-1 {{declaration 'min' is not imported through module 'ModuleSelectorTestingKit'}} + // expected-note@-2 {{did you mean module 'Swift'?}} {{50-74=Swift}} + + self = C.ModuleSelectorTestingKit::init(value: .min) + } + + self.ModuleSelectorTestingKit::myNegate() + // expected-error@-1 {{declaration 'myNegate()' is not imported through module 'ModuleSelectorTestingKit'}} + // expected-note@-2 {{did you mean module 'main'?}} {{10-34=main}} + + ModuleSelectorTestingKit::fatalError() + // expected-error@-1 {{declaration 'fatalError' is not imported through module 'ModuleSelectorTestingKit'}} + // expected-note@-2 {{did you mean module 'Swift'?}} {{5-29=Swift}} + } + + // FIXME: Can we test @convention(witness_method:)? +} + +// Test resolution of Swift:: using `D` + +extension Swift::D {} +// expected-error@-1 {{type 'D' is not imported through module 'Swift'}} +// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{11-16=ModuleSelectorTestingKit}} + +extension D: @retroactive Swift::Equatable { +// Caused by Swift::D failing to typecheck in `equals(_:_:)`: expected-error@-1 *{{extension outside of file declaring struct 'D' prevents automatic synthesis of '==' for protocol 'Equatable'}} expected-note@-1 *{{add stubs for conformance}} + + @_implements(Swift::Equatable, ==(_:_:)) + public static func equals(_: Swift::D, _: Swift::D) -> Swift::Bool { + // expected-error@-1 2{{type 'D' is not imported through module 'Swift'}} + // expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{32-37=ModuleSelectorTestingKit}} + // expected-note@-3 {{did you mean module 'ModuleSelectorTestingKit'?}} {{45-50=ModuleSelectorTestingKit}} + Swift::fatalError() // no-error -- not typechecking function bodies + } + + // FIXME: Add tests with autodiff @_differentiable(jvp:vjp:) and + // @_derivative(of:) + + @_dynamicReplacement(for: Swift::negate()) + // expected-error@-1 {{replaced function 'Swift::negate()' could not be found}} + // expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{29-34=ModuleSelectorTestingKit}} + + mutating func myNegate() { + // expected-note@-1 {{'myNegate()' declared here}} + + let fn: (Swift::Int, Swift::Int) -> Swift::Int = + (Swift::+) + + let magnitude: Int.Swift::Magnitude = Swift::magnitude + // expected-error@-1 {{declaration 'magnitude' is not imported through module 'Swift'}} + // expected-note@-2 {{did you mean module 'main'?}} {{43-48=main}} + + _ = (fn, magnitude) + + if Swift::Bool.Swift::random() { + + Swift::negate() + // expected-error@-1 {{declaration 'negate' is not imported through module 'Swift'}} + // expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{7-12=self.ModuleSelectorTestingKit}} + } + else { + self = Swift::D(value: .Swift::min) + // expected-error@-1 {{declaration 'D' is not imported through module 'Swift'}} + // expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{14-19=ModuleSelectorTestingKit}} + // expected-error@-3 {{cannot infer contextual base in reference to member 'Swift::min'}} + + self = D.Swift::init(value: .min) + // expected-error@-1 {{declaration 'init(value:)' is not imported through module 'Swift'}} + // expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{16-21=ModuleSelectorTestingKit}} + } + + self.Swift::myNegate() + // expected-error@-1 {{declaration 'myNegate()' is not imported through module 'Swift'}} + // expected-note@-2 {{did you mean module 'main'?}} {{10-15=main}} + + Swift::fatalError() + } + + // FIXME: Can we test @convention(witness_method:)? +} + +let mog: Never = fatalError() + +func localVarsCantBeAccessedByModuleSelector() { + let mag: Int.Swift::Magnitude = main::mag + // expected-error@-1 {{declaration 'mag' is not imported through module 'main'}} + // expected-note@-2 {{did you mean the local declaration?}} {{35-41=}} + + let mog: Never = main::mog +} + +struct AvailableUser { + @available(macOS 10.15, *) var use1: String { "foo" } + + @main::available() var use2 + // FIXME improve: expected-error@-1 {{unknown attribute 'available'}} + // FIXME suppress: expected-error@-2 {{type annotation missing in pattern}} + + @ModuleSelectorTestingKit::available() var use4 + // no-error + + @Swift::available() var use5 + // FIXME improve: expected-error@-1 {{unknown attribute 'available'}} + // FIXME suppress: expected-error@-2 {{type annotation missing in pattern}} +} + +func builderUser2(@main::MyBuilder fn: () -> Void) {} +// FIXME improve: expected-error@-1 {{unknown attribute 'MyBuilder'}} + +func builderUser3(@ModuleSelectorTestingKit::MyBuilder fn: () -> Void) {} +// no-error + +func builderUser4(@Swift::MyBuilder fn: () -> Void) {} +// FIXME improve: expected-error@-1 {{unknown attribute 'MyBuilder'}} + +// Error cases + +func decl1( + p1: main::A, + // expected-error@-1 {{type 'A' is not imported through module 'main'}} + // expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{7-11=ModuleSelectorTestingKit}} + label p2: inout A, + // From uses in the switch statements below: expected-note@-1 3 {{did you mean the local declaration?}} + label p3: @escaping () -> A +) { + switch Optional(main::p2) { + // expected-error@-1 {{declaration 'p2' is not imported through module 'main'}} + case Optional.some(let decl1i): + break + case .none: + break + } + + switch Optional(main::p2) { + // expected-error@-1 {{declaration 'p2' is not imported through module 'main'}} + case let Optional.some(decl1j): + break + case .none: + break + } + + switch Optional(main::p2) { + // expected-error@-1 {{declaration 'p2' is not imported through module 'main'}} + case let decl1k?: + break + case .none: + break + } +} + +typealias decl5 = main::Bool +// expected-error@-1 {{type 'Bool' is not imported through module 'main'}} +// expected-note@-2 {{did you mean module 'Swift'?}} {{19-23=Swift}} + +func badModuleNames() { + NonexistentModule::print() + // expected-error@-1 {{declaration 'print' is not imported through module 'NonexistentModule'}} + // expected-note@-2 {{did you mean module 'Swift'?}} {{3-20=Swift}} + // FIXME redundant: expected-note@-3 {{did you mean module 'Swift'?}} + + _ = "foo".NonexistentModule::count + // expected-error@-1 {{declaration 'count' is not imported through module 'NonexistentModule'}} + // expected-note@-2 {{did you mean module 'Swift'?}} {{13-30=Swift}} + + let x: NonexistentModule::MyType = NonexistentModule::MyType() + // expected-error@-1 {{cannot find type 'NonexistentModule::MyType' in scope}} + + let y: A.NonexistentModule::MyChildType = fatalError() + // expected-error@-1 {{'NonexistentModule::MyChildType' is not a member type of struct 'ModuleSelectorTestingKit.A'}} +} diff --git a/test/Parse/module_selector.swift b/test/Parse/module_selector.swift new file mode 100644 index 0000000000000..831793af76f81 --- /dev/null +++ b/test/Parse/module_selector.swift @@ -0,0 +1,873 @@ +// 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, swift_feature_ParserASTGen + +// ModuleSelectorImports +import struct ModuleSelectorTestingKit::A + +import struct _::A +// expected-error@-1 {{'_' cannot be used as an identifier here}} +// expected-legacy-note@-2 {{if this name is unavoidable, use backticks to escape it}} {{15-16=`_`}} + +import struct ModuleSelectorTestingKit::Submodule::A +// 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-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-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 +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-legacy-error@-1 {{expected ',' separator}} expected-new-error@-1 {{unexpected code '10.15, *' in attribute}} + + @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-legacy-error@-1 {{expected ',' separator}} expected-new-error@-1 {{unexpected code '10.15, *' in attribute}} + + +// ModuleSelectorWhitespace +_ = Swift::print + +_ = Swift:: print + +_ = Swift ::print + +_ = Swift :: print + +_ = Swift:: +print +// 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-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 + +_ = Swift +:: +print +// 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-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-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-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-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-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-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-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-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-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-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-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-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-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 + } + + switch Optional(main::decl1g) { + case let Optional.some(Swift::decl1j): + // 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 + } + + switch Optional(main::decl1g) { + case let Swift::decl1k?: + // 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-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}} +} + + +// ModuleSelectorIncorrectClosureDecls +// This gets radically misinterpreted as two statements followed by some invalid code. +"lll".forEach { [Swift::magnitude] + main::elem in print(elem) + // 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-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-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-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-legacy-error@-1 {{expected '{' in enum}} expected-new-error@-1 {{unexpected code '::decl2' in enum}} +enum decl2_substitute { + // expected-legacy-note@-1 {{in declaration of 'decl2_substitute'}} + case Swift::decl2a + // 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-legacy-error@-1 {{expected '{' in struct}} expected-new-error@-1 {{unexpected code '::decl3' in struct}} + +class main::decl4 {} +// expected-legacy-error@-1 {{expected '{' in class}} expected-new-error@-1 {{unexpected code '::decl4' in class}} + +typealias main::decl5 = Swift::Bool +// expected-legacy-error@-1 {{expected '=' in type alias declaration}} expected-new-error@-1 {{unexpected code '::decl5' in typealias declaration}} + +protocol main::decl6 {} +// expected-legacy-error@-1 {{expected '{' in protocol type}} expected-new-error@-1 {{unexpected code '::decl6' in protocol}} +protocol decl6_substitute { + // expected-legacy-note@-1 {{in declaration of 'decl6_substitute'}} + associatedtype Swift::decl6a + // 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-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-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-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-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-legacy-note@-1 {{in declaration of 'Parent'}} + + func main::decl1() {} + // 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-legacy-error@-1 {{expected '{' in enum}} expected-new-error@-1 {{unexpected code '::decl2' in enum}} + + enum decl2_substitute { + // expected-legacy-note@-1 {{in declaration of 'decl2_substitute'}} + case Swift::decl2a + // 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-legacy-error@-1 {{expected '{' in struct}} expected-new-error@-1 {{unexpected code '::decl3' in struct}} + + class main::decl4 {} +// expected-legacy-error@-1 {{expected '{' in class}} expected-new-error@-1 {{unexpected code '::decl4' in class}} + + typealias main::decl5 = Swift::Bool +// expected-legacy-error@-1 {{expected '=' in type alias declaration}} expected-new-error@-1 {{unexpected code '::decl5' in typealias declaration}} +} + + +// ModuleSelectorMacroDecls +struct CreatesDeclExpectation { + #main::myMacro() +} + + +// ModuleSelectorIncorrectRuntimeBaseAttr +@_swift_native_objc_runtime_base(main::BaseClass) +// 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-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-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-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-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-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}} +// 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-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}} +// 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}} +// 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-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-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}} +// 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-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}} +// 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}} +// 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-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-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}} +// 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-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}} +// 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}} +// 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-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-legacy-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-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() { + 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}} +// 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-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-legacy-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-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() { + _ = 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-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-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-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-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-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) +func fn() {} + + +// ModuleSelectorExpr +let x = Swift::do { 1 } + +let x = Swift:: +do { 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-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-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-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-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-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-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-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-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-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-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-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-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-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-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 + +_ = 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-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-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 + +_ = Swift::Any + +_ = { + _ = Swift::$0 + // 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-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-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-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-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-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-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-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-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 + +_ = x.Swift::Self.self + +_ = x.Swift::Type.self + +_ = x.Swift::Protocol.self + +_ = myArray.reduce(0, Swift::+) + +if Swift::#available(macOS 15, *) {} +// 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) {} + +func fn(_: Swift::Any) {} + +func fn(_: Swift::Foo) {} + +func fn(_: Swift::(Int, String)) {} +// 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-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-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) {} + +func fn(_: Foo.Swift::Protocol) {} + +func fn(_: Foo.Swift::Bar) {} + +func fn(_: Foo.Swift::self) {} + + +// ModuleSelectorSubmodule + +_ = Foundation::NSData::NSData() +// 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-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-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#>}} 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 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) +}