diff --git a/include/swift/AST/ASTScope.h b/include/swift/AST/ASTScope.h index 5ebe70dcef3be..3411bed70fbf9 100644 --- a/include/swift/AST/ASTScope.h +++ b/include/swift/AST/ASTScope.h @@ -218,6 +218,10 @@ class ASTScopeImpl : public ASTAllocated { return nullptr; } + virtual NullablePtr getFreestandingMacro() const { + return nullptr; + } + #pragma mark - debugging and printing public: @@ -278,6 +282,10 @@ class ASTScopeImpl : public ASTAllocated { static std::pair lookupFallthroughSourceAndDest(SourceFile *sourceFile, SourceLoc loc); + static void lookupEnclosingMacroScope( + SourceFile *sourceFile, SourceLoc loc, + llvm::function_ref consume); + /// Scopes that cannot bind variables may set this to true to create more /// compact scope tree in the debug info. virtual bool ignoreInDebugInfo() const { return false; } @@ -840,24 +848,20 @@ class DefaultArgumentInitializerScope final : public ASTScopeImpl { bool ignoreInDebugInfo() const override { return true; } }; -/// Consider: -/// @_propertyWrapper -/// struct WrapperWithInitialValue { -/// } -/// struct HasWrapper { -/// @WrapperWithInitialValue var y = 17 -/// } -/// Lookup has to be able to find the use of WrapperWithInitialValue, that's -/// what this scope is for. Because the source positions are screwy. - -class AttachedPropertyWrapperScope final : public ASTScopeImpl { +/// The scope for custom attributes and their arguments, such as for +/// attached property wrappers and for attached macros. +/// +/// Source locations for the attribute name and its arguments are in the +/// custom attribute, so lookup is invoked from within the attribute +/// itself. +class CustomAttributeScope final : public ASTScopeImpl { public: CustomAttr *attr; - VarDecl *decl; + Decl *decl; - AttachedPropertyWrapperScope(CustomAttr *attr, VarDecl *decl) + CustomAttributeScope(CustomAttr *attr,Decl *decl) : attr(attr), decl(decl) {} - virtual ~AttachedPropertyWrapperScope() {} + virtual ~CustomAttributeScope() {} protected: ASTScopeImpl *expandSpecifically(ScopeCreator &) override; @@ -871,7 +875,8 @@ class AttachedPropertyWrapperScope final : public ASTScopeImpl { NullablePtr getDeclAttributeIfAny() const override { return attr; } - bool ignoreInDebugInfo() const override { return true; } + bool ignoreInDebugInfo() const override { return true; } + private: void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &); }; @@ -1134,9 +1139,9 @@ class SpecializeAttributeScope final : public ASTScopeImpl { class DifferentiableAttributeScope final : public ASTScopeImpl { public: DifferentiableAttr *const differentiableAttr; - ValueDecl *const attributedDeclaration; + Decl *const attributedDeclaration; - DifferentiableAttributeScope(DifferentiableAttr *diffAttr, ValueDecl *decl) + DifferentiableAttributeScope(DifferentiableAttr *diffAttr, Decl *decl) : differentiableAttr(diffAttr), attributedDeclaration(decl) {} virtual ~DifferentiableAttributeScope() {} @@ -1270,6 +1275,10 @@ class MacroExpansionDeclScope final : public ASTScopeImpl { SourceRange getSourceRangeOfThisASTNode(bool omitAssertions = false) const override; + NullablePtr getFreestandingMacro() const override { + return decl; + } + protected: void printSpecifics(llvm::raw_ostream &out) const override; diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index b6b2d8396a46f..8de237d91cd67 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -3899,7 +3899,7 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext { /// protocols to which the nominal type conforms. Furthermore, the resulting /// set of declarations has not been filtered for visibility, nor have /// overridden declarations been removed. - TinyPtrVector lookupDirect(DeclName name, + TinyPtrVector lookupDirect(DeclName name, SourceLoc loc = SourceLoc(), OptionSet flags = OptionSet()); @@ -4454,7 +4454,8 @@ class ClassDecl final : public NominalTypeDecl { // Force loading all the members, which will add this attribute if any of // members are determined to be missing while loading. auto mutableThis = const_cast(this); - (void)mutableThis->lookupDirect(DeclBaseName::createConstructor()); + (void)mutableThis->lookupDirect(DeclBaseName::createConstructor(), + getStartLoc()); } if (Bits.ClassDecl.ComputedHasMissingDesignatedInitializers) diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h index d6e21e3167959..8de5bd8494950 100644 --- a/include/swift/AST/DeclContext.h +++ b/include/swift/AST/DeclContext.h @@ -598,7 +598,8 @@ class alignas(1 << DeclContextAlignInBits) DeclContext /// lookup. /// /// \returns true if anything was found. - bool lookupQualified(Type type, DeclNameRef member, NLOptions options, + bool lookupQualified(Type type, DeclNameRef member, + SourceLoc loc, NLOptions options, SmallVectorImpl &decls) const; /// Look for the set of declarations with the given name within the @@ -616,12 +617,12 @@ class alignas(1 << DeclContextAlignInBits) DeclContext /// /// \returns true if anything was found. bool lookupQualified(ArrayRef types, DeclNameRef member, - NLOptions options, + SourceLoc loc, NLOptions options, SmallVectorImpl &decls) const; /// Perform qualified lookup for the given member in the given module. bool lookupQualified(ModuleDecl *module, DeclNameRef member, - NLOptions options, + SourceLoc loc, NLOptions options, SmallVectorImpl &decls) const; /// Look up all Objective-C methods with the given selector visible diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 97e2fb51b35a8..dee6d8918c7b3 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -7188,6 +7188,10 @@ ERROR(macro_accessor_missing_from_expansion,none, ERROR(macro_init_accessor_not_documented,none, "expansion of macro %0 produced an unexpected 'init' accessor", (DeclName)) +ERROR(global_arbitrary_name,none, + "'%0' macros are not allowed to introduce arbitrary names " + "at global scope", + (StringRef)) ERROR(macro_resolve_circular_reference, none, "circular reference resolving %select{freestanding|attached}0 macro %1", diff --git a/include/swift/AST/Evaluator.h b/include/swift/AST/Evaluator.h index 7e42e727eb61f..2ff80cd6419d5 100644 --- a/include/swift/AST/Evaluator.h +++ b/include/swift/AST/Evaluator.h @@ -208,18 +208,6 @@ class Evaluator { /// is treated as a stack and is used to detect cycles. llvm::SetVector activeRequests; - /// How many `ResolveMacroRequest` requests are active. - /// - /// This allows us to quickly determine whether there is any - /// `ResolveMacroRequest` active in the active request stack. - /// It saves us from a linear scan through `activeRequests` when - /// we need to determine this information. - /// - /// Why on earth would we need to determine this information? - /// Please see the extended comment that goes with the constructor - /// of `UnqualifiedLookupRequest`. - unsigned numActiveResolveMacroRequests = 0; - /// A cache that stores the results of requests. evaluator::RequestCache cache; @@ -342,16 +330,6 @@ class Evaluator { return activeRequests.count(ActiveRequest(request)); } - /// Determine whether there is any active "resolve macro" request - /// on the request stack. - /// - /// Why on earth would we need to determine this information? - /// Please see the extended comment that goes with the constructor - /// of `UnqualifiedLookupRequest`. - bool hasActiveResolveMacroRequest() const { - return numActiveResolveMacroRequests > 0; - } - private: /// Diagnose a cycle detected in the evaluation of the given /// request. diff --git a/include/swift/AST/ModuleNameLookup.h b/include/swift/AST/ModuleNameLookup.h index bb09a801f3d66..18283f44dd518 100644 --- a/include/swift/AST/ModuleNameLookup.h +++ b/include/swift/AST/ModuleNameLookup.h @@ -62,7 +62,7 @@ void lookupInModule(const DeclContext *moduleOrFile, DeclName name, SmallVectorImpl &decls, NLKind lookupKind, ResolutionKind resolutionKind, const DeclContext *moduleScopeContext, - NLOptions options); + SourceLoc loc, NLOptions options); /// Performs a qualified lookup into the given module and, if necessary, its /// reexports, observing proper shadowing rules. diff --git a/include/swift/AST/NameLookup.h b/include/swift/AST/NameLookup.h index a4b8a0a3c14f4..5d3898d43283e 100644 --- a/include/swift/AST/NameLookup.h +++ b/include/swift/AST/NameLookup.h @@ -513,7 +513,7 @@ void lookupVisibleDecls(VisibleDeclConsumer &Consumer, /// /// \param CurrDC the DeclContext from which the lookup is done. void lookupVisibleMemberDecls(VisibleDeclConsumer &Consumer, - Type BaseTy, + Type BaseTy, SourceLoc loc, const DeclContext *CurrDC, bool includeInstanceMembers, bool includeDerivedRequirements, @@ -545,6 +545,15 @@ template void filterForDiscriminator(SmallVectorImpl &results, DebuggerClient *debugClient); +/// \returns The set of macro declarations with the given name that +/// fulfill any of the given macro roles. +SmallVector +lookupMacros(DeclContext *dc, DeclNameRef macroName, MacroRoles roles); + +/// \returns Whether the given source location is inside an attached +/// or freestanding macro argument. +bool isInMacroArgument(SourceFile *sourceFile, SourceLoc loc); + /// Call the given function body with each macro declaration and its associated /// role attribute for the given role. /// @@ -816,6 +825,22 @@ class ASTScope : public ASTAllocated { static std::pair lookupFallthroughSourceAndDest(SourceFile *sourceFile, SourceLoc loc); + using PotentialMacro = + llvm::PointerUnion; + + /// Look up the scope tree for the nearest enclosing macro scope at + /// the given source location. + /// + /// \param sourceFile The source file containing the given location. + /// \param loc The source location to start lookup from. + /// \param consume A function that is called when a potential macro + /// scope is found. If \c consume returns \c true, lookup + /// will stop. If \c consume returns \c false, lookup will + /// continue up the scope tree. + static void lookupEnclosingMacroScope( + SourceFile *sourceFile, SourceLoc loc, + llvm::function_ref consume); + SWIFT_DEBUG_DUMP; void print(llvm::raw_ostream &) const; void dumpOneScopeMapLocation(std::pair); diff --git a/include/swift/AST/NameLookupRequests.h b/include/swift/AST/NameLookupRequests.h index 39fe9d7dc2a3b..7aa1c47ee83a5 100644 --- a/include/swift/AST/NameLookupRequests.h +++ b/include/swift/AST/NameLookupRequests.h @@ -461,7 +461,7 @@ class LookupInModuleRequest LookupInModuleRequest( const DeclContext *, DeclName, NLKind, namelookup::ResolutionKind, const DeclContext *, - NLOptions); + SourceLoc, NLOptions); private: friend SimpleRequest; @@ -511,7 +511,7 @@ class ModuleQualifiedLookupRequest public: ModuleQualifiedLookupRequest(const DeclContext *, ModuleDecl *, DeclNameRef, - NLOptions); + SourceLoc, NLOptions); private: friend SimpleRequest; @@ -537,7 +537,7 @@ class QualifiedLookupRequest public: QualifiedLookupRequest(const DeclContext *, SmallVector, - DeclNameRef, NLOptions); + DeclNameRef, SourceLoc, NLOptions); private: friend SimpleRequest; @@ -588,7 +588,7 @@ class DirectLookupRequest TinyPtrVector(DirectLookupDescriptor), RequestFlags::Uncached|RequestFlags::DependencySink> { public: - DirectLookupRequest(DirectLookupDescriptor); + DirectLookupRequest(DirectLookupDescriptor, SourceLoc); private: friend SimpleRequest; diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 8574c38fa42f1..0dd81a6b654cf 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -3249,6 +3249,9 @@ class UnresolvedMacroReference { public: UnresolvedMacroReference(FreestandingMacroExpansion *exp) : pointer(exp) {} UnresolvedMacroReference(CustomAttr *attr) : pointer(attr) {} + UnresolvedMacroReference( + llvm::PointerUnion pointer) + : pointer(pointer) {} FreestandingMacroExpansion *getFreestanding() const { return pointer.dyn_cast(); diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 6d6bb23a2712c..e003098aa03ab 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -2910,7 +2910,8 @@ class ConstraintSystem { /// and no new names are introduced after that point. /// /// \returns A reference to the member-lookup result. - LookupResult &lookupMember(Type base, DeclNameRef name); + LookupResult &lookupMember(Type base, DeclNameRef name, + SourceLoc loc); /// Retrieve the set of "alternative" literal types that we'll explore /// for a given literal protocol kind. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 00bd291f3a025..93c8f0f0959e4 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1072,8 +1072,8 @@ DECLTYPE *ASTContext::get##NAME##Decl() const { \ /* Note: lookupQualified() will search both the Swift overlay \ * and the Clang module it imports. */ \ SmallVector decls; \ - M->lookupQualified(M, DeclNameRef(getIdentifier(#NAME)), NL_OnlyTypes, \ - decls); \ + M->lookupQualified(M, DeclNameRef(getIdentifier(#NAME)), SourceLoc(), \ + NL_OnlyTypes, decls); \ if (decls.size() == 1 && isa(decls[0])) { \ auto decl = cast(decls[0]); \ if (isa(decl) \ @@ -1336,7 +1336,8 @@ ConcreteDeclRef ASTContext::getRegexInitDecl(Type regexType) const { {Id_regexString, Id_version}); SmallVector results; spModule->lookupQualified(getRegexType(), DeclNameRef(name), - NL_IncludeUsableFromInline, results); + SourceLoc(), NL_IncludeUsableFromInline, + results); assert(results.size() == 1); auto *foundDecl = cast(results[0]); auto subs = regexType->getMemberSubstitutionMap(spModule, foundDecl); diff --git a/lib/AST/ASTScope.cpp b/lib/AST/ASTScope.cpp index c4eb1d1370f5f..aa80e71159bf9 100644 --- a/lib/AST/ASTScope.cpp +++ b/lib/AST/ASTScope.cpp @@ -60,6 +60,12 @@ std::pair ASTScope::lookupFallthroughSourceAndDest( return ASTScopeImpl::lookupFallthroughSourceAndDest(sourceFile, loc); } +void ASTScope::lookupEnclosingMacroScope( + SourceFile *sourceFile, SourceLoc loc, + llvm::function_ref body) { + return ASTScopeImpl::lookupEnclosingMacroScope(sourceFile, loc, body); +} + #if SWIFT_COMPILER_IS_MSVC #pragma warning(push) #pragma warning(disable : 4996) @@ -138,7 +144,7 @@ DEFINE_GET_CLASS_NAME(AbstractFunctionDeclScope) DEFINE_GET_CLASS_NAME(ParameterListScope) DEFINE_GET_CLASS_NAME(FunctionBodyScope) DEFINE_GET_CLASS_NAME(DefaultArgumentInitializerScope) -DEFINE_GET_CLASS_NAME(AttachedPropertyWrapperScope) +DEFINE_GET_CLASS_NAME(CustomAttributeScope) DEFINE_GET_CLASS_NAME(PatternEntryDeclScope) DEFINE_GET_CLASS_NAME(PatternEntryInitializerScope) DEFINE_GET_CLASS_NAME(ConditionalClausePatternUseScope) diff --git a/lib/AST/ASTScopeCreation.cpp b/lib/AST/ASTScopeCreation.cpp index 66821d17e6c49..f2bcdedd65f1b 100644 --- a/lib/AST/ASTScopeCreation.cpp +++ b/lib/AST/ASTScopeCreation.cpp @@ -180,7 +180,7 @@ class ScopeCreator final : public ASTAllocated { addChildrenForParsedAccessors(AbstractStorageDecl *asd, ASTScopeImpl *parent); - void addChildrenForKnownAttributes(ValueDecl *decl, + void addChildrenForKnownAttributes(Decl *decl, ASTScopeImpl *parent); /// Add PatternEntryDeclScopes for each pattern binding entry. @@ -569,7 +569,7 @@ void ScopeCreator::addChildrenForParsedAccessors( }); } -void ScopeCreator::addChildrenForKnownAttributes(ValueDecl *decl, +void ScopeCreator::addChildrenForKnownAttributes(Decl *decl, ASTScopeImpl *parent) { SmallVector relevantAttrs; @@ -601,10 +601,8 @@ void ScopeCreator::addChildrenForKnownAttributes(ValueDecl *decl, parent, specAttr, afd); } } else if (auto *customAttr = dyn_cast(attr)) { - if (auto *vd = dyn_cast(decl)) { - constructExpandAndInsert( - parent, customAttr, vd); - } + constructExpandAndInsert( + parent, customAttr, decl); } } } @@ -716,7 +714,7 @@ CREATES_NEW_INSERTION_POINT(ConditionalClausePatternUseScope) NO_NEW_INSERTION_POINT(FunctionBodyScope) NO_NEW_INSERTION_POINT(AbstractFunctionDeclScope) -NO_NEW_INSERTION_POINT(AttachedPropertyWrapperScope) +NO_NEW_INSERTION_POINT(CustomAttributeScope) NO_NEW_INSERTION_POINT(EnumElementScope) NO_NEW_INSERTION_POINT(GuardStmtBodyScope) NO_NEW_INSERTION_POINT(ParameterListScope) @@ -1177,7 +1175,7 @@ void DefaultArgumentInitializerScope:: scopeCreator.addToScopeTree(initExpr, this); } -void AttachedPropertyWrapperScope:: +void CustomAttributeScope:: expandAScopeThatDoesNotCreateANewInsertionPoint( ScopeCreator &scopeCreator) { if (auto *args = attr->getArgs()) { @@ -1192,7 +1190,9 @@ ASTScopeImpl *GenericTypeOrExtensionWholePortion::expandScope( GenericTypeOrExtensionScope *scope, ScopeCreator &scopeCreator) const { // Get now in case recursion emancipates scope auto *const ip = scope->getParent().get(); - + + scopeCreator.addChildrenForKnownAttributes(scope->getDecl(), scope); + auto *context = scope->getGenericContext(); auto *genericParams = (isa(context) ? context->getParsedGenericParams() diff --git a/lib/AST/ASTScopeLookup.cpp b/lib/AST/ASTScopeLookup.cpp index 676e6e9dbdd77..a8168ca096605 100644 --- a/lib/AST/ASTScopeLookup.cpp +++ b/lib/AST/ASTScopeLookup.cpp @@ -675,3 +675,36 @@ std::pair ASTScopeImpl::lookupFallthroughSourceAndDest( return { nullptr, nullptr }; } + +void ASTScopeImpl::lookupEnclosingMacroScope( + SourceFile *sourceFile, SourceLoc loc, + llvm::function_ref consume) { + if (!sourceFile || sourceFile->Kind == SourceFileKind::Interface) + return; + + if (loc.isInvalid()) + return; + + auto *fileScope = sourceFile->getScope().impl; + auto *scope = fileScope->findInnermostEnclosingScope(loc, nullptr); + do { + auto *freestanding = scope->getFreestandingMacro().getPtrOrNull(); + if (freestanding && consume(freestanding)) + return; + + auto *attr = scope->getDeclAttributeIfAny().getPtrOrNull(); + auto *potentialAttached = dyn_cast_or_null(attr); + if (potentialAttached && consume(potentialAttached)) + return; + + // If we've reached a source file scope, we can't be inside of + // a macro argument. Either this is a top-level source file, or + // it's macro expansion buffer. We have to check for this because + // macro expansion buffers for freestanding macros are children of + // MacroExpansionDeclScope, and child scopes of freestanding macros + // are otherwise inside the macro argument. + if (scope->getClassName() == "ASTSourceFileScope") + return; + + } while ((scope = scope->getParent().getPtrOrNull())); +} diff --git a/lib/AST/ASTScopeSourceRange.cpp b/lib/AST/ASTScopeSourceRange.cpp index 0073be55f8e89..1ce85b9319b55 100644 --- a/lib/AST/ASTScopeSourceRange.cpp +++ b/lib/AST/ASTScopeSourceRange.cpp @@ -360,7 +360,7 @@ SourceRange ClosureParametersScope::getSourceRangeOfThisASTNode( return explicitClosureExpr->getSourceRange(); } -SourceRange AttachedPropertyWrapperScope::getSourceRangeOfThisASTNode( +SourceRange CustomAttributeScope::getSourceRangeOfThisASTNode( const bool omitAssertions) const { return attr->getRange(); } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 14d6a9c2849fe..eb62453ce060b 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -5395,7 +5395,7 @@ NominalTypeDecl::getExecutorOwnedEnqueueFunction() const { llvm::SmallVector results; lookupQualified(getSelfNominalTypeDecl(), DeclNameRef(C.Id_enqueue), - NL_ProtocolMembers, + getLoc(), NL_ProtocolMembers, results); for (auto candidate: results) { @@ -5434,7 +5434,7 @@ NominalTypeDecl::getExecutorLegacyOwnedEnqueueFunction() const { llvm::SmallVector results; lookupQualified(getSelfNominalTypeDecl(), DeclNameRef(C.Id_enqueue), - NL_ProtocolMembers, + getLoc(), NL_ProtocolMembers, results); for (auto candidate: results) { @@ -5473,7 +5473,7 @@ NominalTypeDecl::getExecutorLegacyUnownedEnqueueFunction() const { llvm::SmallVector results; lookupQualified(getSelfNominalTypeDecl(), DeclNameRef(C.Id_enqueue), - NL_ProtocolMembers, + getLoc(), NL_ProtocolMembers, results); for (auto candidate: results) { @@ -9927,7 +9927,7 @@ const VarDecl *ClassDecl::getUnownedExecutorProperty() const { llvm::SmallVector results; this->lookupQualified(getSelfNominalTypeDecl(), DeclNameRef(C.Id_unownedExecutor), - NL_ProtocolMembers, + getLoc(), NL_ProtocolMembers, results); for (auto candidate: results) { diff --git a/lib/AST/DocComment.cpp b/lib/AST/DocComment.cpp index 96bf365ef8745..5c73b29a42959 100644 --- a/lib/AST/DocComment.cpp +++ b/lib/AST/DocComment.cpp @@ -435,7 +435,8 @@ class CommentProviderFinder final { SmallVector members; protocol->lookupQualified(const_cast(protocol), DeclNameRef(VD->getName()), - NLOptions::NL_ProtocolMembers, members); + VD->getLoc(), NLOptions::NL_ProtocolMembers, + members); Optional result; for (auto *member : members) { diff --git a/lib/AST/Evaluator.cpp b/lib/AST/Evaluator.cpp index 49c1fab72b53c..fdc1b5889b912 100644 --- a/lib/AST/Evaluator.cpp +++ b/lib/AST/Evaluator.cpp @@ -63,8 +63,6 @@ Evaluator::Evaluator(DiagnosticEngine &diags, const LangOptions &opts) bool Evaluator::checkDependency(const ActiveRequest &request) { // Record this as an active request. if (activeRequests.insert(request)) { - if (request.getAs()) - ++numActiveResolveMacroRequests; return false; } @@ -74,9 +72,6 @@ bool Evaluator::checkDependency(const ActiveRequest &request) { } void Evaluator::finishedRequest(const ActiveRequest &request) { - if (request.getAs()) - --numActiveResolveMacroRequests; - assert(activeRequests.back() == request); activeRequests.pop_back(); } diff --git a/lib/AST/ModuleNameLookup.cpp b/lib/AST/ModuleNameLookup.cpp index 10ea32c053c17..98ae1381690ce 100644 --- a/lib/AST/ModuleNameLookup.cpp +++ b/lib/AST/ModuleNameLookup.cpp @@ -281,10 +281,10 @@ void namelookup::lookupInModule(const DeclContext *moduleOrFile, NLKind lookupKind, ResolutionKind resolutionKind, const DeclContext *moduleScopeContext, - NLOptions options) { + SourceLoc loc, NLOptions options) { auto &ctx = moduleOrFile->getASTContext(); LookupInModuleRequest req(moduleOrFile, name, lookupKind, resolutionKind, - moduleScopeContext, options); + moduleScopeContext, loc, options); auto results = evaluateOrDefault(ctx.evaluator, req, {}); decls.append(results.begin(), results.end()); } diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index 77e029d8e3199..ca2162d7e504e 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -1594,6 +1594,60 @@ static DeclName adjustLazyMacroExpansionNameKey( return name; } +SmallVector +namelookup::lookupMacros(DeclContext *dc, DeclNameRef macroName, + MacroRoles roles) { + SmallVector choices; + auto moduleScopeDC = dc->getModuleScopeContext(); + ASTContext &ctx = moduleScopeDC->getASTContext(); + + // Macro lookup should always exclude macro expansions; macro + // expansions cannot introduce new macro declarations. Note that + // the source location here doesn't matter. + UnqualifiedLookupDescriptor descriptor{ + macroName, moduleScopeDC, SourceLoc(), + UnqualifiedLookupFlags::ExcludeMacroExpansions + }; + + auto lookup = evaluateOrDefault( + ctx.evaluator, UnqualifiedLookupRequest{descriptor}, {}); + for (const auto &found : lookup.allResults()) { + if (auto macro = dyn_cast(found.getValueDecl())) { + auto candidateRoles = macro->getMacroRoles(); + if ((candidateRoles && roles.contains(candidateRoles)) || + // FIXME: `externalMacro` should have all roles. + macro->getBaseIdentifier().str() == "externalMacro") { + choices.push_back(macro); + } + } + } + return choices; +} + +bool +namelookup::isInMacroArgument(SourceFile *sourceFile, SourceLoc loc) { + bool inMacroArgument = false; + + ASTScope::lookupEnclosingMacroScope( + sourceFile, loc, + [&](auto potentialMacro) -> bool { + UnresolvedMacroReference macro(potentialMacro); + + if (macro.getFreestanding()) { + inMacroArgument = true; + } else if (auto *attr = macro.getAttr()) { + auto *moduleScope = sourceFile->getModuleScopeContext(); + auto results = lookupMacros(moduleScope, macro.getMacroName(), + getAttachedMacroRoles()); + inMacroArgument = !results.empty(); + } + + return inMacroArgument; + }); + + return inMacroArgument; +} + /// Call the given function body with each macro declaration and its associated /// role attribute for the given role. /// @@ -1851,10 +1905,10 @@ maybeFilterOutUnwantedDecls(TinyPtrVector decls, } TinyPtrVector -NominalTypeDecl::lookupDirect(DeclName name, +NominalTypeDecl::lookupDirect(DeclName name, SourceLoc loc, OptionSet flags) { return evaluateOrDefault(getASTContext().evaluator, - DirectLookupRequest({this, name, flags}), {}); + DirectLookupRequest({this, name, flags}, loc), {}); } TinyPtrVector @@ -2195,6 +2249,7 @@ void namelookup::tryExtractDirectlyReferencedNominalTypes( bool DeclContext::lookupQualified(Type type, DeclNameRef member, + SourceLoc loc, NLOptions options, SmallVectorImpl &decls) const { using namespace namelookup; @@ -2209,14 +2264,16 @@ bool DeclContext::lookupQualified(Type type, // Handle lookup in a module. if (auto moduleTy = type->getAs()) - return lookupQualified(moduleTy->getModule(), member, options, decls); + return lookupQualified(moduleTy->getModule(), member, + loc, options, decls); // Figure out which nominal types we will look into. SmallVector nominalTypesToLookInto; namelookup::extractDirectlyReferencedNominalTypes(type, nominalTypesToLookInto); - return lookupQualified(nominalTypesToLookInto, member, options, decls); + return lookupQualified(nominalTypesToLookInto, member, + loc, options, decls); } static void installPropertyWrapperMembersIfNeeded(NominalTypeDecl *target, @@ -2251,11 +2308,11 @@ static void installPropertyWrapperMembersIfNeeded(NominalTypeDecl *target, bool DeclContext::lookupQualified(ArrayRef typeDecls, DeclNameRef member, - NLOptions options, + SourceLoc loc, NLOptions options, SmallVectorImpl &decls) const { assert(decls.empty() && "additive lookup not supported"); QualifiedLookupRequest req{this, {typeDecls.begin(), typeDecls.end()}, - member, options}; + member, loc, options}; decls = evaluateOrDefault(getASTContext().evaluator, req, {}); return !decls.empty(); } @@ -2309,7 +2366,11 @@ QualifiedLookupRequest::evaluate(Evaluator &eval, const DeclContext *DC, flags |= NominalTypeDecl::LookupDirectFlags::IncludeAttrImplements; if (options & NL_ExcludeMacroExpansions) flags |= NominalTypeDecl::LookupDirectFlags::ExcludeMacroExpansions; - for (auto decl : current->lookupDirect(member.getFullName(), flags)) { + + // Note that the source loc argument doesn't matter, because excluding + // macro expansions is already propagated through the lookup flags above. + for (auto decl : current->lookupDirect(member.getFullName(), + SourceLoc(), flags)) { // If we're performing a type lookup, don't even attempt to validate // the decl if its not a type. if ((options & NL_OnlyTypes) && !isa(decl)) @@ -2383,10 +2444,10 @@ QualifiedLookupRequest::evaluate(Evaluator &eval, const DeclContext *DC, } bool DeclContext::lookupQualified(ModuleDecl *module, DeclNameRef member, - NLOptions options, + SourceLoc loc, NLOptions options, SmallVectorImpl &decls) const { assert(decls.empty() && "additive lookup not supported"); - ModuleQualifiedLookupRequest req{this, module, member, options}; + ModuleQualifiedLookupRequest req{this, module, member, loc, options}; decls = evaluateOrDefault(getASTContext().evaluator, req, {}); return !decls.empty(); } @@ -2404,7 +2465,7 @@ ModuleQualifiedLookupRequest::evaluate(Evaluator &eval, const DeclContext *DC, auto topLevelScope = DC->getModuleScopeContext(); if (module == topLevelScope->getParentModule()) { lookupInModule(module, member.getFullName(), decls, NLKind::QualifiedLookup, - kind, topLevelScope, options); + kind, topLevelScope, SourceLoc(), options); } else { // Note: This is a lookup into another module. Unless we're compiling // multiple modules at once, or if the other module re-exports this one, @@ -2421,7 +2482,7 @@ ModuleQualifiedLookupRequest::evaluate(Evaluator &eval, const DeclContext *DC, })) { lookupInModule(module, member.getFullName(), decls, NLKind::QualifiedLookup, kind, topLevelScope, - options); + SourceLoc(), options); } } @@ -2613,6 +2674,20 @@ directReferencesForUnqualifiedTypeLookup(DeclNameRef name, SourceLoc loc, DeclContext *dc, LookupOuterResults lookupOuter, bool allowUsableFromInline=false) { + UnqualifiedLookupOptions options = + UnqualifiedLookupFlags::TypeLookup | + UnqualifiedLookupFlags::AllowProtocolMembers; + if (lookupOuter == LookupOuterResults::Included) + options |= UnqualifiedLookupFlags::IncludeOuterResults; + + if (allowUsableFromInline) + options |= UnqualifiedLookupFlags::IncludeUsableFromInline; + + // Manually exclude macro expansions here since the source location + // is overridden below. + if (namelookup::isInMacroArgument(dc->getParentSourceFile(), loc)) + options |= UnqualifiedLookupFlags::ExcludeMacroExpansions; + // In a protocol or protocol extension, the 'where' clause can refer to // associated types without 'Self' qualification: // @@ -2640,15 +2715,6 @@ directReferencesForUnqualifiedTypeLookup(DeclNameRef name, DirectlyReferencedTypeDecls results; - UnqualifiedLookupOptions options = - UnqualifiedLookupFlags::TypeLookup | - UnqualifiedLookupFlags::AllowProtocolMembers; - if (lookupOuter == LookupOuterResults::Included) - options |= UnqualifiedLookupFlags::IncludeOuterResults; - - if (allowUsableFromInline) - options |= UnqualifiedLookupFlags::IncludeUsableFromInline; - auto &ctx = dc->getASTContext(); auto descriptor = UnqualifiedLookupDescriptor(name, dc, loc, options); auto lookup = evaluateOrDefault(ctx.evaluator, @@ -2679,6 +2745,7 @@ directReferencesForQualifiedTypeLookup(Evaluator &evaluator, ArrayRef baseTypes, DeclNameRef name, DeclContext *dc, + SourceLoc loc, bool allowUsableFromInline=false) { DirectlyReferencedTypeDecls result; auto addResults = [&result](ArrayRef found){ @@ -2705,7 +2772,7 @@ directReferencesForQualifiedTypeLookup(Evaluator &evaluator, resolveTypeDeclsToNominal(ctx.evaluator, ctx, baseTypes, moduleDecls, anyObject); - dc->lookupQualified(nominalTypeDecls, name, options, members); + dc->lookupQualified(nominalTypeDecls, name, loc, options, members); // Search all of the modules. for (auto module : moduleDecls) { @@ -2713,7 +2780,7 @@ directReferencesForQualifiedTypeLookup(Evaluator &evaluator, innerOptions &= ~NL_RemoveOverridden; innerOptions &= ~NL_RemoveNonVisible; SmallVector moduleMembers; - dc->lookupQualified(module, name, innerOptions, moduleMembers); + dc->lookupQualified(module, name, loc, innerOptions, moduleMembers); members.append(moduleMembers.begin(), moduleMembers.end()); } @@ -2765,6 +2832,7 @@ directReferencesForDeclRefTypeRepr(Evaluator &evaluator, ASTContext &ctx, current = directReferencesForQualifiedTypeLookup(evaluator, ctx, current, component->getNameRef(), dc, + component->getLoc(), allowUsableFromInline); if (current.empty()) return current; @@ -3552,7 +3620,8 @@ bool IsCallAsFunctionNominalRequest::evaluate(Evaluator &evaluator, // member access. SmallVector results; auto opts = NL_QualifiedDefault | NL_ProtocolMembers | NL_IgnoreAccessControl; - dc->lookupQualified(decl, DeclNameRef(ctx.Id_callAsFunction), opts, results); + dc->lookupQualified(decl, DeclNameRef(ctx.Id_callAsFunction), + decl->getLoc(), opts, results); return llvm::any_of(results, [](ValueDecl *decl) -> bool { if (auto *fd = dyn_cast(decl)) diff --git a/lib/AST/NameLookupRequests.cpp b/lib/AST/NameLookupRequests.cpp index 617db015e9040..33b8d86e4a6f2 100644 --- a/lib/AST/NameLookupRequests.cpp +++ b/lib/AST/NameLookupRequests.cpp @@ -519,24 +519,14 @@ swift::extractNearestSourceLoc(CustomRefCountingOperationDescriptor desc) { // macros, because doing so trivially creates a cyclic dependency amongst the // macro expansions that will be detected by the request-evaluator. // -// Our lookup requests don't always have enough information to answer the -// question "is this part of an argument to a macro?", so we do a much simpler, -// more efficient, and not-entirely-sound hack based on the request-evaluator. -// Specifically, if we are in the process of resolving a macro (which is -// determined by checking for the presence of a `ResolveMacroRequest` in the -// request-evaluator stack), then we adjust the options used for the name -// lookup request we are forming to exclude macro expansions. The evaluation -// of that request will then avoid expanding any macros, and not produce any -// results that involve entries in already-expanded macros. By adjusting the -// request itself, we still distinguish between requests that can and cannot -// look into macro expansions, so it doesn't break caching for those immediate -// requests. -// -// Over time, we should seek to replace this heuristic with a location-based -// check, where we use ASTScope to determine whether we are inside a macro -// argument. This existing check might still be useful because it's going to -// be faster than a location-based query, but the location-based query can be -// fully correct. +// We use source locations to answer the question "is this part of an argument +// to a macro?" through `namelookup::isInMacroArgument`. If the answer is yes, +// then we adjust the options used for the name lookup request we are forming +// to exclude macro expansions. The evaluation of that request will then avoid +// expanding any macros, and not produce any results that involve entries in +// already-expanded macros. By adjusting the request itself, we still +// distinguish between requests that can and cannot look into macro expansions, +// so it doesn't break caching for those immediate requests. /// Exclude macros in the unqualified lookup descriptor if we need to. static UnqualifiedLookupDescriptor excludeMacrosIfNeeded( @@ -545,8 +535,10 @@ static UnqualifiedLookupDescriptor excludeMacrosIfNeeded( UnqualifiedLookupFlags::ExcludeMacroExpansions)) return descriptor; - auto &evaluator = descriptor.DC->getASTContext().evaluator; - if (!evaluator.hasActiveResolveMacroRequest()) + auto isInMacroArgument = namelookup::isInMacroArgument( + descriptor.DC->getParentSourceFile(), descriptor.Loc); + + if (!isInMacroArgument) return descriptor; descriptor.Options |= UnqualifiedLookupFlags::ExcludeMacroExpansions; @@ -555,13 +547,15 @@ static UnqualifiedLookupDescriptor excludeMacrosIfNeeded( /// Exclude macros in the direct lookup descriptor if we need to. static DirectLookupDescriptor excludeMacrosIfNeeded( - DirectLookupDescriptor descriptor) { + DirectLookupDescriptor descriptor, SourceLoc loc) { if (descriptor.Options.contains( NominalTypeDecl::LookupDirectFlags::ExcludeMacroExpansions)) return descriptor; - auto &evaluator = descriptor.DC->getASTContext().evaluator; - if (!evaluator.hasActiveResolveMacroRequest()) + auto isInMacroArgument = namelookup::isInMacroArgument( + descriptor.DC->getParentSourceFile(), loc); + + if (!isInMacroArgument) return descriptor; descriptor.Options |= @@ -572,12 +566,15 @@ static DirectLookupDescriptor excludeMacrosIfNeeded( /// Exclude macros in the name lookup options if we need to. static NLOptions -excludeMacrosIfNeeded(const DeclContext *dc, NLOptions options) { +excludeMacrosIfNeeded(const DeclContext *dc, SourceLoc loc, + NLOptions options) { if (options & NL_ExcludeMacroExpansions) return options; - auto &evaluator = dc->getASTContext().evaluator; - if (!evaluator.hasActiveResolveMacroRequest()) + auto isInMacroArgument = namelookup::isInMacroArgument( + dc->getParentSourceFile(), loc); + + if (!isInMacroArgument) return options; return options | NL_ExcludeMacroExpansions; @@ -591,25 +588,27 @@ LookupInModuleRequest::LookupInModuleRequest( const DeclContext *moduleOrFile, DeclName name, NLKind lookupKind, namelookup::ResolutionKind resolutionKind, const DeclContext *moduleScopeContext, - NLOptions options + SourceLoc loc, NLOptions options ) : SimpleRequest(moduleOrFile, name, lookupKind, resolutionKind, moduleScopeContext, - excludeMacrosIfNeeded(moduleOrFile, options)) { } + excludeMacrosIfNeeded(moduleOrFile, loc, options)) { } ModuleQualifiedLookupRequest::ModuleQualifiedLookupRequest( const DeclContext *dc, ModuleDecl *module, DeclNameRef name, - NLOptions options - ) : SimpleRequest(dc, module, name, excludeMacrosIfNeeded(dc, options)) { } + SourceLoc loc, NLOptions options + ) : SimpleRequest(dc, module, name, + excludeMacrosIfNeeded(dc, loc, options)) { } QualifiedLookupRequest::QualifiedLookupRequest( const DeclContext *dc, SmallVector decls, - DeclNameRef name, NLOptions options + DeclNameRef name, + SourceLoc loc, NLOptions options ) : SimpleRequest(dc, std::move(decls), name, - excludeMacrosIfNeeded(dc, options)) { } + excludeMacrosIfNeeded(dc, loc, options)) { } -DirectLookupRequest::DirectLookupRequest(DirectLookupDescriptor descriptor) - : SimpleRequest(excludeMacrosIfNeeded(descriptor)) { } +DirectLookupRequest::DirectLookupRequest(DirectLookupDescriptor descriptor, SourceLoc loc) + : SimpleRequest(excludeMacrosIfNeeded(descriptor, loc)) { } // Implement the clang importer type zone. #define SWIFT_TYPEID_ZONE ClangImporter diff --git a/lib/AST/RequirementMachine/NameLookup.cpp b/lib/AST/RequirementMachine/NameLookup.cpp index ddb218353a656..6a9e83421f37e 100644 --- a/lib/AST/RequirementMachine/NameLookup.cpp +++ b/lib/AST/RequirementMachine/NameLookup.cpp @@ -48,7 +48,7 @@ swift::rewriting::lookupConcreteNestedType( SmallVectorImpl &concreteDecls) { SmallVector foundMembers; decl->getParentModule()->lookupQualified( - decl, DeclNameRef(name), + decl, DeclNameRef(name), decl->getLoc(), NL_QualifiedDefault | NL_OnlyTypes | NL_ProtocolMembers, foundMembers); for (auto member : foundMembers) diff --git a/lib/AST/UnqualifiedLookup.cpp b/lib/AST/UnqualifiedLookup.cpp index b48b4abcadc15..6651bbea3322a 100644 --- a/lib/AST/UnqualifiedLookup.cpp +++ b/lib/AST/UnqualifiedLookup.cpp @@ -333,7 +333,8 @@ void UnqualifiedLookupFactory::ResultFinderForTypeContext::findResults( return; SmallVector Lookup; - contextForLookup->lookupQualified(selfBounds, Name, baseNLOptions, Lookup); + contextForLookup->lookupQualified(selfBounds, Name, factory->Loc, + baseNLOptions, Lookup); for (auto Result : Lookup) { auto baseDC = const_cast(whereValueIsMember(Result)); auto baseDecl = getBaseDeclForResult(baseDC); @@ -531,7 +532,8 @@ void UnqualifiedLookupFactory::addImportedResults(const DeclContext *const dc) { if (options.contains(Flags::ExcludeMacroExpansions)) nlOptions |= NL_ExcludeMacroExpansions; lookupInModule(dc, Name.getFullName(), CurModuleResults, - NLKind::UnqualifiedLookup, resolutionKind, dc, nlOptions); + NLKind::UnqualifiedLookup, resolutionKind, dc, + Loc, nlOptions); // Always perform name shadowing for type lookup. if (options.contains(Flags::TypeLookup)) { diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index d7d3527a6c7a0..88d2a9a93dd3e 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -6532,7 +6532,7 @@ void SwiftDeclConverter::recordObjCOverride(AbstractFunctionDecl *decl) { // Dig out the Objective-C superclass. SmallVector results; superDecl->lookupQualified(superDecl, DeclNameRef(decl->getName()), - NL_QualifiedDefault, + decl->getLoc(), NL_QualifiedDefault, results); for (auto member : results) { if (member->getKind() != decl->getKind() || @@ -6605,7 +6605,7 @@ void SwiftDeclConverter::recordObjCOverride(SubscriptDecl *subscript) { SmallVector lookup; subscript->getModuleContext()->lookupQualified( superDecl, DeclNameRef(subscript->getName()), - NL_QualifiedDefault, lookup); + subscript->getLoc(), NL_QualifiedDefault, lookup); for (auto result : lookup) { auto parentSub = dyn_cast(result); @@ -8292,7 +8292,8 @@ static void finishTypeWitnesses( NL_OnlyTypes | NL_ProtocolMembers); - dc->lookupQualified(nominal, DeclNameRef(assocType->getName()), options, + dc->lookupQualified(nominal, DeclNameRef(assocType->getName()), + nominal->getLoc(), options, lookupResults); for (auto member : lookupResults) { auto typeDecl = cast(member); diff --git a/lib/Frontend/ModuleInterfaceSupport.cpp b/lib/Frontend/ModuleInterfaceSupport.cpp index ee08b89e508c3..3a01ee45af93c 100644 --- a/lib/Frontend/ModuleInterfaceSupport.cpp +++ b/lib/Frontend/ModuleInterfaceSupport.cpp @@ -181,7 +181,7 @@ diagnoseIfModuleImportsShadowingDecl(ModuleInterfaceOptions const &Opts, SmallVector decls; lookupInModule(importedModule, importingModule->getName(), decls, NLKind::UnqualifiedLookup, ResolutionKind::TypesOnly, - importedModule, + importedModule, SourceLoc(), NL_UnqualifiedDefault | NL_IncludeUsableFromInline); for (auto decl : decls) diagnoseDeclShadowsModule(Opts, cast(decl), importingModule, diff --git a/lib/IDE/CompletionLookup.cpp b/lib/IDE/CompletionLookup.cpp index b697641afeba4..33f99cc19b0aa 100644 --- a/lib/IDE/CompletionLookup.cpp +++ b/lib/IDE/CompletionLookup.cpp @@ -2262,7 +2262,7 @@ bool CompletionLookup::tryUnwrappedCompletions(Type ExprType, bool isIUO) { // unforced IUO. if (isIUO) { if (Type Unwrapped = ExprType->getOptionalObjectType()) { - lookupVisibleMemberDecls(*this, Unwrapped, CurrDeclContext, + lookupVisibleMemberDecls(*this, Unwrapped, DotLoc, CurrDeclContext, IncludeInstanceMembers, /*includeDerivedRequirements*/ false, /*includeProtocolExtensionMembers*/ true); @@ -2289,7 +2289,8 @@ bool CompletionLookup::tryUnwrappedCompletions(Type ExprType, bool isIUO) { if (NumBytesToEraseForOptionalUnwrap <= CodeCompletionResult::MaxNumBytesToErase) { if (!tryTupleExprCompletions(Unwrapped)) { - lookupVisibleMemberDecls(*this, Unwrapped, CurrDeclContext, + lookupVisibleMemberDecls(*this, Unwrapped, DotLoc, + CurrDeclContext, IncludeInstanceMembers, /*includeDerivedRequirements*/ false, /*includeProtocolExtensionMembers*/ true); @@ -2370,7 +2371,7 @@ void CompletionLookup::getValueExprCompletions(Type ExprType, ValueDecl *VD) { // Don't check/return so we still add the members of Optional itself below tryUnwrappedCompletions(ExprType, isIUO); - lookupVisibleMemberDecls(*this, ExprType, CurrDeclContext, + lookupVisibleMemberDecls(*this, ExprType, DotLoc, CurrDeclContext, IncludeInstanceMembers, /*includeDerivedRequirements*/ false, /*includeProtocolExtensionMembers*/ true); @@ -2833,7 +2834,7 @@ void CompletionLookup::getUnresolvedMemberCompletions(Type T) { llvm::SaveAndRestore SaveLook(Kind, LookupKind::ValueExpr); llvm::SaveAndRestore SaveType(ExprType, baseType); llvm::SaveAndRestore SaveUnresolved(IsUnresolvedMember, true); - lookupVisibleMemberDecls(consumer, baseType, CurrDeclContext, + lookupVisibleMemberDecls(consumer, baseType, DotLoc, CurrDeclContext, /*includeInstanceMembers=*/false, /*includeDerivedRequirements*/ false, /*includeProtocolExtensionMembers*/ true); @@ -2847,7 +2848,7 @@ void CompletionLookup::getEnumElementPatternCompletions(Type T) { llvm::SaveAndRestore SaveLook(Kind, LookupKind::EnumElement); llvm::SaveAndRestore SaveType(ExprType, baseType); llvm::SaveAndRestore SaveUnresolved(IsUnresolvedMember, true); - lookupVisibleMemberDecls(*this, baseType, CurrDeclContext, + lookupVisibleMemberDecls(*this, baseType, DotLoc, CurrDeclContext, /*includeInstanceMembers=*/false, /*includeDerivedRequirements=*/false, /*includeProtocolExtensionMembers=*/true); @@ -2915,8 +2916,8 @@ void CompletionLookup::getTypeCompletions(Type BaseType) { Kind = LookupKind::Type; this->BaseType = BaseType; NeedLeadingDot = !HaveDot; - lookupVisibleMemberDecls(*this, MetatypeType::get(BaseType), CurrDeclContext, - IncludeInstanceMembers, + lookupVisibleMemberDecls(*this, MetatypeType::get(BaseType), DotLoc, + CurrDeclContext, IncludeInstanceMembers, /*includeDerivedRequirements*/ false, /*includeProtocolExtensionMembers*/ false); if (BaseType->isAnyExistentialType()) { @@ -2951,8 +2952,8 @@ void CompletionLookup::getGenericRequirementCompletions( Kind = LookupKind::GenericRequirement; this->BaseType = selfTy; NeedLeadingDot = false; - lookupVisibleMemberDecls(*this, MetatypeType::get(selfTy), CurrDeclContext, - IncludeInstanceMembers, + lookupVisibleMemberDecls(*this, MetatypeType::get(selfTy), DotLoc, + CurrDeclContext, IncludeInstanceMembers, /*includeDerivedRequirements*/ false, /*includeProtocolExtensionMembers*/ true); // We not only allow referencing nested types/typealiases directly, but also diff --git a/lib/IDE/CompletionOverrideLookup.cpp b/lib/IDE/CompletionOverrideLookup.cpp index 53320471bfbe7..8a97365271c7e 100644 --- a/lib/IDE/CompletionOverrideLookup.cpp +++ b/lib/IDE/CompletionOverrideLookup.cpp @@ -541,7 +541,7 @@ void CompletionOverrideLookup::getOverrideCompletions(SourceLoc Loc) { if (CurrTy && !CurrTy->is()) { // Look for overridable static members too. Type Meta = MetatypeType::get(CurrTy); - lookupVisibleMemberDecls(*this, Meta, CurrDeclContext, + lookupVisibleMemberDecls(*this, Meta, introducerLoc, CurrDeclContext, /*includeInstanceMembers=*/true, /*includeDerivedRequirements*/ true, /*includeProtocolExtensionMembers*/ false); diff --git a/lib/IDE/ConformingMethodList.cpp b/lib/IDE/ConformingMethodList.cpp index ed5fde99cead9..ef1d355695116 100644 --- a/lib/IDE/ConformingMethodList.cpp +++ b/lib/IDE/ConformingMethodList.cpp @@ -166,7 +166,8 @@ void ConformingMethodListCallbacks::getMatchingMethods( } LocalConsumer(CurDeclContext, T, expectedTypes, result); - lookupVisibleMemberDecls(LocalConsumer, MetatypeType::get(T), CurDeclContext, + lookupVisibleMemberDecls(LocalConsumer, MetatypeType::get(T), + Loc, CurDeclContext, /*includeInstanceMembers=*/false, /*includeDerivedRequirements*/false, /*includeProtocolExtensionMembers*/true); diff --git a/lib/IDE/ExprContextAnalysis.cpp b/lib/IDE/ExprContextAnalysis.cpp index 2aac61940a841..565be3e8d24c4 100644 --- a/lib/IDE/ExprContextAnalysis.cpp +++ b/lib/IDE/ExprContextAnalysis.cpp @@ -372,7 +372,7 @@ class ExprParentFinder : public ASTWalker { /// Collect function (or subscript) members with the given \p name on \p baseTy. static void collectPossibleCalleesByQualifiedLookup( - DeclContext &DC, Type baseTy, DeclNameRef name, + DeclContext &DC, Type baseTy, DeclNameRef name, SourceLoc loc, SmallVectorImpl &candidates) { auto baseInstanceTy = baseTy->getMetatypeInstanceType(); if (!baseInstanceTy->mayHaveMembers()) @@ -395,7 +395,7 @@ static void collectPossibleCalleesByQualifiedLookup( SmallVector decls; if (!DC.lookupQualified(baseInstanceTy, - name.withoutArgumentLabels(), + name.withoutArgumentLabels(), loc, NL_QualifiedDefault | NL_ProtocolMembers, decls)) return; @@ -522,7 +522,9 @@ static void collectPossibleCalleesByQualifiedLookup( } } - collectPossibleCalleesByQualifiedLookup(DC, baseTy, name, candidates); + collectPossibleCalleesByQualifiedLookup(DC, baseTy, name, + baseExpr->getLoc(), + candidates); // Add virtual 'subscript(keyPath: KeyPath) -> Value'. if (name.getBaseName() == DeclBaseName::createSubscript() && @@ -553,6 +555,7 @@ static bool collectPossibleCalleesForUnresolvedMember( return; collectPossibleCalleesByQualifiedLookup(DC, MetatypeType::get(expectedTy), unresolvedMemberExpr->getName(), + unresolvedMemberExpr->getLoc(), candidates); }; diff --git a/lib/IDE/TypeContextInfo.cpp b/lib/IDE/TypeContextInfo.cpp index ffb398ae39b8f..abbc8a88a7bcf 100644 --- a/lib/IDE/TypeContextInfo.cpp +++ b/lib/IDE/TypeContextInfo.cpp @@ -194,7 +194,8 @@ void ContextInfoCallbacks::getImplicitMembers( } LocalConsumer(CurDeclContext, T, Result); - lookupVisibleMemberDecls(LocalConsumer, MetatypeType::get(T), CurDeclContext, + lookupVisibleMemberDecls(LocalConsumer, MetatypeType::get(T), + Loc, CurDeclContext, /*includeInstanceMembers=*/false, /*includeDerivedRequirements*/false, /*includeProtocolExtensionMembers*/true); diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 0e163d85d8dd8..7c62326b4a4f4 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -154,6 +154,9 @@ void Parser::performIDEInspectionSecondPassImpl( // discriminators. Context.evaluator.clearCachedOutput(LocalDiscriminatorsRequest{DC}); + // Clear any ASTScopes that were expanded. + SF.clearScope(); + switch (info.Kind) { case IDEInspectionDelayedDeclKind::TopLevelCodeDecl: { // Re-enter the top-level code decl context. diff --git a/lib/SIL/IR/SILFunctionType.cpp b/lib/SIL/IR/SILFunctionType.cpp index 4afc45feb516f..cfe743ad3c3ec 100644 --- a/lib/SIL/IR/SILFunctionType.cpp +++ b/lib/SIL/IR/SILFunctionType.cpp @@ -1058,7 +1058,7 @@ static CanType getKnownType(Optional &cacheSlot, ASTContext &C, // themselves. SmallVector decls; mod->lookupQualified(mod, DeclNameRef(C.getIdentifier(typeName)), - NL_QualifiedDefault, decls); + SourceLoc(), NL_QualifiedDefault, decls); if (decls.size() != 1) return CanType(); diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index 996d654321465..c70a797ceadc9 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -371,7 +371,7 @@ static FuncDecl *lookupIntrinsic(ModuleDecl &module, return *cache; SmallVector decls; - module.lookupQualified(&module, DeclNameRef(name), + module.lookupQualified(&module, DeclNameRef(name), SourceLoc(), NL_QualifiedDefault | NL_IncludeUsableFromInline, decls); if (decls.size() != 1) { diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp index 6c04a9f890a5e..90d3014bd6109 100644 --- a/lib/SILGen/SILGenFunction.cpp +++ b/lib/SILGen/SILGenFunction.cpp @@ -1092,7 +1092,7 @@ void SILGenFunction::emitArtificialTopLevel(Decl *mainDecl) { SmallVector results; UIKit->lookupQualified(UIKit, DeclNameRef(ctx.getIdentifier("UIApplicationMain")), - NL_QualifiedDefault, + SourceLoc(), NL_QualifiedDefault, results); // As the comment above alludes, using a qualified lookup into UIKit is diff --git a/lib/Sema/BuilderTransform.cpp b/lib/Sema/BuilderTransform.cpp index b6ae98679227c..78a9739cd694e 100644 --- a/lib/Sema/BuilderTransform.cpp +++ b/lib/Sema/BuilderTransform.cpp @@ -1379,6 +1379,7 @@ ResultBuilderOpSupport TypeChecker::checkBuilderOpSupport( SmallVector foundDecls; dc->lookupQualified( builderType, DeclNameRef(fnName), + builderType->getAnyNominal()->getLoc(), NL_QualifiedDefault | NL_ProtocolMembers, foundDecls); for (auto decl : foundDecls) { if (auto func = dyn_cast(decl)) { diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index c2ed909db3352..196217cb62aac 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -2104,7 +2104,8 @@ bool AssignmentFailure::diagnoseAsError() { if (auto typeContext = DC->getInnermostTypeContext()) { SmallVector results; DC->lookupQualified(typeContext->getSelfNominalTypeDecl(), - VD->createNameRef(), NL_QualifiedDefault, results); + VD->createNameRef(), Loc, + NL_QualifiedDefault, results); auto foundProperty = llvm::find_if(results, [&](ValueDecl *decl) { // We're looking for a settable property that is the same type as the diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index c30c94dbc2792..1c71bf20a74de 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -1244,7 +1244,7 @@ namespace { auto macroIdent = ctx.getIdentifier(kind); auto macros = lookupMacros( - macroIdent, expr->getLoc(), FunctionRefKind::Unapplied, + macroIdent, FunctionRefKind::Unapplied, MacroRole::Expression); if (!macros.empty()) { // Introduce an overload set for the macro reference. @@ -3896,12 +3896,12 @@ namespace { /// Lookup all macros with the given macro name. SmallVector - lookupMacros(Identifier macroName, SourceLoc loc, + lookupMacros(Identifier macroName, FunctionRefKind functionRefKind, MacroRoles roles) { SmallVector choices; - auto results = TypeChecker::lookupMacros( - CurDC, DeclNameRef(macroName), loc, roles); + auto results = namelookup::lookupMacros( + CurDC, DeclNameRef(macroName), roles); for (const auto &result : results) { OverloadChoice choice = OverloadChoice(Type(), result, functionRefKind); choices.push_back(choice); @@ -3926,8 +3926,7 @@ namespace { auto macroIdent = expr->getMacroName().getBaseIdentifier(); FunctionRefKind functionRefKind = FunctionRefKind::SingleApply; auto macros = lookupMacros( - macroIdent, expr->getMacroNameLoc().getBaseNameLoc(), - functionRefKind, expr->getMacroRoles()); + macroIdent, functionRefKind, expr->getMacroRoles()); if (macros.empty()) { ctx.Diags.diagnose(expr->getMacroNameLoc(), diag::macro_undefined, macroIdent) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index da48e9cd8286a..77d02761259a9 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -9307,6 +9307,9 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, Type baseObjTy = baseTy->getRValueType(); Type instanceTy = baseObjTy; + auto memberNode = simplifyLocatorToAnchor(memberLocator); + auto memberLoc = memberNode ? memberNode.getStartLoc() : SourceLoc(); + if (auto baseObjMeta = baseObjTy->getAs()) { instanceTy = baseObjMeta->getInstanceType(); } @@ -9419,7 +9422,7 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, } // Look for members within the base. - LookupResult &lookup = lookupMember(instanceTy, lookupName); + LookupResult &lookup = lookupMember(instanceTy, lookupName, memberLoc); // If this is true, we're using type construction syntax (Foo()) rather // than an explicit call to `init` (Foo.init()). @@ -9819,7 +9822,8 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, memberName.getBaseName() == DeclBaseName::createConstructor() && !isImplicitInit) { auto &compatLookup = lookupMember(instanceTy, - DeclNameRef(ctx.getIdentifier("init"))); + DeclNameRef(ctx.getIdentifier("init")), + memberLoc); for (auto result : compatLookup) addChoice(getOverloadChoice(result.getValueDecl(), /*isBridged=*/false, @@ -9829,7 +9833,8 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, // If the instance type is a bridged to an Objective-C type, perform // a lookup into that Objective-C type. if (bridgedType) { - LookupResult &bridgedLookup = lookupMember(bridgedType, memberName); + LookupResult &bridgedLookup = lookupMember(bridgedType, memberName, + memberLoc); ModuleDecl *foundationModule = nullptr; for (auto result : bridgedLookup) { // Ignore results from the Objective-C "Foundation" @@ -9892,7 +9897,8 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, // prioritize them and mark any results found on wrapped type // as a fallback results. bool isFallback = !result.ViableCandidates.empty(); - LookupResult &optionalLookup = lookupMember(objectType, memberName); + LookupResult &optionalLookup = lookupMember(objectType, memberName, + memberLoc); for (auto result : optionalLookup) addChoice(getOverloadChoice(result.getValueDecl(), /*bridged*/ false, @@ -9960,7 +9966,8 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, lookupOptions |= NameLookupFlags::IgnoreAccessControl; auto lookup = - TypeChecker::lookupMember(DC, instanceTy, memberName, lookupOptions); + TypeChecker::lookupMember(DC, instanceTy, memberName, + memberLoc, lookupOptions); for (auto entry : lookup) { auto *cand = entry.getValueDecl(); diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index 26e6a088d0cea..30bf38a0771f4 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -1014,6 +1014,7 @@ static void collectNonOveriddenSuperclassInits( SmallVector lookupResults; subclass->lookupQualified( superclassDecl, DeclNameRef::createConstructor(), + subclass->getStartLoc(), subOptions, lookupResults); for (auto decl : lookupResults) { diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 10563c1fe10f8..632c9ef72690b 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -279,13 +279,15 @@ getDynamicResultSignature(ValueDecl *decl) { llvm_unreachable("Not a valid @objc member"); } -LookupResult &ConstraintSystem::lookupMember(Type base, DeclNameRef name) { +LookupResult &ConstraintSystem::lookupMember(Type base, DeclNameRef name, + SourceLoc loc) { // Check whether we've already performed this lookup. auto &result = MemberLookups[{base, name}]; if (result) return *result; // Lookup the member. - result = TypeChecker::lookupMember(DC, base, name, defaultMemberLookupOptions); + result = TypeChecker::lookupMember(DC, base, name, loc, + defaultMemberLookupOptions); // If we aren't performing dynamic lookup, we're done. if (!*result || !base->isAnyObject()) diff --git a/lib/Sema/ImportResolution.cpp b/lib/Sema/ImportResolution.cpp index 520ae263b6a09..5661c3a20ebc2 100644 --- a/lib/Sema/ImportResolution.cpp +++ b/lib/Sema/ImportResolution.cpp @@ -1135,7 +1135,7 @@ ScopedImportLookupRequest::evaluate(Evaluator &evaluator, lookupInModule(topLevelModule, accessPath.front().Item, decls, NLKind::QualifiedLookup, ResolutionKind::Overloadable, import->getDeclContext()->getModuleScopeContext(), - NL_QualifiedDefault); + import->getLoc(), NL_QualifiedDefault); auto importLoc = import->getLoc(); if (decls.empty()) { diff --git a/lib/Sema/LookupVisibleDecls.cpp b/lib/Sema/LookupVisibleDecls.cpp index c089f6767ad2e..ad39282fdea44 100644 --- a/lib/Sema/LookupVisibleDecls.cpp +++ b/lib/Sema/LookupVisibleDecls.cpp @@ -1143,7 +1143,7 @@ struct KeyPathDynamicMemberConsumer : public VisibleDeclConsumer { } // end anonymous namespace static void lookupVisibleDynamicMemberLookupDecls( - Type baseType, KeyPathDynamicMemberConsumer &consumer, + Type baseType, SourceLoc loc, KeyPathDynamicMemberConsumer &consumer, const DeclContext *dc, LookupState LS, DeclVisibilityKind reason, GenericSignature Sig, VisitedSet &visited, llvm::DenseSet &seenDynamicLookup); @@ -1154,13 +1154,14 @@ static void lookupVisibleDynamicMemberLookupDecls( /// \note This is an implementation detail of \c lookupVisibleMemberDecls and /// exists to create the correct recursion for dynamic member lookup. static void lookupVisibleMemberAndDynamicMemberDecls( - Type baseType, VisibleDeclConsumer &consumer, + Type baseType, SourceLoc loc, VisibleDeclConsumer &consumer, KeyPathDynamicMemberConsumer &dynamicMemberConsumer, const DeclContext *DC, LookupState LS, DeclVisibilityKind reason, GenericSignature Sig, VisitedSet &visited, llvm::DenseSet &seenDynamicLookup) { lookupVisibleMemberDeclsImpl(baseType, consumer, DC, LS, reason, Sig, visited); - lookupVisibleDynamicMemberLookupDecls(baseType, dynamicMemberConsumer, DC, LS, - reason, Sig, visited, seenDynamicLookup); + lookupVisibleDynamicMemberLookupDecls(baseType, loc, dynamicMemberConsumer, + DC, LS, reason, Sig, visited, + seenDynamicLookup); } /// Enumerates all keypath dynamic members of \c baseType, as seen from the @@ -1170,7 +1171,7 @@ static void lookupVisibleMemberAndDynamicMemberDecls( /// dynamic member subscripts and looks up the members of the keypath's root /// type. static void lookupVisibleDynamicMemberLookupDecls( - Type baseType, KeyPathDynamicMemberConsumer &consumer, + Type baseType, SourceLoc loc, KeyPathDynamicMemberConsumer &consumer, const DeclContext *dc, LookupState LS, DeclVisibilityKind reason, GenericSignature Sig, VisitedSet &visited, llvm::DenseSet &seenDynamicLookup) { @@ -1187,7 +1188,7 @@ static void lookupVisibleDynamicMemberLookupDecls( { ctx, DeclBaseName::createSubscript(), { ctx.Id_dynamicMember} }); SmallVector subscripts; - dc->lookupQualified(baseType, subscriptName, + dc->lookupQualified(baseType, subscriptName, loc, NL_QualifiedDefault | NL_ProtocolMembers, subscripts); for (ValueDecl *VD : subscripts) { @@ -1209,9 +1210,9 @@ static void lookupVisibleDynamicMemberLookupDecls( KeyPathDynamicMemberConsumer::SubscriptChange sub(consumer, subscript, baseType); - lookupVisibleMemberAndDynamicMemberDecls(memberType, consumer, consumer, dc, - LS, reason, Sig, visited, - seenDynamicLookup); + lookupVisibleMemberAndDynamicMemberDecls(memberType, loc, consumer, + consumer, dc, LS, reason, Sig, + visited, seenDynamicLookup); } } @@ -1222,8 +1223,9 @@ static void lookupVisibleDynamicMemberLookupDecls( /// where 'self' is the type of 'a'. This operation is only valid after name /// binding. static void lookupVisibleMemberDecls( - Type BaseTy, VisibleDeclConsumer &Consumer, const DeclContext *CurrDC, - LookupState LS, DeclVisibilityKind Reason, GenericSignature Sig) { + Type BaseTy, SourceLoc loc, VisibleDeclConsumer &Consumer, + const DeclContext *CurrDC, LookupState LS, + DeclVisibilityKind Reason, GenericSignature Sig) { OverrideFilteringConsumer overrideConsumer(BaseTy, CurrDC); KeyPathDynamicMemberConsumer dynamicConsumer( Consumer, @@ -1232,7 +1234,7 @@ static void lookupVisibleMemberDecls( VisitedSet Visited; llvm::DenseSet seenDynamicLookup; lookupVisibleMemberAndDynamicMemberDecls( - BaseTy, overrideConsumer, dynamicConsumer, CurrDC, LS, Reason, + BaseTy, loc, overrideConsumer, dynamicConsumer, CurrDC, LS, Reason, Sig, Visited, seenDynamicLookup); // Report the declarations we found to the real consumer. @@ -1346,8 +1348,8 @@ static void lookupVisibleDeclsImpl(VisibleDeclConsumer &Consumer, } if (ExtendedType) { - ::lookupVisibleMemberDecls(ExtendedType, Consumer, DC, LS, MemberReason, - nullptr); + ::lookupVisibleMemberDecls(ExtendedType, Loc, Consumer, DC, LS, + MemberReason, nullptr); // Going outside the current type context. MemberReason = DeclVisibilityKind::MemberOfOutsideNominal; @@ -1403,7 +1405,7 @@ void swift::lookupVisibleDecls(VisibleDeclConsumer &Consumer, } void swift::lookupVisibleMemberDecls(VisibleDeclConsumer &Consumer, Type BaseTy, - const DeclContext *CurrDC, + SourceLoc loc, const DeclContext *CurrDC, bool includeInstanceMembers, bool includeDerivedRequirements, bool includeProtocolExtensionMembers, @@ -1420,7 +1422,7 @@ void swift::lookupVisibleMemberDecls(VisibleDeclConsumer &Consumer, Type BaseTy, ls = ls.withIncludeProtocolExtensionMembers(); } - ::lookupVisibleMemberDecls(BaseTy, Consumer, CurrDC, ls, + ::lookupVisibleMemberDecls(BaseTy, loc, Consumer, CurrDC, ls, DeclVisibilityKind::MemberOfCurrentNominal, Sig); } diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index 4b17e5bfb1859..0c144273096c6 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -4332,7 +4332,8 @@ class ObjCSelectorWalker : public ASTWalker { auto nominal = method->getDeclContext()->getSelfNominalTypeDecl(); auto result = TypeChecker::lookupMember( const_cast(DC), nominal->getDeclaredInterfaceType(), - DeclNameRef(lookupName), defaultMemberLookupOptions); + DeclNameRef(lookupName), method->getLoc(), + defaultMemberLookupOptions); // If we didn't find multiple methods, there is no ambiguity. if (result.size() < 2) return false; diff --git a/lib/Sema/PreCheckExpr.cpp b/lib/Sema/PreCheckExpr.cpp index f634cdf72cdaa..08c56383184cf 100644 --- a/lib/Sema/PreCheckExpr.cpp +++ b/lib/Sema/PreCheckExpr.cpp @@ -602,8 +602,14 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, } TypoCorrectionResults corrections(Name, nameLoc); - TypeChecker::performTypoCorrection(DC, UDRE->getRefKind(), Type(), - lookupOptions, corrections); + + // FIXME: Don't perform typo correction inside macro arguments, because it + // will invoke synthesizing declarations in this scope, which will attempt to + // expand this macro which leads to circular reference errors. + if (!namelookup::isInMacroArgument(DC->getParentSourceFile(), UDRE->getLoc())) { + TypeChecker::performTypoCorrection(DC, UDRE->getRefKind(), Type(), + lookupOptions, corrections); + } if (auto typo = corrections.claimUniqueCorrection()) { auto diag = Context.Diags.diagnose( @@ -1395,7 +1401,7 @@ TypeExpr *PreCheckExpression::simplifyNestedTypeExpr(UnresolvedDotExpr *UDE) { // See if the type has a member type with this name. auto Result = TypeChecker::lookupMemberType( DC, TD->getDeclaredInterfaceType(), Name, - defaultMemberLookupOptions); + UDE->getLoc(), defaultMemberLookupOptions); // If there is no nested type with this name, we have a lookup of // a non-type member, so leave the expression as-is. @@ -1488,6 +1494,7 @@ TypeExpr *PreCheckExpression::simplifyNestedTypeExpr(UnresolvedDotExpr *UDE) { if (BaseTy->mayHaveMembers()) { // See if there is a member type with this name. auto Result = TypeChecker::lookupMemberType(DC, BaseTy, Name, + UDE->getLoc(), defaultMemberLookupOptions); // If there is no nested type with this name, we have a lookup of diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index ae66572e3f267..9d1d99b2b2114 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -2328,7 +2328,8 @@ void AttributeChecker::checkApplicationMainAttribute(DeclAttribute *attr, namelookup::lookupInModule(KitModule, Id_ApplicationDelegate, decls, NLKind::QualifiedLookup, namelookup::ResolutionKind::TypesOnly, - SF, NL_QualifiedDefault); + SF, attr->getLocation(), + NL_QualifiedDefault); if (decls.size() == 1) ApplicationDelegateProto = dyn_cast(decls[0]); } @@ -3047,7 +3048,8 @@ static void lookupReplacedDecl(DeclNameRef replacedDeclName, options |= NL_IncludeUsableFromInline; if (typeCtx) - moduleScopeCtxt->lookupQualified({typeCtx}, replacedDeclName, options, + moduleScopeCtxt->lookupQualified({typeCtx}, replacedDeclName, + attr->getLocation(), options, results); } @@ -4057,11 +4059,12 @@ void AttributeChecker::visitResultBuilderAttr(ResultBuilderAttr *attr) { auto builderType = nominal->getDeclaredType(); nominal->lookupQualified(builderType, DeclNameRef(buildPartialBlockFirst), - NL_QualifiedDefault, + attr->getLocation(), NL_QualifiedDefault, buildPartialBlockFirstMatches); nominal->lookupQualified( builderType, DeclNameRef(buildPartialBlockAccumulated), - NL_QualifiedDefault, buildPartialBlockAccumulatedMatches); + attr->getLocation(), NL_QualifiedDefault, + buildPartialBlockAccumulatedMatches); hasAccessibleBuildPartialBlockFirst = llvm::any_of( buildPartialBlockFirstMatches, isBuildMethodAsAccessibleAsType); @@ -7267,7 +7270,8 @@ ValueDecl *RenamedDeclRequest::evaluate(Evaluator &evaluator, SmallVector lookupResults; attachedContext->lookupQualified(attachedContext->getParentModule(), nameRef.withoutArgumentLabels(), - NL_OnlyTypes, lookupResults); + attr->getLocation(), NL_OnlyTypes, + lookupResults); if (lookupResults.size() == 1) return lookupResults[0]; return nullptr; diff --git a/lib/Sema/TypeCheckCodeCompletion.cpp b/lib/Sema/TypeCheckCodeCompletion.cpp index 58acb0c1e1965..9076c7b7f7aef 100644 --- a/lib/Sema/TypeCheckCodeCompletion.cpp +++ b/lib/Sema/TypeCheckCodeCompletion.cpp @@ -767,6 +767,7 @@ bool swift::typeCheckExpression(DeclContext *DC, Expr *&parsedExpr) { LookupResult swift::lookupSemanticMember(DeclContext *DC, Type ty, DeclName name) { - return TypeChecker::lookupMember(DC, ty, DeclNameRef(name), None); + return TypeChecker::lookupMember(DC, ty, DeclNameRef(name), + SourceLoc(), None); } diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index eb566bcde9a3c..4501c282578be 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -266,7 +266,8 @@ VarDecl *GlobalActorInstanceRequest::evaluate( // conformance to the 'GlobalActor' protocol. SmallVector decls; nominal->lookupQualified( - nominal, DeclNameRef(ctx.Id_shared), NL_QualifiedDefault, decls); + nominal, DeclNameRef(ctx.Id_shared), + nominal->getLoc(), NL_QualifiedDefault, decls); for (auto decl : decls) { auto var = dyn_cast(decl); if (!var) diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index dd0f7655608e3..b982f0436f629 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -774,7 +774,7 @@ PrimaryAssociatedTypesRequest::evaluate(Evaluator &evaluator, SmallVector result; decl->lookupQualified(ArrayRef(decl), - DeclNameRef(pair.first), + DeclNameRef(pair.first), decl->getLoc(), NL_QualifiedDefault | NL_OnlyTypes, result); @@ -1609,28 +1609,6 @@ TypeChecker::lookupPrecedenceGroup(DeclContext *dc, Identifier name, return PrecedenceGroupLookupResult(dc, name, std::move(groups)); } -SmallVector -TypeChecker::lookupMacros(DeclContext *dc, DeclNameRef macroName, - SourceLoc loc, MacroRoles roles) { - SmallVector choices; - auto moduleScopeDC = dc->getModuleScopeContext(); - ASTContext &ctx = moduleScopeDC->getASTContext(); - UnqualifiedLookupDescriptor descriptor(macroName, moduleScopeDC); - auto lookup = evaluateOrDefault( - ctx.evaluator, UnqualifiedLookupRequest{descriptor}, {}); - for (const auto &found : lookup.allResults()) { - if (auto macro = dyn_cast(found.getValueDecl())) { - auto candidateRoles = macro->getMacroRoles(); - if ((candidateRoles && roles.contains(candidateRoles)) || - // FIXME: `externalMacro` should have all roles. - macro->getBaseIdentifier().str() == "externalMacro") { - choices.push_back(macro); - } - } - } - return choices; -} - /// Validate the given operator declaration. /// /// This establishes key invariants, such as an InfixOperatorDecl's diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp index d4aff7bc2bffc..1ff5390225d7f 100644 --- a/lib/Sema/TypeCheckDeclOverride.cpp +++ b/lib/Sema/TypeCheckDeclOverride.cpp @@ -928,7 +928,7 @@ SmallVector OverrideMatcher::match( ctx->synthesizeSemanticMembersIfNeeded(membersName); } dc->lookupQualified(superContexts, DeclNameRef(membersName), - NL_QualifiedDefault, members); + decl->getLoc(), NL_QualifiedDefault, members); } // Check each member we found. diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index a0ecff79ba60c..7b3283e5b959c 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -1412,6 +1412,7 @@ static void diagnoseClassWithoutInitializers(ClassDecl *classDecl) { { C, DeclBaseName::createConstructor(), { C.Id_from } }); auto result = TypeChecker::lookupMember(superclassDecl, superclassType, initFrom, + classDecl->getLoc(), NameLookupFlags::IgnoreAccessControl); if (!result.empty() && !result.front().getValueDecl()->isImplicit()) diff --git a/lib/Sema/TypeCheckMacros.cpp b/lib/Sema/TypeCheckMacros.cpp index 90e00f9fb0c78..c7b0f454aca02 100644 --- a/lib/Sema/TypeCheckMacros.cpp +++ b/lib/Sema/TypeCheckMacros.cpp @@ -1470,6 +1470,40 @@ swift::expandConformances(CustomAttr *attr, MacroDecl *macro, return macroSourceFile->getBufferID(); } +/// Emits an error and returns \c true if the maro reference may +/// introduce arbitrary names at global scope. +static bool diagnoseArbitraryGlobalNames(DeclContext *dc, + UnresolvedMacroReference macroRef, + MacroRole macroRole) { + auto &ctx = dc->getASTContext(); + assert(macroRole == MacroRole::Declaration || + macroRole == MacroRole::Peer); + + if (!dc->isModuleScopeContext()) + return false; + + bool isInvalid = false; + namelookup::forEachPotentialResolvedMacro( + dc, macroRef.getMacroName(), macroRole, + [&](MacroDecl *decl, const MacroRoleAttr *attr) { + if (!isInvalid && + attr->hasNameKind(MacroIntroducedDeclNameKind::Arbitrary)) { + ctx.Diags.diagnose(macroRef.getSigilLoc(), + diag::global_arbitrary_name, + getMacroRoleString(macroRole)); + isInvalid = true; + + // If this is an attached macro, mark the attribute as invalid + // to avoid diagnosing an unknown attribute later. + if (auto *attr = macroRef.getAttr()) { + attr->setInvalid(); + } + } + }); + + return isInvalid; +} + ConcreteDeclRef ResolveMacroRequest::evaluate(Evaluator &evaluator, UnresolvedMacroReference macroRef, DeclContext *dc) const { @@ -1486,12 +1520,25 @@ ConcreteDeclRef ResolveMacroRequest::evaluate(Evaluator &evaluator, // When a macro is not found for a custom attribute, it may be a non-macro. // So bail out to prevent diagnostics from the contraint system. if (macroRef.getAttr()) { - auto foundMacros = TypeChecker::lookupMacros( - dc, macroRef.getMacroName(), SourceLoc(), roles); + auto foundMacros = namelookup::lookupMacros( + dc, macroRef.getMacroName(), roles); if (foundMacros.empty()) return ConcreteDeclRef(); } + // Freestanding and peer macros applied at top-level scope cannot introduce + // arbitrary names. Introducing arbitrary names means that any lookup + // into this scope must expand the macro. This is a problem, because + // resolving the macro can invoke type checking other declarations, e.g. + // anything that the macro arguments depend on. If _anything_ the macro + // depends on performs name unqualified name lookup, e.g. type resolution, + // we'll get circularity errors. It's better to prevent this by banning + // these macros at global scope if any of the macro candidates introduce + // arbitrary names. + if (diagnoseArbitraryGlobalNames(dc, macroRef, MacroRole::Declaration) || + diagnoseArbitraryGlobalNames(dc, macroRef, MacroRole::Peer)) + return ConcreteDeclRef(); + // If we already have a MacroExpansionExpr, use that. Otherwise, // create one. MacroExpansionExpr *macroExpansion; diff --git a/lib/Sema/TypeCheckNameLookup.cpp b/lib/Sema/TypeCheckNameLookup.cpp index 51b8f416467b3..4cfc994ab296c 100644 --- a/lib/Sema/TypeCheckNameLookup.cpp +++ b/lib/Sema/TypeCheckNameLookup.cpp @@ -314,6 +314,7 @@ TypeChecker::lookupUnqualifiedType(DeclContext *dc, DeclNameRef name, LookupResult TypeChecker::lookupMember(DeclContext *dc, Type type, DeclNameRef name, + SourceLoc loc, NameLookupOptions options) { assert(type->mayHaveMembers()); @@ -331,7 +332,7 @@ LookupResult TypeChecker::lookupMember(DeclContext *dc, LookupResultBuilder builder(result, dc, options); SmallVector lookupResults; - dc->lookupQualified(type, name, subOptions, lookupResults); + dc->lookupQualified(type, name, loc, subOptions, lookupResults); for (auto found : lookupResults) builder.add(found, nullptr, /*baseDecl=*/nullptr, type, /*isOuter=*/false); @@ -407,6 +408,7 @@ TypeChecker::isUnsupportedMemberTypeAccess(Type type, TypeDecl *typeDecl, LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc, Type type, DeclNameRef name, + SourceLoc loc, NameLookupOptions options) { LookupTypeResult result; @@ -422,7 +424,7 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc, // Make sure we've resolved implicit members, if we need them. namelookup::installSemanticMembersIfNeeded(type, name); - if (!dc->lookupQualified(type, name, subOptions, decls)) + if (!dc->lookupQualified(type, name, loc, subOptions, decls)) return result; // Look through the declarations, keeping only the unique type declarations. @@ -615,7 +617,7 @@ void TypeChecker::performTypoCorrection(DeclContext *DC, DeclRefKind refKind, }); if (baseTypeOrNull) { - lookupVisibleMemberDecls(consumer, baseTypeOrNull, DC, + lookupVisibleMemberDecls(consumer, baseTypeOrNull, SourceLoc(), DC, /*includeInstanceMembers*/true, /*includeDerivedRequirements*/false, /*includeProtocolExtensionMembers*/true, diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index 69260e9a0975e..eafc5638c7c13 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -142,7 +142,7 @@ lookupEnumMemberElement(DeclContext *DC, Type ty, // FIXME: We should be able to tell if this is a private lookup. NameLookupOptions lookupOptions = defaultMemberLookupOptions; LookupResult foundElements = - TypeChecker::lookupMember(DC, ty, name, lookupOptions); + TypeChecker::lookupMember(DC, ty, name, UseLoc, lookupOptions); return filterForEnumElement(DC, UseLoc, /*unqualifiedLookup=*/false, foundElements); } diff --git a/lib/Sema/TypeCheckPropertyWrapper.cpp b/lib/Sema/TypeCheckPropertyWrapper.cpp index 8e0717021ef52..8419c276f9d57 100644 --- a/lib/Sema/TypeCheckPropertyWrapper.cpp +++ b/lib/Sema/TypeCheckPropertyWrapper.cpp @@ -38,7 +38,9 @@ static VarDecl *findValueProperty(ASTContext &ctx, NominalTypeDecl *nominal, SmallVector vars; { SmallVector decls; - nominal->lookupQualified(nominal, DeclNameRef(name), NL_QualifiedDefault, + nominal->lookupQualified(nominal, DeclNameRef(name), + nominal->getStartLoc(), + NL_QualifiedDefault, decls); for (const auto &foundDecl : decls) { auto foundVar = dyn_cast(foundDecl); @@ -348,6 +350,7 @@ PropertyWrapperTypeInfoRequest::evaluate( SmallVector decls; nominal->lookupQualified(nominal, DeclNameRef::createConstructor(), + nominal->getStartLoc(), NL_QualifiedDefault, decls); PropertyWrapperTypeInfo result; diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index e8197806b3d10..a2580fe9c680e 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -1306,7 +1306,8 @@ WitnessChecker::lookupValueWitnessesViaImplementsAttr( nominal->synthesizeSemanticMembersIfNeeded(name.getFullName()); SmallVector lookupResults; - DC->lookupQualified(nominal, name, subOptions, lookupResults); + DC->lookupQualified(nominal, name, nominal->getLoc(), + subOptions, lookupResults); for (auto decl : lookupResults) { if (!isa(decl->getDeclContext())) @@ -1387,7 +1388,8 @@ WitnessChecker::lookupValueWitnesses(ValueDecl *req, bool *ignoringNames) { SmallVector lookupResults; bool addedAny = false; - DC->lookupQualified(nominal, reqName, options, lookupResults); + DC->lookupQualified(nominal, reqName, nominal->getLoc(), + options, lookupResults); for (auto *decl : lookupResults) { if (!isa(decl->getDeclContext())) { witnesses.push_back(decl); @@ -1399,7 +1401,8 @@ WitnessChecker::lookupValueWitnesses(ValueDecl *req, bool *ignoringNames) { // again using only the base name. if (!addedAny && ignoringNames) { lookupResults.clear(); - DC->lookupQualified(nominal, reqBaseName, options, lookupResults); + DC->lookupQualified(nominal, reqBaseName, nominal->getLoc(), + options, lookupResults); for (auto *decl : lookupResults) { if (!isa(decl->getDeclContext())) witnesses.push_back(decl); @@ -4754,6 +4757,7 @@ ResolveWitnessResult ConformanceChecker::resolveTypeWitnessViaLookup( DC->lookupQualified(DC->getSelfNominalTypeDecl(), assocType->createNameRef(), + DC->getSelfNominalTypeDecl()->getLoc(), subOptions, candidates); // If there aren't any candidates, we're done. @@ -6331,7 +6335,8 @@ diagnoseMissingAppendInterpolationMethod(NominalTypeDecl *typeDecl) { DeclNameRef baseName(typeDecl->getASTContext().Id_appendInterpolation); SmallVector lookupResults; - typeDecl->lookupQualified(typeDecl, baseName, subOptions, lookupResults); + typeDecl->lookupQualified(typeDecl, baseName, typeDecl->getLoc(), + subOptions, lookupResults); for (auto decl : lookupResults) { auto method = dyn_cast(decl); if (!method) continue; @@ -7202,6 +7207,7 @@ void TypeChecker::inferDefaultWitnesses(ProtocolDecl *proto) { SmallVector found; module->lookupQualified( proto, DeclNameRef(assocType->getName()), + proto->getLoc(), NL_QualifiedDefault|NL_ProtocolMembers|NL_OnlyTypes, found); if (found.size() == 1 && isa(found[0])) diff --git a/lib/Sema/TypeCheckProtocolInference.cpp b/lib/Sema/TypeCheckProtocolInference.cpp index 89fdacaa6b247..830d1aed3df7a 100644 --- a/lib/Sema/TypeCheckProtocolInference.cpp +++ b/lib/Sema/TypeCheckProtocolInference.cpp @@ -594,6 +594,7 @@ AssociatedTypeInference::inferTypeWitnessesViaAssociatedType( // @_implements attributes. SmallVector lookupResults; dc->lookupQualified(adoptee->getAnyNominal(), defaultName, + adoptee->getAnyNominal()->getStartLoc(), subOptions, lookupResults); InferredAssociatedTypesByWitnesses result; diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 6acbee696995c..ae0b89651947f 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -2180,6 +2180,7 @@ static bool checkSuperInit(ConstructorDecl *fromCtor, SmallVector lookupResults; fromCtor->lookupQualified(superclassDecl, DeclNameRef::createConstructor(), + apply->getLoc(), subOptions, lookupResults); for (auto decl : lookupResults) { diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index c448f4dd90103..979654b18cc1b 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -2730,10 +2730,10 @@ static VarDecl *synthesizePropertyWrapperProjectionVar( auto dc = var->getDeclContext(); if (dc->isTypeContext()) { dc->lookupQualified(dc->getSelfNominalTypeDecl(), projectionName, - NL_QualifiedDefault, declsFound); + var->getLoc(), NL_QualifiedDefault, declsFound); } else if (dc->isModuleScopeContext()) { dc->lookupQualified(dc->getParentModule(), projectionName, - NL_QualifiedDefault, declsFound); + var->getLoc(), NL_QualifiedDefault, declsFound); } else { llvm_unreachable("Property wrappers don't work in local contexts"); } diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 6926bef6593d0..ef53dab93a395 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -1412,7 +1412,8 @@ static Type diagnoseUnknownType(TypeResolution resolution, NameLookupOptions relookupOptions = lookupOptions; relookupOptions |= NameLookupFlags::IgnoreAccessControl; auto inaccessibleMembers = TypeChecker::lookupMemberType( - dc, parentType, repr->getNameRef(), relookupOptions); + dc, parentType, repr->getNameRef(), + repr->getLoc(), relookupOptions); if (inaccessibleMembers) { // FIXME: What if the unviable candidates have different levels of access? const TypeDecl *first = inaccessibleMembers.front().Member; @@ -1443,8 +1444,8 @@ static Type diagnoseUnknownType(TypeResolution resolution, NLOptions memberLookupOptions = (NL_QualifiedDefault | NL_IgnoreAccessControl); SmallVector results; - dc->lookupQualified(parentType, repr->getNameRef(), memberLookupOptions, - results); + dc->lookupQualified(parentType, repr->getNameRef(), repr->getLoc(), + memberLookupOptions, results); // Looks like this is not a member type, but simply a member of parent type. if (!results.empty()) { @@ -1834,7 +1835,7 @@ static Type resolveQualifiedIdentTypeRepr(TypeResolution resolution, LookupTypeResult memberTypes; if (parentTy->mayHaveMembers()) memberTypes = TypeChecker::lookupMemberType( - DC, parentTy, repr->getNameRef(), lookupOptions); + DC, parentTy, repr->getNameRef(), repr->getLoc(), lookupOptions); // Name lookup was ambiguous. Complain. // FIXME: Could try to apply generic arguments first, and see whether diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index 4cba8b17db863..22aed44dd31fc 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -914,6 +914,7 @@ LookupResult lookupUnqualifiedType( /// \returns The result of name lookup. LookupResult lookupMember(DeclContext *dc, Type type, DeclNameRef name, + SourceLoc loc = SourceLoc(), NameLookupOptions options = defaultMemberLookupOptions); /// Look up a member type within the given type. @@ -929,6 +930,7 @@ lookupMember(DeclContext *dc, Type type, DeclNameRef name, /// \returns The result of name lookup. LookupTypeResult lookupMemberType(DeclContext *dc, Type type, DeclNameRef name, + SourceLoc loc = SourceLoc(), NameLookupOptions options = defaultMemberTypeLookupOptions); /// Given an expression that's known to be an infix operator, @@ -939,10 +941,6 @@ lookupPrecedenceGroupForInfixOperator(DeclContext *dc, Expr *op, bool diagnose); PrecedenceGroupLookupResult lookupPrecedenceGroup(DeclContext *dc, Identifier name, SourceLoc nameLoc); -SmallVector -lookupMacros(DeclContext *dc, DeclNameRef macroName, SourceLoc loc, - MacroRoles contexts); - enum class UnsupportedMemberTypeAccessKind : uint8_t { None, TypeAliasOfUnboundGeneric, diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 21f3f0bcc34a4..b07da21d476c2 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -1926,7 +1926,7 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) { getIdentifier(privateDiscriminator)); } else { baseModule->lookupQualified(baseModule, DeclNameRef(name), - NL_QualifiedDefault, + SourceLoc(), NL_QualifiedDefault, values); } filterValues(filterTy, nullptr, nullptr, isType, inProtocolExt, @@ -2113,7 +2113,7 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) { getIdentifier(privateDiscriminator)); } else { otherModule->lookupQualified(otherModule, DeclNameRef(name), - NL_QualifiedDefault, + SourceLoc(), NL_QualifiedDefault, values); } diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp index 4e7bc7a429dce..98e7cf39b4641 100644 --- a/lib/Serialization/ModuleFile.cpp +++ b/lib/Serialization/ModuleFile.cpp @@ -560,7 +560,7 @@ void ModuleFile::getImportDecls(SmallVectorImpl &Results) { SmallVector Decls; TopLevelModule->lookupQualified( TopLevelModule, DeclNameRef(ScopeID), - NL_QualifiedDefault, Decls); + SourceLoc(), NL_QualifiedDefault, Decls); Optional FoundKind = ImportDecl::findBestImportKind(Decls); assert(FoundKind.has_value() && "deserialized imports should not be ambiguous"); diff --git a/test/Macros/Inputs/syntax_macro_definitions.swift b/test/Macros/Inputs/syntax_macro_definitions.swift index b01cb48da66dc..3b4d17dc27118 100644 --- a/test/Macros/Inputs/syntax_macro_definitions.swift +++ b/test/Macros/Inputs/syntax_macro_definitions.swift @@ -1603,3 +1603,26 @@ extension SelfAlwaysEqualOperator: MemberMacro { ] } } + +public struct InitializableMacro: ConformanceMacro, MemberMacro { + public static func expansion( + of node: AttributeSyntax, + providingConformancesOf decl: some DeclGroupSyntax, + in context: some MacroExpansionContext + ) throws -> [(TypeSyntax, GenericWhereClauseSyntax?)] { + return [("Initializable", nil)] + } + + public static func expansion( + of node: AttributeSyntax, + providingMembersOf decl: some DeclGroupSyntax, + in context: some MacroExpansionContext + ) throws -> [DeclSyntax] { + let requirement: DeclSyntax = + """ + init(value: Int) {} + """ + + return [requirement] + } +} diff --git a/test/Macros/macro_expand_peers.swift b/test/Macros/macro_expand_peers.swift index 1f469a088a814..304c621f186fa 100644 --- a/test/Macros/macro_expand_peers.swift +++ b/test/Macros/macro_expand_peers.swift @@ -162,6 +162,16 @@ struct S2 { #endif } +#if TEST_DIAGNOSTICS +// Peer macros cannot introduce arbitrary names at global scope + +//expected-error@+1 {{'peer' macros are not allowed to introduce arbitrary names at global scope}} +@addCompletionHandlerArbitrarily(x) +func h(a: Int, for b: String, _ value: Double) async -> String { + return b +} +#endif + // Stored properties generated by a peer macro @attached(accessor) @attached(peer, names: prefixed(_)) diff --git a/test/Macros/top_level_freestanding.swift b/test/Macros/top_level_freestanding.swift index 3fd9c07c1d6bd..48fe22e78ca51 100644 --- a/test/Macros/top_level_freestanding.swift +++ b/test/Macros/top_level_freestanding.swift @@ -72,13 +72,17 @@ struct HasInnerClosure { #freestandingWithClosure(1) { x in x } } +#if TEST_DIAGNOSTICS // Arbitrary names at global scope #bitwidthNumberedStructs("MyIntGlobal") +// expected-error@-1 {{'declaration' macros are not allowed to introduce arbitrary names at global scope}} func testArbitraryAtGlobal() { _ = MyIntGlobal16() + // expected-error@-1 {{cannot find 'MyIntGlobal16' in scope}} } +#endif // DIAG_BUFFERS-DAG: @__swiftmacro_9MacroUser33_{{.*}}9stringifyfMf1_{{.*}}warning: 'deprecated()' is deprecated // DIAG_BUFFERS-DAG: @__swiftmacro_9MacroUser33_{{.*}}9stringifyfMf2_{{.*}}warning: 'deprecated()' is deprecated @@ -104,3 +108,24 @@ func testGlobalVariable() { } #endif + + +@freestanding(declaration) +macro Empty(_ closure: () -> T) = #externalMacro(module: "MacroDefinition", type: "EmptyDeclarationMacro") + +#Empty { + S(a: 10, b: 10) +} + +@attached(conformance) +@attached(member, names: named(init)) +macro Initializable() = #externalMacro(module: "MacroDefinition", type: "InitializableMacro") + +protocol Initializable { + init(value: Int) +} + +@Initializable +struct S { + init(a: Int, b: Int) {} +} diff --git a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp index c0bc79d71151a..928377c556793 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp @@ -536,7 +536,8 @@ static void walkRelatedDecls(const ValueDecl *VD, const FnTy &Fn) { auto type = DC->getDeclaredInterfaceType(); if (!type->is()) { DC->lookupQualified(type, DeclNameRef(VD->getBaseName()), - NL_QualifiedDefault, results); + VD->getLoc(), NL_QualifiedDefault, + results); } } else { namelookup::lookupInModule(DC->getModuleScopeContext(), @@ -544,6 +545,7 @@ static void walkRelatedDecls(const ValueDecl *VD, const FnTy &Fn) { NLKind::UnqualifiedLookup, namelookup::ResolutionKind::Overloadable, DC->getModuleScopeContext(), + VD->getLoc(), NL_UnqualifiedDefault); }