From 804eab8ac0d7ae5e3729b80cc8de365047367a1e Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Wed, 7 Jun 2023 21:27:33 -0700 Subject: [PATCH 01/14] [ASTScope] Rename and generalize AttachedPropertyWrapperScope to CustomAttributeScope so that it can represent the scope for any custom attribute and its arguments. This commit is NFC, but CustomAttributeScope is now applicable to attached macros. (cherry picked from commit abcdc6c60f2ea456869347da4f3c2698d38528de) --- include/swift/AST/ASTScope.h | 24 ++++++++++-------------- lib/AST/ASTScope.cpp | 2 +- lib/AST/ASTScopeCreation.cpp | 6 +++--- lib/AST/ASTScopeSourceRange.cpp | 2 +- 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/include/swift/AST/ASTScope.h b/include/swift/AST/ASTScope.h index 5ebe70dcef3be..5cbbc8ee8ab4e 100644 --- a/include/swift/AST/ASTScope.h +++ b/include/swift/AST/ASTScope.h @@ -840,24 +840,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; + ValueDecl *decl; - AttachedPropertyWrapperScope(CustomAttr *attr, VarDecl *decl) + CustomAttributeScope(CustomAttr *attr, ValueDecl *decl) : attr(attr), decl(decl) {} - virtual ~AttachedPropertyWrapperScope() {} + virtual ~CustomAttributeScope() {} protected: ASTScopeImpl *expandSpecifically(ScopeCreator &) override; diff --git a/lib/AST/ASTScope.cpp b/lib/AST/ASTScope.cpp index c4eb1d1370f5f..e71d5f2e9014a 100644 --- a/lib/AST/ASTScope.cpp +++ b/lib/AST/ASTScope.cpp @@ -138,7 +138,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..ef6f34abd8c53 100644 --- a/lib/AST/ASTScopeCreation.cpp +++ b/lib/AST/ASTScopeCreation.cpp @@ -602,7 +602,7 @@ void ScopeCreator::addChildrenForKnownAttributes(ValueDecl *decl, } } else if (auto *customAttr = dyn_cast(attr)) { if (auto *vd = dyn_cast(decl)) { - constructExpandAndInsert( + constructExpandAndInsert( parent, customAttr, vd); } } @@ -716,7 +716,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 +1177,7 @@ void DefaultArgumentInitializerScope:: scopeCreator.addToScopeTree(initExpr, this); } -void AttachedPropertyWrapperScope:: +void CustomAttributeScope:: expandAScopeThatDoesNotCreateANewInsertionPoint( ScopeCreator &scopeCreator) { if (auto *args = attr->getArgs()) { 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(); } From 5dbe6ac2efe8aa82e1f77493a6bd865d845aa30b Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Fri, 9 Jun 2023 23:33:17 -0700 Subject: [PATCH 02/14] [ASTScope] Add attribute scopes for nominal type and extension scopes. (cherry picked from commit 2c0c596d95f9ad967a97d6f77a032ad266f40b36) --- include/swift/AST/ASTScope.h | 8 ++++---- lib/AST/ASTScopeCreation.cpp | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/swift/AST/ASTScope.h b/include/swift/AST/ASTScope.h index 5cbbc8ee8ab4e..6c88eca412355 100644 --- a/include/swift/AST/ASTScope.h +++ b/include/swift/AST/ASTScope.h @@ -849,9 +849,9 @@ class DefaultArgumentInitializerScope final : public ASTScopeImpl { class CustomAttributeScope final : public ASTScopeImpl { public: CustomAttr *attr; - ValueDecl *decl; + Decl *decl; - CustomAttributeScope(CustomAttr *attr, ValueDecl *decl) + CustomAttributeScope(CustomAttr *attr,Decl *decl) : attr(attr), decl(decl) {} virtual ~CustomAttributeScope() {} @@ -1130,9 +1130,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() {} diff --git a/lib/AST/ASTScopeCreation.cpp b/lib/AST/ASTScopeCreation.cpp index ef6f34abd8c53..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); } } } @@ -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() From d226b082e8e4a07851befb00324a694bd811466d Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Sat, 10 Jun 2023 00:40:15 -0700 Subject: [PATCH 03/14] [ASTScope] Add APIs for determining whether a given source location is inside a macro argument. (cherry picked from commit cd79cf97d683a7fb711d89cff2ea0bcd447e0d6b) --- include/swift/AST/ASTScope.h | 25 ++++++++++++++++++++++++- include/swift/AST/NameLookup.h | 4 ++++ lib/AST/ASTScope.cpp | 5 +++++ lib/AST/ASTScopeLookup.cpp | 18 ++++++++++++++++++ 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/include/swift/AST/ASTScope.h b/include/swift/AST/ASTScope.h index 6c88eca412355..a8d229e89069b 100644 --- a/include/swift/AST/ASTScope.h +++ b/include/swift/AST/ASTScope.h @@ -278,6 +278,17 @@ class ASTScopeImpl : public ASTAllocated { static std::pair lookupFallthroughSourceAndDest(SourceFile *sourceFile, SourceLoc loc); + /// Returns \c true if the given source location is inside an attached + /// or freestanding macro argument. + static bool isInMacroArgument(SourceFile *sourceFile, SourceLoc loc); + + /// Returns \c true if this scope contains macro arguments. + /// + /// This is always true within macro expansion decl scopes, and it's + /// true within custom attribute scopes if the attribute name is a + /// potential macro reference. + virtual bool isMacroArgumentScope() const { return false; } + /// 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; } @@ -867,7 +878,15 @@ class CustomAttributeScope final : public ASTScopeImpl { NullablePtr getDeclAttributeIfAny() const override { return attr; } - bool ignoreInDebugInfo() const override { return true; } + bool ignoreInDebugInfo() const override { return true; } + + bool isMacroArgumentScope() const override { + // FIXME: This should check whether the attribute name is + // a macro. Otherwise, macro expansion will be suppressed + // for property wrapper arguments. + return true; + } + private: void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &); }; @@ -1266,6 +1285,10 @@ class MacroExpansionDeclScope final : public ASTScopeImpl { SourceRange getSourceRangeOfThisASTNode(bool omitAssertions = false) const override; + bool isMacroArgumentScope() const override { + return true; + } + protected: void printSpecifics(llvm::raw_ostream &out) const override; diff --git a/include/swift/AST/NameLookup.h b/include/swift/AST/NameLookup.h index 82085c59f5b09..bc5aea9c1b07b 100644 --- a/include/swift/AST/NameLookup.h +++ b/include/swift/AST/NameLookup.h @@ -815,6 +815,10 @@ class ASTScope : public ASTAllocated { static std::pair lookupFallthroughSourceAndDest(SourceFile *sourceFile, SourceLoc loc); + /// Returns \c true if the given source location is inside an attached + /// or freestanding macro argument. + static bool isInMacroArgument(SourceFile *sourceFile, SourceLoc loc); + SWIFT_DEBUG_DUMP; void print(llvm::raw_ostream &) const; void dumpOneScopeMapLocation(std::pair); diff --git a/lib/AST/ASTScope.cpp b/lib/AST/ASTScope.cpp index e71d5f2e9014a..b9b830aad6cce 100644 --- a/lib/AST/ASTScope.cpp +++ b/lib/AST/ASTScope.cpp @@ -60,6 +60,11 @@ std::pair ASTScope::lookupFallthroughSourceAndDest( return ASTScopeImpl::lookupFallthroughSourceAndDest(sourceFile, loc); } +bool ASTScope::isInMacroArgument(SourceFile *sourceFile, + SourceLoc loc) { + return ASTScopeImpl::isInMacroArgument(sourceFile, loc); +} + #if SWIFT_COMPILER_IS_MSVC #pragma warning(push) #pragma warning(disable : 4996) diff --git a/lib/AST/ASTScopeLookup.cpp b/lib/AST/ASTScopeLookup.cpp index 676e6e9dbdd77..f7aa0bba5b46c 100644 --- a/lib/AST/ASTScopeLookup.cpp +++ b/lib/AST/ASTScopeLookup.cpp @@ -675,3 +675,21 @@ std::pair ASTScopeImpl::lookupFallthroughSourceAndDest( return { nullptr, nullptr }; } + +bool ASTScopeImpl::isInMacroArgument(SourceFile *sourceFile, + SourceLoc loc) { + if (!sourceFile || sourceFile->Kind == SourceFileKind::Interface) + return false; + + if (loc.isInvalid()) + return false; + + auto *fileScope = sourceFile->getScope().impl; + auto *scope = fileScope->findInnermostEnclosingScope(loc, nullptr); + do { + if (scope->isMacroArgumentScope()) + return true; + } while ((scope = scope->getParent().getPtrOrNull())); + + return false; +} From 68b8c69883d9e6f3f4b28497b9f208bec420c498 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Sat, 10 Jun 2023 00:52:17 -0700 Subject: [PATCH 04/14] [Macros] Always exclude macro expansions in TypeChecker::lookupMacros. (cherry picked from commit 29430645110307597f6aa1ea0e342ac0dfd4fc45) --- lib/Sema/CSGen.cpp | 9 ++++----- lib/Sema/TypeCheckDecl.cpp | 12 ++++++++++-- lib/Sema/TypeCheckMacros.cpp | 2 +- lib/Sema/TypeChecker.h | 3 +-- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 867a9f74ba1d6..1eb5491154c93 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); + 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/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 4dd71587584b3..f4ed0a5af1f18 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -1612,11 +1612,19 @@ TypeChecker::lookupPrecedenceGroup(DeclContext *dc, Identifier name, SmallVector TypeChecker::lookupMacros(DeclContext *dc, DeclNameRef macroName, - SourceLoc loc, MacroRoles roles) { + MacroRoles roles) { SmallVector choices; auto moduleScopeDC = dc->getModuleScopeContext(); ASTContext &ctx = moduleScopeDC->getASTContext(); - UnqualifiedLookupDescriptor descriptor(macroName, moduleScopeDC); + + // 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()) { diff --git a/lib/Sema/TypeCheckMacros.cpp b/lib/Sema/TypeCheckMacros.cpp index 5a64184d06448..2713f1e6e15fb 100644 --- a/lib/Sema/TypeCheckMacros.cpp +++ b/lib/Sema/TypeCheckMacros.cpp @@ -1488,7 +1488,7 @@ ConcreteDeclRef ResolveMacroRequest::evaluate(Evaluator &evaluator, // So bail out to prevent diagnostics from the contraint system. if (macroRef.getAttr()) { auto foundMacros = TypeChecker::lookupMacros( - dc, macroRef.getMacroName(), SourceLoc(), roles); + dc, macroRef.getMacroName(), roles); if (foundMacros.empty()) return ConcreteDeclRef(); } diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index a8568b6ee29d7..c8c4e63b61f0e 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -940,8 +940,7 @@ PrecedenceGroupLookupResult lookupPrecedenceGroup(DeclContext *dc, Identifier name, SourceLoc nameLoc); SmallVector -lookupMacros(DeclContext *dc, DeclNameRef macroName, SourceLoc loc, - MacroRoles contexts); +lookupMacros(DeclContext *dc, DeclNameRef macroName, MacroRoles contexts); enum class UnsupportedMemberTypeAccessKind : uint8_t { None, From 6097df7da1babb66fe25c8db5d7115c242881d77 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Sat, 10 Jun 2023 01:38:30 -0700 Subject: [PATCH 05/14] [NameLookup] Plumb source location arguments through all name lookup APIs. This source location will be used to determine whether to add a name lookup option to exclude macro expansions when the name lookup request is constructed. Currently, the source location argument is unused. (cherry picked from commit cd752cca225174fd8459986273c172fc0c86d2af) --- include/swift/AST/Decl.h | 5 +- include/swift/AST/DeclContext.h | 7 ++- include/swift/AST/ModuleNameLookup.h | 2 +- include/swift/AST/NameLookupRequests.h | 8 +-- include/swift/Sema/ConstraintSystem.h | 3 +- lib/AST/ASTContext.cpp | 7 ++- lib/AST/Decl.cpp | 8 +-- lib/AST/DocComment.cpp | 3 +- lib/AST/ModuleNameLookup.cpp | 4 +- lib/AST/NameLookup.cpp | 61 ++++++++++++------- lib/AST/NameLookupRequests.cpp | 23 ++++--- lib/AST/RequirementMachine/NameLookup.cpp | 2 +- lib/AST/UnqualifiedLookup.cpp | 6 +- lib/ClangImporter/ImportDecl.cpp | 7 ++- lib/Frontend/ModuleInterfaceSupport.cpp | 2 +- lib/IDE/ExprContextAnalysis.cpp | 9 ++- lib/SIL/IR/SILFunctionType.cpp | 2 +- lib/SILGen/SILGen.cpp | 2 +- lib/SILGen/SILGenFunction.cpp | 2 +- lib/Sema/BuilderTransform.cpp | 1 + lib/Sema/CSDiagnostics.cpp | 3 +- lib/Sema/CSSimplify.cpp | 17 ++++-- lib/Sema/CodeSynthesis.cpp | 1 + lib/Sema/ConstraintSystem.cpp | 6 +- lib/Sema/ImportResolution.cpp | 2 +- lib/Sema/LookupVisibleDecls.cpp | 1 + lib/Sema/MiscDiagnostics.cpp | 3 +- lib/Sema/PreCheckExpr.cpp | 3 +- lib/Sema/TypeCheckAttr.cpp | 14 +++-- lib/Sema/TypeCheckCodeCompletion.cpp | 3 +- lib/Sema/TypeCheckConcurrency.cpp | 3 +- lib/Sema/TypeCheckDecl.cpp | 2 +- lib/Sema/TypeCheckDeclOverride.cpp | 2 +- lib/Sema/TypeCheckDeclPrimary.cpp | 1 + lib/Sema/TypeCheckNameLookup.cpp | 6 +- lib/Sema/TypeCheckPattern.cpp | 2 +- lib/Sema/TypeCheckPropertyWrapper.cpp | 5 +- lib/Sema/TypeCheckProtocol.cpp | 14 +++-- lib/Sema/TypeCheckProtocolInference.cpp | 1 + lib/Sema/TypeCheckStmt.cpp | 1 + lib/Sema/TypeCheckStorage.cpp | 4 +- lib/Sema/TypeCheckType.cpp | 9 +-- lib/Sema/TypeChecker.h | 2 + lib/Serialization/Deserialization.cpp | 4 +- lib/Serialization/ModuleFile.cpp | 2 +- .../lib/SwiftLang/SwiftSourceDocInfo.cpp | 4 +- 46 files changed, 174 insertions(+), 105 deletions(-) diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 445c019d6f60c..958891b373407 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/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/NameLookupRequests.h b/include/swift/AST/NameLookupRequests.h index a80596c2ecce7..26401a232a0ed 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/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 1034c6b8848b5..5a54d3fd8ae2d 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 9ccec3ea7d8f3..0a2b122d693b4 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1058,8 +1058,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) \ @@ -1322,7 +1322,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/Decl.cpp b/lib/AST/Decl.cpp index b6d9b5b05b76d..a175ca301c56a 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -5386,7 +5386,7 @@ NominalTypeDecl::getExecutorOwnedEnqueueFunction() const { llvm::SmallVector results; lookupQualified(getSelfNominalTypeDecl(), DeclNameRef(C.Id_enqueue), - NL_ProtocolMembers, + getLoc(), NL_ProtocolMembers, results); for (auto candidate: results) { @@ -5425,7 +5425,7 @@ NominalTypeDecl::getExecutorLegacyOwnedEnqueueFunction() const { llvm::SmallVector results; lookupQualified(getSelfNominalTypeDecl(), DeclNameRef(C.Id_enqueue), - NL_ProtocolMembers, + getLoc(), NL_ProtocolMembers, results); for (auto candidate: results) { @@ -5464,7 +5464,7 @@ NominalTypeDecl::getExecutorLegacyUnownedEnqueueFunction() const { llvm::SmallVector results; lookupQualified(getSelfNominalTypeDecl(), DeclNameRef(C.Id_enqueue), - NL_ProtocolMembers, + getLoc(), NL_ProtocolMembers, results); for (auto candidate: results) { @@ -9918,7 +9918,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 d27eb8dfc605d..ab4b27dce7d5c 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/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 98b13f3550473..b032876d369d2 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -1851,10 +1851,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 +2195,7 @@ void namelookup::tryExtractDirectlyReferencedNominalTypes( bool DeclContext::lookupQualified(Type type, DeclNameRef member, + SourceLoc loc, NLOptions options, SmallVectorImpl &decls) const { using namespace namelookup; @@ -2209,14 +2210,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 +2254,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 +2312,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 +2390,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 +2411,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 +2428,7 @@ ModuleQualifiedLookupRequest::evaluate(Evaluator &eval, const DeclContext *DC, })) { lookupInModule(module, member.getFullName(), decls, NLKind::QualifiedLookup, kind, topLevelScope, - options); + SourceLoc(), options); } } @@ -2613,6 +2620,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 (ASTScope::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 +2661,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 +2691,7 @@ directReferencesForQualifiedTypeLookup(Evaluator &evaluator, ArrayRef baseTypes, DeclNameRef name, DeclContext *dc, + SourceLoc loc, bool allowUsableFromInline=false) { DirectlyReferencedTypeDecls result; auto addResults = [&result](ArrayRef found){ @@ -2705,7 +2718,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 +2726,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 +2778,7 @@ directReferencesForDeclRefTypeRepr(Evaluator &evaluator, ASTContext &ctx, current = directReferencesForQualifiedTypeLookup(evaluator, ctx, current, component->getNameRef(), dc, + component->getLoc(), allowUsableFromInline); if (current.empty()) return current; @@ -3549,7 +3563,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..2376d38928e2c 100644 --- a/lib/AST/NameLookupRequests.cpp +++ b/lib/AST/NameLookupRequests.cpp @@ -555,7 +555,7 @@ 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; @@ -572,7 +572,8 @@ 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; @@ -591,25 +592,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 f2e981dc1d161..94972adabff70 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -6501,7 +6501,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() || @@ -6574,7 +6574,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); @@ -8261,7 +8261,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/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/SIL/IR/SILFunctionType.cpp b/lib/SIL/IR/SILFunctionType.cpp index 4e36cc1b39349..b400796adc839 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 d20aae7beb325..bb00a91eb8361 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/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index efdd3a25de389..3f98057b25af3 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -9310,6 +9310,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(); } @@ -9422,7 +9425,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()). @@ -9822,7 +9825,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, @@ -9832,7 +9836,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" @@ -9895,7 +9900,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, @@ -9963,7 +9969,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 1054c2a55ada6..6a9f951ea2a75 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..2d723468f1597 100644 --- a/lib/Sema/LookupVisibleDecls.cpp +++ b/lib/Sema/LookupVisibleDecls.cpp @@ -1188,6 +1188,7 @@ static void lookupVisibleDynamicMemberLookupDecls( SmallVector subscripts; dc->lookupQualified(baseType, subscriptName, + baseType->getAnyNominal()->getLoc(), NL_QualifiedDefault | NL_ProtocolMembers, subscripts); for (ValueDecl *VD : subscripts) { diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index f338cc2856044..973fac065f0b6 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -4331,7 +4331,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..e270db6a2e799 100644 --- a/lib/Sema/PreCheckExpr.cpp +++ b/lib/Sema/PreCheckExpr.cpp @@ -1395,7 +1395,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 +1488,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 be46303e39966..16bbb590abe5d 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -2300,7 +2300,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]); } @@ -3009,7 +3010,8 @@ static void lookupReplacedDecl(DeclNameRef replacedDeclName, options |= NL_IncludeUsableFromInline; if (typeCtx) - moduleScopeCtxt->lookupQualified({typeCtx}, replacedDeclName, options, + moduleScopeCtxt->lookupQualified({typeCtx}, replacedDeclName, + attr->getLocation(), options, results); } @@ -4032,11 +4034,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); @@ -7242,7 +7245,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 f4ed0a5af1f18..84142ad5a22d4 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); diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp index 83ed04797276a..4268c7d624913 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 3c06ccd47e0d8..436c940246762 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -1413,6 +1413,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/TypeCheckNameLookup.cpp b/lib/Sema/TypeCheckNameLookup.cpp index 51b8f416467b3..8d1c037b6aee1 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. diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index ccecf769eebc1..afe2ba7683725 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 772d0d494a325..7a2f826453e39 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -1304,7 +1304,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())) @@ -1385,7 +1386,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); @@ -1397,7 +1399,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); @@ -4752,6 +4755,7 @@ ResolveWitnessResult ConformanceChecker::resolveTypeWitnessViaLookup( DC->lookupQualified(DC->getSelfNominalTypeDecl(), assocType->createNameRef(), + DC->getSelfNominalTypeDecl()->getLoc(), subOptions, candidates); // If there aren't any candidates, we're done. @@ -6329,7 +6333,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; @@ -7200,6 +7205,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 c9a754885ee2f..fe0a15bd6e7c5 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -2734,10 +2734,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 9e75d85f8b08b..5076603ec6652 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -1411,7 +1411,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; @@ -1442,8 +1443,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()) { @@ -1833,7 +1834,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 c8c4e63b61f0e..ad8f06703c254 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, diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index d5e1af5156d69..dae20e9bad3d7 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -1716,7 +1716,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, @@ -1899,7 +1899,7 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) { getIdentifier(privateDiscriminator)); } else { baseModule->lookupQualified(baseModule, DeclNameRef(name), - NL_QualifiedDefault, + SourceLoc(), NL_QualifiedDefault, values); } diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp index 132d1901ecd85..e52ace0968388 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/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); } From dfc4c9a49f3a7d7a7663a75e7d774ae5a98df7c7 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Sat, 10 Jun 2023 01:41:20 -0700 Subject: [PATCH 06/14] [NameLookup] Use source locations to determine whether to exclude macro expansions. Evaluator::hasActiveResolveMacroRequest is now unused. (cherry picked from commit 61c99ccd1a12232d230305ce2f530d536a6c6948) --- lib/AST/NameLookupRequests.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/AST/NameLookupRequests.cpp b/lib/AST/NameLookupRequests.cpp index 2376d38928e2c..600a27ba4b283 100644 --- a/lib/AST/NameLookupRequests.cpp +++ b/lib/AST/NameLookupRequests.cpp @@ -545,8 +545,10 @@ static UnqualifiedLookupDescriptor excludeMacrosIfNeeded( UnqualifiedLookupFlags::ExcludeMacroExpansions)) return descriptor; - auto &evaluator = descriptor.DC->getASTContext().evaluator; - if (!evaluator.hasActiveResolveMacroRequest()) + auto isInMacroArgument = ASTScope::isInMacroArgument( + descriptor.DC->getParentSourceFile(), descriptor.Loc); + + if (!isInMacroArgument) return descriptor; descriptor.Options |= UnqualifiedLookupFlags::ExcludeMacroExpansions; @@ -560,8 +562,10 @@ static DirectLookupDescriptor excludeMacrosIfNeeded( NominalTypeDecl::LookupDirectFlags::ExcludeMacroExpansions)) return descriptor; - auto &evaluator = descriptor.DC->getASTContext().evaluator; - if (!evaluator.hasActiveResolveMacroRequest()) + auto isInMacroArgument = ASTScope::isInMacroArgument( + descriptor.DC->getParentSourceFile(), loc); + + if (!isInMacroArgument) return descriptor; descriptor.Options |= @@ -577,8 +581,10 @@ excludeMacrosIfNeeded(const DeclContext *dc, SourceLoc loc, if (options & NL_ExcludeMacroExpansions) return options; - auto &evaluator = dc->getASTContext().evaluator; - if (!evaluator.hasActiveResolveMacroRequest()) + auto isInMacroArgument = ASTScope::isInMacroArgument( + dc->getParentSourceFile(), loc); + + if (!isInMacroArgument) return options; return options | NL_ExcludeMacroExpansions; From 8d2da1414604e7414b528425b5c85128fddb3a50 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Sat, 10 Jun 2023 01:42:25 -0700 Subject: [PATCH 07/14] [PreCheckExpr] Don't perform typo correction inside macro arguments. (cherry picked from commit db23cf5f32d1df12624deb4250fd02d61c323cf5) --- lib/Sema/PreCheckExpr.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/Sema/PreCheckExpr.cpp b/lib/Sema/PreCheckExpr.cpp index e270db6a2e799..0fe4d0df8d8d3 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 (!ASTScope::isInMacroArgument(DC->getParentSourceFile(), UDRE->getLoc())) { + TypeChecker::performTypoCorrection(DC, UDRE->getRefKind(), Type(), + lookupOptions, corrections); + } if (auto typo = corrections.claimUniqueCorrection()) { auto diag = Context.Diags.diagnose( From 3f9fc448e0c3e9fdc8e2cb676c11ddfe79e19621 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Sat, 10 Jun 2023 01:42:46 -0700 Subject: [PATCH 08/14] [Macros] Add a test that invokes macro expansion through the conformance checker while type checking a freestanding macro argument in the same scope. (cherry picked from commit f9f63e3aea61e3ae01419427225efee96c982e7d) --- .../Inputs/syntax_macro_definitions.swift | 23 +++++++++++++++++++ test/Macros/top_level_freestanding.swift | 21 +++++++++++++++++ 2 files changed, 44 insertions(+) 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/top_level_freestanding.swift b/test/Macros/top_level_freestanding.swift index 3fd9c07c1d6bd..ed4cc3e51f3b5 100644 --- a/test/Macros/top_level_freestanding.swift +++ b/test/Macros/top_level_freestanding.swift @@ -104,3 +104,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) {} +} From 0ad8532426123fa90c22ec0695b3de84ec7d4796 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Sat, 10 Jun 2023 15:08:29 -0700 Subject: [PATCH 09/14] [Macros] Ban freestanding and peer macro expansions that can produce arbitrary names at global scope. 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. (cherry picked from commit 98249543cd8625d283d94d175636a8d0535d0887) --- include/swift/AST/DiagnosticsSema.def | 4 ++ lib/Sema/TypeCheckMacros.cpp | 47 ++++++++++++++++++++++++ test/Macros/macro_expand_peers.swift | 10 +++++ test/Macros/top_level_freestanding.swift | 4 ++ 4 files changed, 65 insertions(+) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index ac527f467cd73..f691ce744bfb8 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -7102,6 +7102,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/lib/Sema/TypeCheckMacros.cpp b/lib/Sema/TypeCheckMacros.cpp index 2713f1e6e15fb..741e04775af6a 100644 --- a/lib/Sema/TypeCheckMacros.cpp +++ b/lib/Sema/TypeCheckMacros.cpp @@ -1471,6 +1471,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 { @@ -1493,6 +1527,19 @@ ConcreteDeclRef ResolveMacroRequest::evaluate(Evaluator &evaluator, 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/test/Macros/macro_expand_peers.swift b/test/Macros/macro_expand_peers.swift index 3e09274b76755..d05be2c80281e 100644 --- a/test/Macros/macro_expand_peers.swift +++ b/test/Macros/macro_expand_peers.swift @@ -158,6 +158,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 ed4cc3e51f3b5..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 From e4118773d6dd3eee7a8276c6f721022c3cbd5c5f Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Sat, 10 Jun 2023 16:19:01 -0700 Subject: [PATCH 10/14] [ASTScope] Don't consider freestanding macro expansions as being part of a macro argument. (cherry picked from commit 0b91f633492ee4f3c7d3108838a6e301d2d99369) --- lib/AST/ASTScopeLookup.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/AST/ASTScopeLookup.cpp b/lib/AST/ASTScopeLookup.cpp index f7aa0bba5b46c..196051fa1c016 100644 --- a/lib/AST/ASTScopeLookup.cpp +++ b/lib/AST/ASTScopeLookup.cpp @@ -689,6 +689,16 @@ bool ASTScopeImpl::isInMacroArgument(SourceFile *sourceFile, do { if (scope->isMacroArgumentScope()) return true; + + // 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 false; + } while ((scope = scope->getParent().getPtrOrNull())); return false; From 41b3f35a04cc19b72a16524cd27f66a2605ba957 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Sat, 10 Jun 2023 22:07:38 -0700 Subject: [PATCH 11/14] [CodeCompletion] Plumb source locations through code completion name lookup. (cherry picked from commit 706411d2e65d53a8afac800ae5dde28a03f53a52) --- include/swift/AST/NameLookup.h | 2 +- lib/IDE/CompletionLookup.cpp | 19 ++++++++------- lib/IDE/CompletionOverrideLookup.cpp | 2 +- lib/IDE/ConformingMethodList.cpp | 3 ++- lib/IDE/TypeContextInfo.cpp | 3 ++- lib/Sema/LookupVisibleDecls.cpp | 35 ++++++++++++++-------------- lib/Sema/TypeCheckNameLookup.cpp | 2 +- 7 files changed, 35 insertions(+), 31 deletions(-) diff --git a/include/swift/AST/NameLookup.h b/include/swift/AST/NameLookup.h index bc5aea9c1b07b..be86ef988c891 100644 --- a/include/swift/AST/NameLookup.h +++ b/include/swift/AST/NameLookup.h @@ -512,7 +512,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, diff --git a/lib/IDE/CompletionLookup.cpp b/lib/IDE/CompletionLookup.cpp index 4431d861935e3..0aa20a5adb7ed 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/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/Sema/LookupVisibleDecls.cpp b/lib/Sema/LookupVisibleDecls.cpp index 2d723468f1597..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,8 +1188,7 @@ static void lookupVisibleDynamicMemberLookupDecls( { ctx, DeclBaseName::createSubscript(), { ctx.Id_dynamicMember} }); SmallVector subscripts; - dc->lookupQualified(baseType, subscriptName, - baseType->getAnyNominal()->getLoc(), + dc->lookupQualified(baseType, subscriptName, loc, NL_QualifiedDefault | NL_ProtocolMembers, subscripts); for (ValueDecl *VD : subscripts) { @@ -1210,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); } } @@ -1223,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, @@ -1233,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. @@ -1347,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; @@ -1404,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, @@ -1421,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/TypeCheckNameLookup.cpp b/lib/Sema/TypeCheckNameLookup.cpp index 8d1c037b6aee1..4cfc994ab296c 100644 --- a/lib/Sema/TypeCheckNameLookup.cpp +++ b/lib/Sema/TypeCheckNameLookup.cpp @@ -617,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, From 732acad9a80de534fc1a0069913ca4da6169e138 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Sat, 10 Jun 2023 23:37:32 -0700 Subject: [PATCH 12/14] [Parser] Reset ASTScopes before performing the IDEInspection second pass. IDE inspection can delay parsing of particular declarations, so expanding ASTScopes during the first pass will miss those declarations. Clear any expanded scopes to force re-expansion during the second pass. (cherry picked from commit 51e1a39a0c5eb0731360b2037aaec385ec83010b) --- lib/Parse/Parser.cpp | 3 +++ 1 file changed, 3 insertions(+) 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. From 9a3d53191edcb1ab26797e6a0f57de79af7eef2b Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Sun, 11 Jun 2023 19:44:07 -0700 Subject: [PATCH 13/14] [NameLookup] Move macro-related name lookup operations into the namelookup namespace. This moves the `isInMacroArgument` predicate and `lookupMacros` into `namelookup`. ASTScope still encapsulates the scope tree and contains the operation to lookup the enclosing macro scope, which then invokes a callback to determine whether a potential macro scope is indeed a macro, because answering this question requires name lookup. (cherry picked from commit 393b4ceb956f91f02a10c0b671664313a6bb8563) --- include/swift/AST/ASTScope.h | 28 +++++--------- include/swift/AST/NameLookup.h | 27 +++++++++++-- include/swift/AST/TypeCheckRequests.h | 3 ++ lib/AST/ASTScope.cpp | 7 ++-- lib/AST/ASTScopeLookup.cpp | 23 ++++++----- lib/AST/NameLookup.cpp | 56 ++++++++++++++++++++++++++- lib/AST/NameLookupRequests.cpp | 6 +-- lib/Sema/CSGen.cpp | 2 +- lib/Sema/PreCheckExpr.cpp | 2 +- lib/Sema/TypeCheckDecl.cpp | 30 -------------- lib/Sema/TypeCheckMacros.cpp | 2 +- lib/Sema/TypeChecker.h | 3 -- 12 files changed, 115 insertions(+), 74 deletions(-) diff --git a/include/swift/AST/ASTScope.h b/include/swift/AST/ASTScope.h index a8d229e89069b..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,16 +282,9 @@ class ASTScopeImpl : public ASTAllocated { static std::pair lookupFallthroughSourceAndDest(SourceFile *sourceFile, SourceLoc loc); - /// Returns \c true if the given source location is inside an attached - /// or freestanding macro argument. - static bool isInMacroArgument(SourceFile *sourceFile, SourceLoc loc); - - /// Returns \c true if this scope contains macro arguments. - /// - /// This is always true within macro expansion decl scopes, and it's - /// true within custom attribute scopes if the attribute name is a - /// potential macro reference. - virtual bool isMacroArgumentScope() const { return false; } + 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. @@ -879,13 +876,6 @@ class CustomAttributeScope final : public ASTScopeImpl { return attr; } bool ignoreInDebugInfo() const override { return true; } - - bool isMacroArgumentScope() const override { - // FIXME: This should check whether the attribute name is - // a macro. Otherwise, macro expansion will be suppressed - // for property wrapper arguments. - return true; - } private: void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &); @@ -1285,8 +1275,8 @@ class MacroExpansionDeclScope final : public ASTScopeImpl { SourceRange getSourceRangeOfThisASTNode(bool omitAssertions = false) const override; - bool isMacroArgumentScope() const override { - return true; + NullablePtr getFreestandingMacro() const override { + return decl; } protected: diff --git a/include/swift/AST/NameLookup.h b/include/swift/AST/NameLookup.h index be86ef988c891..3d0e838b61d88 100644 --- a/include/swift/AST/NameLookup.h +++ b/include/swift/AST/NameLookup.h @@ -544,6 +544,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. /// @@ -815,9 +824,21 @@ class ASTScope : public ASTAllocated { static std::pair lookupFallthroughSourceAndDest(SourceFile *sourceFile, SourceLoc loc); - /// Returns \c true if the given source location is inside an attached - /// or freestanding macro argument. - static bool isInMacroArgument(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; 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/lib/AST/ASTScope.cpp b/lib/AST/ASTScope.cpp index b9b830aad6cce..aa80e71159bf9 100644 --- a/lib/AST/ASTScope.cpp +++ b/lib/AST/ASTScope.cpp @@ -60,9 +60,10 @@ std::pair ASTScope::lookupFallthroughSourceAndDest( return ASTScopeImpl::lookupFallthroughSourceAndDest(sourceFile, loc); } -bool ASTScope::isInMacroArgument(SourceFile *sourceFile, - SourceLoc loc) { - return ASTScopeImpl::isInMacroArgument(sourceFile, loc); +void ASTScope::lookupEnclosingMacroScope( + SourceFile *sourceFile, SourceLoc loc, + llvm::function_ref body) { + return ASTScopeImpl::lookupEnclosingMacroScope(sourceFile, loc, body); } #if SWIFT_COMPILER_IS_MSVC diff --git a/lib/AST/ASTScopeLookup.cpp b/lib/AST/ASTScopeLookup.cpp index 196051fa1c016..a8168ca096605 100644 --- a/lib/AST/ASTScopeLookup.cpp +++ b/lib/AST/ASTScopeLookup.cpp @@ -676,19 +676,26 @@ std::pair ASTScopeImpl::lookupFallthroughSourceAndDest( return { nullptr, nullptr }; } -bool ASTScopeImpl::isInMacroArgument(SourceFile *sourceFile, - SourceLoc loc) { +void ASTScopeImpl::lookupEnclosingMacroScope( + SourceFile *sourceFile, SourceLoc loc, + llvm::function_ref consume) { if (!sourceFile || sourceFile->Kind == SourceFileKind::Interface) - return false; + return; if (loc.isInvalid()) - return false; + return; auto *fileScope = sourceFile->getScope().impl; auto *scope = fileScope->findInnermostEnclosingScope(loc, nullptr); do { - if (scope->isMacroArgumentScope()) - return true; + 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 @@ -697,9 +704,7 @@ bool ASTScopeImpl::isInMacroArgument(SourceFile *sourceFile, // MacroExpansionDeclScope, and child scopes of freestanding macros // are otherwise inside the macro argument. if (scope->getClassName() == "ASTSourceFileScope") - return false; + return; } while ((scope = scope->getParent().getPtrOrNull())); - - return false; } diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index b032876d369d2..e61f79c205b20 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. /// @@ -2631,7 +2685,7 @@ directReferencesForUnqualifiedTypeLookup(DeclNameRef name, // Manually exclude macro expansions here since the source location // is overridden below. - if (ASTScope::isInMacroArgument(dc->getParentSourceFile(), loc)) + if (namelookup::isInMacroArgument(dc->getParentSourceFile(), loc)) options |= UnqualifiedLookupFlags::ExcludeMacroExpansions; // In a protocol or protocol extension, the 'where' clause can refer to diff --git a/lib/AST/NameLookupRequests.cpp b/lib/AST/NameLookupRequests.cpp index 600a27ba4b283..d934dec0442e6 100644 --- a/lib/AST/NameLookupRequests.cpp +++ b/lib/AST/NameLookupRequests.cpp @@ -545,7 +545,7 @@ static UnqualifiedLookupDescriptor excludeMacrosIfNeeded( UnqualifiedLookupFlags::ExcludeMacroExpansions)) return descriptor; - auto isInMacroArgument = ASTScope::isInMacroArgument( + auto isInMacroArgument = namelookup::isInMacroArgument( descriptor.DC->getParentSourceFile(), descriptor.Loc); if (!isInMacroArgument) @@ -562,7 +562,7 @@ static DirectLookupDescriptor excludeMacrosIfNeeded( NominalTypeDecl::LookupDirectFlags::ExcludeMacroExpansions)) return descriptor; - auto isInMacroArgument = ASTScope::isInMacroArgument( + auto isInMacroArgument = namelookup::isInMacroArgument( descriptor.DC->getParentSourceFile(), loc); if (!isInMacroArgument) @@ -581,7 +581,7 @@ excludeMacrosIfNeeded(const DeclContext *dc, SourceLoc loc, if (options & NL_ExcludeMacroExpansions) return options; - auto isInMacroArgument = ASTScope::isInMacroArgument( + auto isInMacroArgument = namelookup::isInMacroArgument( dc->getParentSourceFile(), loc); if (!isInMacroArgument) diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 1eb5491154c93..926d923922daa 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -3900,7 +3900,7 @@ namespace { FunctionRefKind functionRefKind, MacroRoles roles) { SmallVector choices; - auto results = TypeChecker::lookupMacros( + auto results = namelookup::lookupMacros( CurDC, DeclNameRef(macroName), roles); for (const auto &result : results) { OverloadChoice choice = OverloadChoice(Type(), result, functionRefKind); diff --git a/lib/Sema/PreCheckExpr.cpp b/lib/Sema/PreCheckExpr.cpp index 0fe4d0df8d8d3..08c56383184cf 100644 --- a/lib/Sema/PreCheckExpr.cpp +++ b/lib/Sema/PreCheckExpr.cpp @@ -606,7 +606,7 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, // 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 (!ASTScope::isInMacroArgument(DC->getParentSourceFile(), UDRE->getLoc())) { + if (!namelookup::isInMacroArgument(DC->getParentSourceFile(), UDRE->getLoc())) { TypeChecker::performTypoCorrection(DC, UDRE->getRefKind(), Type(), lookupOptions, corrections); } diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 84142ad5a22d4..fe948f27f5d05 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -1610,36 +1610,6 @@ TypeChecker::lookupPrecedenceGroup(DeclContext *dc, Identifier name, return PrecedenceGroupLookupResult(dc, name, std::move(groups)); } -SmallVector -TypeChecker::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; -} - /// Validate the given operator declaration. /// /// This establishes key invariants, such as an InfixOperatorDecl's diff --git a/lib/Sema/TypeCheckMacros.cpp b/lib/Sema/TypeCheckMacros.cpp index 741e04775af6a..e4e611a5f218a 100644 --- a/lib/Sema/TypeCheckMacros.cpp +++ b/lib/Sema/TypeCheckMacros.cpp @@ -1521,7 +1521,7 @@ 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( + auto foundMacros = namelookup::lookupMacros( dc, macroRef.getMacroName(), roles); if (foundMacros.empty()) return ConcreteDeclRef(); diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index ad8f06703c254..23e5ccf3f3764 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -941,9 +941,6 @@ lookupPrecedenceGroupForInfixOperator(DeclContext *dc, Expr *op, bool diagnose); PrecedenceGroupLookupResult lookupPrecedenceGroup(DeclContext *dc, Identifier name, SourceLoc nameLoc); -SmallVector -lookupMacros(DeclContext *dc, DeclNameRef macroName, MacroRoles contexts); - enum class UnsupportedMemberTypeAccessKind : uint8_t { None, TypeAliasOfUnboundGeneric, From 454bb306e84b0fc2f7a5b585c1f03011ba1c1188 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Sun, 11 Jun 2023 19:57:28 -0700 Subject: [PATCH 14/14] [Evaluator] Remove hasActiveResolveMacroRequest(). (cherry picked from commit 2cc1204afe883939eeda628c773210b6c7267d51) --- include/swift/AST/Evaluator.h | 22 ---------------------- lib/AST/Evaluator.cpp | 5 ----- lib/AST/NameLookupRequests.cpp | 26 ++++++++------------------ 3 files changed, 8 insertions(+), 45 deletions(-) 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/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/NameLookupRequests.cpp b/lib/AST/NameLookupRequests.cpp index d934dec0442e6..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(