From abcdc6c60f2ea456869347da4f3c2698d38528de 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. --- 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 2c0c596d95f9ad967a97d6f77a032ad266f40b36 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. --- 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 cd79cf97d683a7fb711d89cff2ea0bcd447e0d6b 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. --- 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 a4b8a0a3c14f4..baa687e140652 100644 --- a/include/swift/AST/NameLookup.h +++ b/include/swift/AST/NameLookup.h @@ -816,6 +816,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 29430645110307597f6aa1ea0e342ac0dfd4fc45 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. --- 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 c30c94dbc2792..8286a65c3a1ec 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 dd0f7655608e3..f545fa889a86a 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -1611,11 +1611,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 90e00f9fb0c78..a5b1922c2b237 100644 --- a/lib/Sema/TypeCheckMacros.cpp +++ b/lib/Sema/TypeCheckMacros.cpp @@ -1487,7 +1487,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 4cba8b17db863..ae1a548050102 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 cd752cca225174fd8459986273c172fc0c86d2af 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. --- 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 b6b2d8396a46f..8de237d91cd67 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -3899,7 +3899,7 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext { /// protocols to which the nominal type conforms. Furthermore, the resulting /// set of declarations has not been filtered for visibility, nor have /// overridden declarations been removed. - TinyPtrVector lookupDirect(DeclName name, + TinyPtrVector lookupDirect(DeclName name, SourceLoc loc = SourceLoc(), OptionSet flags = OptionSet()); @@ -4454,7 +4454,8 @@ class ClassDecl final : public NominalTypeDecl { // Force loading all the members, which will add this attribute if any of // members are determined to be missing while loading. auto mutableThis = const_cast(this); - (void)mutableThis->lookupDirect(DeclBaseName::createConstructor()); + (void)mutableThis->lookupDirect(DeclBaseName::createConstructor(), + getStartLoc()); } if (Bits.ClassDecl.ComputedHasMissingDesignatedInitializers) diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h index d6e21e3167959..8de5bd8494950 100644 --- a/include/swift/AST/DeclContext.h +++ b/include/swift/AST/DeclContext.h @@ -598,7 +598,8 @@ class alignas(1 << DeclContextAlignInBits) DeclContext /// lookup. /// /// \returns true if anything was found. - bool lookupQualified(Type type, DeclNameRef member, NLOptions options, + bool lookupQualified(Type type, DeclNameRef member, + SourceLoc loc, NLOptions options, SmallVectorImpl &decls) const; /// Look for the set of declarations with the given name within the @@ -616,12 +617,12 @@ class alignas(1 << DeclContextAlignInBits) DeclContext /// /// \returns true if anything was found. bool lookupQualified(ArrayRef types, DeclNameRef member, - NLOptions options, + SourceLoc loc, NLOptions options, SmallVectorImpl &decls) const; /// Perform qualified lookup for the given member in the given module. bool lookupQualified(ModuleDecl *module, DeclNameRef member, - NLOptions options, + SourceLoc loc, NLOptions options, SmallVectorImpl &decls) const; /// Look up all Objective-C methods with the given selector visible diff --git a/include/swift/AST/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 39fe9d7dc2a3b..7aa1c47ee83a5 100644 --- a/include/swift/AST/NameLookupRequests.h +++ b/include/swift/AST/NameLookupRequests.h @@ -461,7 +461,7 @@ class LookupInModuleRequest LookupInModuleRequest( const DeclContext *, DeclName, NLKind, namelookup::ResolutionKind, const DeclContext *, - NLOptions); + SourceLoc, NLOptions); private: friend SimpleRequest; @@ -511,7 +511,7 @@ class ModuleQualifiedLookupRequest public: ModuleQualifiedLookupRequest(const DeclContext *, ModuleDecl *, DeclNameRef, - NLOptions); + SourceLoc, NLOptions); private: friend SimpleRequest; @@ -537,7 +537,7 @@ class QualifiedLookupRequest public: QualifiedLookupRequest(const DeclContext *, SmallVector, - DeclNameRef, NLOptions); + DeclNameRef, SourceLoc, NLOptions); private: friend SimpleRequest; @@ -588,7 +588,7 @@ class DirectLookupRequest TinyPtrVector(DirectLookupDescriptor), RequestFlags::Uncached|RequestFlags::DependencySink> { public: - DirectLookupRequest(DirectLookupDescriptor); + DirectLookupRequest(DirectLookupDescriptor, SourceLoc); private: friend SimpleRequest; diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 6d6bb23a2712c..e003098aa03ab 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -2910,7 +2910,8 @@ class ConstraintSystem { /// and no new names are introduced after that point. /// /// \returns A reference to the member-lookup result. - LookupResult &lookupMember(Type base, DeclNameRef name); + LookupResult &lookupMember(Type base, DeclNameRef name, + SourceLoc loc); /// Retrieve the set of "alternative" literal types that we'll explore /// for a given literal protocol kind. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 00bd291f3a025..93c8f0f0959e4 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1072,8 +1072,8 @@ DECLTYPE *ASTContext::get##NAME##Decl() const { \ /* Note: lookupQualified() will search both the Swift overlay \ * and the Clang module it imports. */ \ SmallVector decls; \ - M->lookupQualified(M, DeclNameRef(getIdentifier(#NAME)), NL_OnlyTypes, \ - decls); \ + M->lookupQualified(M, DeclNameRef(getIdentifier(#NAME)), SourceLoc(), \ + NL_OnlyTypes, decls); \ if (decls.size() == 1 && isa(decls[0])) { \ auto decl = cast(decls[0]); \ if (isa(decl) \ @@ -1336,7 +1336,8 @@ ConcreteDeclRef ASTContext::getRegexInitDecl(Type regexType) const { {Id_regexString, Id_version}); SmallVector results; spModule->lookupQualified(getRegexType(), DeclNameRef(name), - NL_IncludeUsableFromInline, results); + SourceLoc(), NL_IncludeUsableFromInline, + results); assert(results.size() == 1); auto *foundDecl = cast(results[0]); auto subs = regexType->getMemberSubstitutionMap(spModule, foundDecl); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 14d6a9c2849fe..eb62453ce060b 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -5395,7 +5395,7 @@ NominalTypeDecl::getExecutorOwnedEnqueueFunction() const { llvm::SmallVector results; lookupQualified(getSelfNominalTypeDecl(), DeclNameRef(C.Id_enqueue), - NL_ProtocolMembers, + getLoc(), NL_ProtocolMembers, results); for (auto candidate: results) { @@ -5434,7 +5434,7 @@ NominalTypeDecl::getExecutorLegacyOwnedEnqueueFunction() const { llvm::SmallVector results; lookupQualified(getSelfNominalTypeDecl(), DeclNameRef(C.Id_enqueue), - NL_ProtocolMembers, + getLoc(), NL_ProtocolMembers, results); for (auto candidate: results) { @@ -5473,7 +5473,7 @@ NominalTypeDecl::getExecutorLegacyUnownedEnqueueFunction() const { llvm::SmallVector results; lookupQualified(getSelfNominalTypeDecl(), DeclNameRef(C.Id_enqueue), - NL_ProtocolMembers, + getLoc(), NL_ProtocolMembers, results); for (auto candidate: results) { @@ -9927,7 +9927,7 @@ const VarDecl *ClassDecl::getUnownedExecutorProperty() const { llvm::SmallVector results; this->lookupQualified(getSelfNominalTypeDecl(), DeclNameRef(C.Id_unownedExecutor), - NL_ProtocolMembers, + getLoc(), NL_ProtocolMembers, results); for (auto candidate: results) { diff --git a/lib/AST/DocComment.cpp b/lib/AST/DocComment.cpp index 96bf365ef8745..5c73b29a42959 100644 --- a/lib/AST/DocComment.cpp +++ b/lib/AST/DocComment.cpp @@ -435,7 +435,8 @@ class CommentProviderFinder final { SmallVector members; protocol->lookupQualified(const_cast(protocol), DeclNameRef(VD->getName()), - NLOptions::NL_ProtocolMembers, members); + VD->getLoc(), NLOptions::NL_ProtocolMembers, + members); Optional result; for (auto *member : members) { diff --git a/lib/AST/ModuleNameLookup.cpp b/lib/AST/ModuleNameLookup.cpp index 10ea32c053c17..98ae1381690ce 100644 --- a/lib/AST/ModuleNameLookup.cpp +++ b/lib/AST/ModuleNameLookup.cpp @@ -281,10 +281,10 @@ void namelookup::lookupInModule(const DeclContext *moduleOrFile, NLKind lookupKind, ResolutionKind resolutionKind, const DeclContext *moduleScopeContext, - NLOptions options) { + SourceLoc loc, NLOptions options) { auto &ctx = moduleOrFile->getASTContext(); LookupInModuleRequest req(moduleOrFile, name, lookupKind, resolutionKind, - moduleScopeContext, options); + moduleScopeContext, loc, options); auto results = evaluateOrDefault(ctx.evaluator, req, {}); decls.append(results.begin(), results.end()); } diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index 77e029d8e3199..66c3bd8a97657 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; @@ -3552,7 +3566,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 d7d3527a6c7a0..88d2a9a93dd3e 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -6532,7 +6532,7 @@ void SwiftDeclConverter::recordObjCOverride(AbstractFunctionDecl *decl) { // Dig out the Objective-C superclass. SmallVector results; superDecl->lookupQualified(superDecl, DeclNameRef(decl->getName()), - NL_QualifiedDefault, + decl->getLoc(), NL_QualifiedDefault, results); for (auto member : results) { if (member->getKind() != decl->getKind() || @@ -6605,7 +6605,7 @@ void SwiftDeclConverter::recordObjCOverride(SubscriptDecl *subscript) { SmallVector lookup; subscript->getModuleContext()->lookupQualified( superDecl, DeclNameRef(subscript->getName()), - NL_QualifiedDefault, lookup); + subscript->getLoc(), NL_QualifiedDefault, lookup); for (auto result : lookup) { auto parentSub = dyn_cast(result); @@ -8292,7 +8292,8 @@ static void finishTypeWitnesses( NL_OnlyTypes | NL_ProtocolMembers); - dc->lookupQualified(nominal, DeclNameRef(assocType->getName()), options, + dc->lookupQualified(nominal, DeclNameRef(assocType->getName()), + nominal->getLoc(), options, lookupResults); for (auto member : lookupResults) { auto typeDecl = cast(member); diff --git a/lib/Frontend/ModuleInterfaceSupport.cpp b/lib/Frontend/ModuleInterfaceSupport.cpp index ee08b89e508c3..3a01ee45af93c 100644 --- a/lib/Frontend/ModuleInterfaceSupport.cpp +++ b/lib/Frontend/ModuleInterfaceSupport.cpp @@ -181,7 +181,7 @@ diagnoseIfModuleImportsShadowingDecl(ModuleInterfaceOptions const &Opts, SmallVector decls; lookupInModule(importedModule, importingModule->getName(), decls, NLKind::UnqualifiedLookup, ResolutionKind::TypesOnly, - importedModule, + importedModule, SourceLoc(), NL_UnqualifiedDefault | NL_IncludeUsableFromInline); for (auto decl : decls) diagnoseDeclShadowsModule(Opts, cast(decl), importingModule, diff --git a/lib/IDE/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 4afc45feb516f..cfe743ad3c3ec 100644 --- a/lib/SIL/IR/SILFunctionType.cpp +++ b/lib/SIL/IR/SILFunctionType.cpp @@ -1058,7 +1058,7 @@ static CanType getKnownType(Optional &cacheSlot, ASTContext &C, // themselves. SmallVector decls; mod->lookupQualified(mod, DeclNameRef(C.getIdentifier(typeName)), - NL_QualifiedDefault, decls); + SourceLoc(), NL_QualifiedDefault, decls); if (decls.size() != 1) return CanType(); diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index 996d654321465..c70a797ceadc9 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -371,7 +371,7 @@ static FuncDecl *lookupIntrinsic(ModuleDecl &module, return *cache; SmallVector decls; - module.lookupQualified(&module, DeclNameRef(name), + module.lookupQualified(&module, DeclNameRef(name), SourceLoc(), NL_QualifiedDefault | NL_IncludeUsableFromInline, decls); if (decls.size() != 1) { diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp index 6c04a9f890a5e..90d3014bd6109 100644 --- a/lib/SILGen/SILGenFunction.cpp +++ b/lib/SILGen/SILGenFunction.cpp @@ -1092,7 +1092,7 @@ void SILGenFunction::emitArtificialTopLevel(Decl *mainDecl) { SmallVector results; UIKit->lookupQualified(UIKit, DeclNameRef(ctx.getIdentifier("UIApplicationMain")), - NL_QualifiedDefault, + SourceLoc(), NL_QualifiedDefault, results); // As the comment above alludes, using a qualified lookup into UIKit is diff --git a/lib/Sema/BuilderTransform.cpp b/lib/Sema/BuilderTransform.cpp index b6ae98679227c..78a9739cd694e 100644 --- a/lib/Sema/BuilderTransform.cpp +++ b/lib/Sema/BuilderTransform.cpp @@ -1379,6 +1379,7 @@ ResultBuilderOpSupport TypeChecker::checkBuilderOpSupport( SmallVector foundDecls; dc->lookupQualified( builderType, DeclNameRef(fnName), + builderType->getAnyNominal()->getLoc(), NL_QualifiedDefault | NL_ProtocolMembers, foundDecls); for (auto decl : foundDecls) { if (auto func = dyn_cast(decl)) { diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index c2ed909db3352..196217cb62aac 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -2104,7 +2104,8 @@ bool AssignmentFailure::diagnoseAsError() { if (auto typeContext = DC->getInnermostTypeContext()) { SmallVector results; DC->lookupQualified(typeContext->getSelfNominalTypeDecl(), - VD->createNameRef(), NL_QualifiedDefault, results); + VD->createNameRef(), Loc, + NL_QualifiedDefault, results); auto foundProperty = llvm::find_if(results, [&](ValueDecl *decl) { // We're looking for a settable property that is the same type as the diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index da48e9cd8286a..77d02761259a9 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -9307,6 +9307,9 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, Type baseObjTy = baseTy->getRValueType(); Type instanceTy = baseObjTy; + auto memberNode = simplifyLocatorToAnchor(memberLocator); + auto memberLoc = memberNode ? memberNode.getStartLoc() : SourceLoc(); + if (auto baseObjMeta = baseObjTy->getAs()) { instanceTy = baseObjMeta->getInstanceType(); } @@ -9419,7 +9422,7 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, } // Look for members within the base. - LookupResult &lookup = lookupMember(instanceTy, lookupName); + LookupResult &lookup = lookupMember(instanceTy, lookupName, memberLoc); // If this is true, we're using type construction syntax (Foo()) rather // than an explicit call to `init` (Foo.init()). @@ -9819,7 +9822,8 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, memberName.getBaseName() == DeclBaseName::createConstructor() && !isImplicitInit) { auto &compatLookup = lookupMember(instanceTy, - DeclNameRef(ctx.getIdentifier("init"))); + DeclNameRef(ctx.getIdentifier("init")), + memberLoc); for (auto result : compatLookup) addChoice(getOverloadChoice(result.getValueDecl(), /*isBridged=*/false, @@ -9829,7 +9833,8 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, // If the instance type is a bridged to an Objective-C type, perform // a lookup into that Objective-C type. if (bridgedType) { - LookupResult &bridgedLookup = lookupMember(bridgedType, memberName); + LookupResult &bridgedLookup = lookupMember(bridgedType, memberName, + memberLoc); ModuleDecl *foundationModule = nullptr; for (auto result : bridgedLookup) { // Ignore results from the Objective-C "Foundation" @@ -9892,7 +9897,8 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, // prioritize them and mark any results found on wrapped type // as a fallback results. bool isFallback = !result.ViableCandidates.empty(); - LookupResult &optionalLookup = lookupMember(objectType, memberName); + LookupResult &optionalLookup = lookupMember(objectType, memberName, + memberLoc); for (auto result : optionalLookup) addChoice(getOverloadChoice(result.getValueDecl(), /*bridged*/ false, @@ -9960,7 +9966,8 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName, lookupOptions |= NameLookupFlags::IgnoreAccessControl; auto lookup = - TypeChecker::lookupMember(DC, instanceTy, memberName, lookupOptions); + TypeChecker::lookupMember(DC, instanceTy, memberName, + memberLoc, lookupOptions); for (auto entry : lookup) { auto *cand = entry.getValueDecl(); diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index 26e6a088d0cea..30bf38a0771f4 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -1014,6 +1014,7 @@ static void collectNonOveriddenSuperclassInits( SmallVector lookupResults; subclass->lookupQualified( superclassDecl, DeclNameRef::createConstructor(), + subclass->getStartLoc(), subOptions, lookupResults); for (auto decl : lookupResults) { diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 10563c1fe10f8..632c9ef72690b 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -279,13 +279,15 @@ getDynamicResultSignature(ValueDecl *decl) { llvm_unreachable("Not a valid @objc member"); } -LookupResult &ConstraintSystem::lookupMember(Type base, DeclNameRef name) { +LookupResult &ConstraintSystem::lookupMember(Type base, DeclNameRef name, + SourceLoc loc) { // Check whether we've already performed this lookup. auto &result = MemberLookups[{base, name}]; if (result) return *result; // Lookup the member. - result = TypeChecker::lookupMember(DC, base, name, defaultMemberLookupOptions); + result = TypeChecker::lookupMember(DC, base, name, loc, + defaultMemberLookupOptions); // If we aren't performing dynamic lookup, we're done. if (!*result || !base->isAnyObject()) diff --git a/lib/Sema/ImportResolution.cpp b/lib/Sema/ImportResolution.cpp index 520ae263b6a09..5661c3a20ebc2 100644 --- a/lib/Sema/ImportResolution.cpp +++ b/lib/Sema/ImportResolution.cpp @@ -1135,7 +1135,7 @@ ScopedImportLookupRequest::evaluate(Evaluator &evaluator, lookupInModule(topLevelModule, accessPath.front().Item, decls, NLKind::QualifiedLookup, ResolutionKind::Overloadable, import->getDeclContext()->getModuleScopeContext(), - NL_QualifiedDefault); + import->getLoc(), NL_QualifiedDefault); auto importLoc = import->getLoc(); if (decls.empty()) { diff --git a/lib/Sema/LookupVisibleDecls.cpp b/lib/Sema/LookupVisibleDecls.cpp index c089f6767ad2e..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 4b17e5bfb1859..0c144273096c6 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -4332,7 +4332,8 @@ class ObjCSelectorWalker : public ASTWalker { auto nominal = method->getDeclContext()->getSelfNominalTypeDecl(); auto result = TypeChecker::lookupMember( const_cast(DC), nominal->getDeclaredInterfaceType(), - DeclNameRef(lookupName), defaultMemberLookupOptions); + DeclNameRef(lookupName), method->getLoc(), + defaultMemberLookupOptions); // If we didn't find multiple methods, there is no ambiguity. if (result.size() < 2) return false; diff --git a/lib/Sema/PreCheckExpr.cpp b/lib/Sema/PreCheckExpr.cpp index f634cdf72cdaa..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 ae66572e3f267..9d1d99b2b2114 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -2328,7 +2328,8 @@ void AttributeChecker::checkApplicationMainAttribute(DeclAttribute *attr, namelookup::lookupInModule(KitModule, Id_ApplicationDelegate, decls, NLKind::QualifiedLookup, namelookup::ResolutionKind::TypesOnly, - SF, NL_QualifiedDefault); + SF, attr->getLocation(), + NL_QualifiedDefault); if (decls.size() == 1) ApplicationDelegateProto = dyn_cast(decls[0]); } @@ -3047,7 +3048,8 @@ static void lookupReplacedDecl(DeclNameRef replacedDeclName, options |= NL_IncludeUsableFromInline; if (typeCtx) - moduleScopeCtxt->lookupQualified({typeCtx}, replacedDeclName, options, + moduleScopeCtxt->lookupQualified({typeCtx}, replacedDeclName, + attr->getLocation(), options, results); } @@ -4057,11 +4059,12 @@ void AttributeChecker::visitResultBuilderAttr(ResultBuilderAttr *attr) { auto builderType = nominal->getDeclaredType(); nominal->lookupQualified(builderType, DeclNameRef(buildPartialBlockFirst), - NL_QualifiedDefault, + attr->getLocation(), NL_QualifiedDefault, buildPartialBlockFirstMatches); nominal->lookupQualified( builderType, DeclNameRef(buildPartialBlockAccumulated), - NL_QualifiedDefault, buildPartialBlockAccumulatedMatches); + attr->getLocation(), NL_QualifiedDefault, + buildPartialBlockAccumulatedMatches); hasAccessibleBuildPartialBlockFirst = llvm::any_of( buildPartialBlockFirstMatches, isBuildMethodAsAccessibleAsType); @@ -7267,7 +7270,8 @@ ValueDecl *RenamedDeclRequest::evaluate(Evaluator &evaluator, SmallVector lookupResults; attachedContext->lookupQualified(attachedContext->getParentModule(), nameRef.withoutArgumentLabels(), - NL_OnlyTypes, lookupResults); + attr->getLocation(), NL_OnlyTypes, + lookupResults); if (lookupResults.size() == 1) return lookupResults[0]; return nullptr; diff --git a/lib/Sema/TypeCheckCodeCompletion.cpp b/lib/Sema/TypeCheckCodeCompletion.cpp index 58acb0c1e1965..9076c7b7f7aef 100644 --- a/lib/Sema/TypeCheckCodeCompletion.cpp +++ b/lib/Sema/TypeCheckCodeCompletion.cpp @@ -767,6 +767,7 @@ bool swift::typeCheckExpression(DeclContext *DC, Expr *&parsedExpr) { LookupResult swift::lookupSemanticMember(DeclContext *DC, Type ty, DeclName name) { - return TypeChecker::lookupMember(DC, ty, DeclNameRef(name), None); + return TypeChecker::lookupMember(DC, ty, DeclNameRef(name), + SourceLoc(), None); } diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index eb566bcde9a3c..4501c282578be 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -266,7 +266,8 @@ VarDecl *GlobalActorInstanceRequest::evaluate( // conformance to the 'GlobalActor' protocol. SmallVector decls; nominal->lookupQualified( - nominal, DeclNameRef(ctx.Id_shared), NL_QualifiedDefault, decls); + nominal, DeclNameRef(ctx.Id_shared), + nominal->getLoc(), NL_QualifiedDefault, decls); for (auto decl : decls) { auto var = dyn_cast(decl); if (!var) diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index f545fa889a86a..0d039346f9589 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 d4aff7bc2bffc..1ff5390225d7f 100644 --- a/lib/Sema/TypeCheckDeclOverride.cpp +++ b/lib/Sema/TypeCheckDeclOverride.cpp @@ -928,7 +928,7 @@ SmallVector OverrideMatcher::match( ctx->synthesizeSemanticMembersIfNeeded(membersName); } dc->lookupQualified(superContexts, DeclNameRef(membersName), - NL_QualifiedDefault, members); + decl->getLoc(), NL_QualifiedDefault, members); } // Check each member we found. diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index a0ecff79ba60c..7b3283e5b959c 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -1412,6 +1412,7 @@ static void diagnoseClassWithoutInitializers(ClassDecl *classDecl) { { C, DeclBaseName::createConstructor(), { C.Id_from } }); auto result = TypeChecker::lookupMember(superclassDecl, superclassType, initFrom, + classDecl->getLoc(), NameLookupFlags::IgnoreAccessControl); if (!result.empty() && !result.front().getValueDecl()->isImplicit()) diff --git a/lib/Sema/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 69260e9a0975e..eafc5638c7c13 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -142,7 +142,7 @@ lookupEnumMemberElement(DeclContext *DC, Type ty, // FIXME: We should be able to tell if this is a private lookup. NameLookupOptions lookupOptions = defaultMemberLookupOptions; LookupResult foundElements = - TypeChecker::lookupMember(DC, ty, name, lookupOptions); + TypeChecker::lookupMember(DC, ty, name, UseLoc, lookupOptions); return filterForEnumElement(DC, UseLoc, /*unqualifiedLookup=*/false, foundElements); } diff --git a/lib/Sema/TypeCheckPropertyWrapper.cpp b/lib/Sema/TypeCheckPropertyWrapper.cpp index 8e0717021ef52..8419c276f9d57 100644 --- a/lib/Sema/TypeCheckPropertyWrapper.cpp +++ b/lib/Sema/TypeCheckPropertyWrapper.cpp @@ -38,7 +38,9 @@ static VarDecl *findValueProperty(ASTContext &ctx, NominalTypeDecl *nominal, SmallVector vars; { SmallVector decls; - nominal->lookupQualified(nominal, DeclNameRef(name), NL_QualifiedDefault, + nominal->lookupQualified(nominal, DeclNameRef(name), + nominal->getStartLoc(), + NL_QualifiedDefault, decls); for (const auto &foundDecl : decls) { auto foundVar = dyn_cast(foundDecl); @@ -348,6 +350,7 @@ PropertyWrapperTypeInfoRequest::evaluate( SmallVector decls; nominal->lookupQualified(nominal, DeclNameRef::createConstructor(), + nominal->getStartLoc(), NL_QualifiedDefault, decls); PropertyWrapperTypeInfo result; diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index e8197806b3d10..a2580fe9c680e 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -1306,7 +1306,8 @@ WitnessChecker::lookupValueWitnessesViaImplementsAttr( nominal->synthesizeSemanticMembersIfNeeded(name.getFullName()); SmallVector lookupResults; - DC->lookupQualified(nominal, name, subOptions, lookupResults); + DC->lookupQualified(nominal, name, nominal->getLoc(), + subOptions, lookupResults); for (auto decl : lookupResults) { if (!isa(decl->getDeclContext())) @@ -1387,7 +1388,8 @@ WitnessChecker::lookupValueWitnesses(ValueDecl *req, bool *ignoringNames) { SmallVector lookupResults; bool addedAny = false; - DC->lookupQualified(nominal, reqName, options, lookupResults); + DC->lookupQualified(nominal, reqName, nominal->getLoc(), + options, lookupResults); for (auto *decl : lookupResults) { if (!isa(decl->getDeclContext())) { witnesses.push_back(decl); @@ -1399,7 +1401,8 @@ WitnessChecker::lookupValueWitnesses(ValueDecl *req, bool *ignoringNames) { // again using only the base name. if (!addedAny && ignoringNames) { lookupResults.clear(); - DC->lookupQualified(nominal, reqBaseName, options, lookupResults); + DC->lookupQualified(nominal, reqBaseName, nominal->getLoc(), + options, lookupResults); for (auto *decl : lookupResults) { if (!isa(decl->getDeclContext())) witnesses.push_back(decl); @@ -4754,6 +4757,7 @@ ResolveWitnessResult ConformanceChecker::resolveTypeWitnessViaLookup( DC->lookupQualified(DC->getSelfNominalTypeDecl(), assocType->createNameRef(), + DC->getSelfNominalTypeDecl()->getLoc(), subOptions, candidates); // If there aren't any candidates, we're done. @@ -6331,7 +6335,8 @@ diagnoseMissingAppendInterpolationMethod(NominalTypeDecl *typeDecl) { DeclNameRef baseName(typeDecl->getASTContext().Id_appendInterpolation); SmallVector lookupResults; - typeDecl->lookupQualified(typeDecl, baseName, subOptions, lookupResults); + typeDecl->lookupQualified(typeDecl, baseName, typeDecl->getLoc(), + subOptions, lookupResults); for (auto decl : lookupResults) { auto method = dyn_cast(decl); if (!method) continue; @@ -7202,6 +7207,7 @@ void TypeChecker::inferDefaultWitnesses(ProtocolDecl *proto) { SmallVector found; module->lookupQualified( proto, DeclNameRef(assocType->getName()), + proto->getLoc(), NL_QualifiedDefault|NL_ProtocolMembers|NL_OnlyTypes, found); if (found.size() == 1 && isa(found[0])) diff --git a/lib/Sema/TypeCheckProtocolInference.cpp b/lib/Sema/TypeCheckProtocolInference.cpp index 89fdacaa6b247..830d1aed3df7a 100644 --- a/lib/Sema/TypeCheckProtocolInference.cpp +++ b/lib/Sema/TypeCheckProtocolInference.cpp @@ -594,6 +594,7 @@ AssociatedTypeInference::inferTypeWitnessesViaAssociatedType( // @_implements attributes. SmallVector lookupResults; dc->lookupQualified(adoptee->getAnyNominal(), defaultName, + adoptee->getAnyNominal()->getStartLoc(), subOptions, lookupResults); InferredAssociatedTypesByWitnesses result; diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 6acbee696995c..ae0b89651947f 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -2180,6 +2180,7 @@ static bool checkSuperInit(ConstructorDecl *fromCtor, SmallVector lookupResults; fromCtor->lookupQualified(superclassDecl, DeclNameRef::createConstructor(), + apply->getLoc(), subOptions, lookupResults); for (auto decl : lookupResults) { diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index c448f4dd90103..979654b18cc1b 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -2730,10 +2730,10 @@ static VarDecl *synthesizePropertyWrapperProjectionVar( auto dc = var->getDeclContext(); if (dc->isTypeContext()) { dc->lookupQualified(dc->getSelfNominalTypeDecl(), projectionName, - NL_QualifiedDefault, declsFound); + var->getLoc(), NL_QualifiedDefault, declsFound); } else if (dc->isModuleScopeContext()) { dc->lookupQualified(dc->getParentModule(), projectionName, - NL_QualifiedDefault, declsFound); + var->getLoc(), NL_QualifiedDefault, declsFound); } else { llvm_unreachable("Property wrappers don't work in local contexts"); } diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 6926bef6593d0..ef53dab93a395 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -1412,7 +1412,8 @@ static Type diagnoseUnknownType(TypeResolution resolution, NameLookupOptions relookupOptions = lookupOptions; relookupOptions |= NameLookupFlags::IgnoreAccessControl; auto inaccessibleMembers = TypeChecker::lookupMemberType( - dc, parentType, repr->getNameRef(), relookupOptions); + dc, parentType, repr->getNameRef(), + repr->getLoc(), relookupOptions); if (inaccessibleMembers) { // FIXME: What if the unviable candidates have different levels of access? const TypeDecl *first = inaccessibleMembers.front().Member; @@ -1443,8 +1444,8 @@ static Type diagnoseUnknownType(TypeResolution resolution, NLOptions memberLookupOptions = (NL_QualifiedDefault | NL_IgnoreAccessControl); SmallVector results; - dc->lookupQualified(parentType, repr->getNameRef(), memberLookupOptions, - results); + dc->lookupQualified(parentType, repr->getNameRef(), repr->getLoc(), + memberLookupOptions, results); // Looks like this is not a member type, but simply a member of parent type. if (!results.empty()) { @@ -1834,7 +1835,7 @@ static Type resolveQualifiedIdentTypeRepr(TypeResolution resolution, LookupTypeResult memberTypes; if (parentTy->mayHaveMembers()) memberTypes = TypeChecker::lookupMemberType( - DC, parentTy, repr->getNameRef(), lookupOptions); + DC, parentTy, repr->getNameRef(), repr->getLoc(), lookupOptions); // Name lookup was ambiguous. Complain. // FIXME: Could try to apply generic arguments first, and see whether diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index ae1a548050102..7fe330049c3b4 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 21f3f0bcc34a4..b07da21d476c2 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -1926,7 +1926,7 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) { getIdentifier(privateDiscriminator)); } else { baseModule->lookupQualified(baseModule, DeclNameRef(name), - NL_QualifiedDefault, + SourceLoc(), NL_QualifiedDefault, values); } filterValues(filterTy, nullptr, nullptr, isType, inProtocolExt, @@ -2113,7 +2113,7 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) { getIdentifier(privateDiscriminator)); } else { otherModule->lookupQualified(otherModule, DeclNameRef(name), - NL_QualifiedDefault, + SourceLoc(), NL_QualifiedDefault, values); } diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp index 4e7bc7a429dce..98e7cf39b4641 100644 --- a/lib/Serialization/ModuleFile.cpp +++ b/lib/Serialization/ModuleFile.cpp @@ -560,7 +560,7 @@ void ModuleFile::getImportDecls(SmallVectorImpl &Results) { SmallVector Decls; TopLevelModule->lookupQualified( TopLevelModule, DeclNameRef(ScopeID), - NL_QualifiedDefault, Decls); + SourceLoc(), NL_QualifiedDefault, Decls); Optional FoundKind = ImportDecl::findBestImportKind(Decls); assert(FoundKind.has_value() && "deserialized imports should not be ambiguous"); diff --git a/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 61c99ccd1a12232d230305ce2f530d536a6c6948 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. --- 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 db23cf5f32d1df12624deb4250fd02d61c323cf5 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. --- 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 f9f63e3aea61e3ae01419427225efee96c982e7d 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. --- .../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 98249543cd8625d283d94d175636a8d0535d0887 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. --- 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 97e2fb51b35a8..dee6d8918c7b3 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -7188,6 +7188,10 @@ ERROR(macro_accessor_missing_from_expansion,none, ERROR(macro_init_accessor_not_documented,none, "expansion of macro %0 produced an unexpected 'init' accessor", (DeclName)) +ERROR(global_arbitrary_name,none, + "'%0' macros are not allowed to introduce arbitrary names " + "at global scope", + (StringRef)) ERROR(macro_resolve_circular_reference, none, "circular reference resolving %select{freestanding|attached}0 macro %1", diff --git a/lib/Sema/TypeCheckMacros.cpp b/lib/Sema/TypeCheckMacros.cpp index a5b1922c2b237..00be8a294574a 100644 --- a/lib/Sema/TypeCheckMacros.cpp +++ b/lib/Sema/TypeCheckMacros.cpp @@ -1470,6 +1470,40 @@ swift::expandConformances(CustomAttr *attr, MacroDecl *macro, return macroSourceFile->getBufferID(); } +/// Emits an error and returns \c true if the maro reference may +/// introduce arbitrary names at global scope. +static bool diagnoseArbitraryGlobalNames(DeclContext *dc, + UnresolvedMacroReference macroRef, + MacroRole macroRole) { + auto &ctx = dc->getASTContext(); + assert(macroRole == MacroRole::Declaration || + macroRole == MacroRole::Peer); + + if (!dc->isModuleScopeContext()) + return false; + + bool isInvalid = false; + namelookup::forEachPotentialResolvedMacro( + dc, macroRef.getMacroName(), macroRole, + [&](MacroDecl *decl, const MacroRoleAttr *attr) { + if (!isInvalid && + attr->hasNameKind(MacroIntroducedDeclNameKind::Arbitrary)) { + ctx.Diags.diagnose(macroRef.getSigilLoc(), + diag::global_arbitrary_name, + getMacroRoleString(macroRole)); + isInvalid = true; + + // If this is an attached macro, mark the attribute as invalid + // to avoid diagnosing an unknown attribute later. + if (auto *attr = macroRef.getAttr()) { + attr->setInvalid(); + } + } + }); + + return isInvalid; +} + ConcreteDeclRef ResolveMacroRequest::evaluate(Evaluator &evaluator, UnresolvedMacroReference macroRef, DeclContext *dc) const { @@ -1492,6 +1526,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 1f469a088a814..304c621f186fa 100644 --- a/test/Macros/macro_expand_peers.swift +++ b/test/Macros/macro_expand_peers.swift @@ -162,6 +162,16 @@ struct S2 { #endif } +#if TEST_DIAGNOSTICS +// Peer macros cannot introduce arbitrary names at global scope + +//expected-error@+1 {{'peer' macros are not allowed to introduce arbitrary names at global scope}} +@addCompletionHandlerArbitrarily(x) +func h(a: Int, for b: String, _ value: Double) async -> String { + return b +} +#endif + // Stored properties generated by a peer macro @attached(accessor) @attached(peer, names: prefixed(_)) diff --git a/test/Macros/top_level_freestanding.swift b/test/Macros/top_level_freestanding.swift index 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 0b91f633492ee4f3c7d3108838a6e301d2d99369 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. --- 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 706411d2e65d53a8afac800ae5dde28a03f53a52 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. --- 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 baa687e140652..51aea7c64db31 100644 --- a/include/swift/AST/NameLookup.h +++ b/include/swift/AST/NameLookup.h @@ -513,7 +513,7 @@ void lookupVisibleDecls(VisibleDeclConsumer &Consumer, /// /// \param CurrDC the DeclContext from which the lookup is done. void lookupVisibleMemberDecls(VisibleDeclConsumer &Consumer, - Type BaseTy, + Type BaseTy, SourceLoc loc, const DeclContext *CurrDC, bool includeInstanceMembers, bool includeDerivedRequirements, diff --git a/lib/IDE/CompletionLookup.cpp b/lib/IDE/CompletionLookup.cpp index b697641afeba4..33f99cc19b0aa 100644 --- a/lib/IDE/CompletionLookup.cpp +++ b/lib/IDE/CompletionLookup.cpp @@ -2262,7 +2262,7 @@ bool CompletionLookup::tryUnwrappedCompletions(Type ExprType, bool isIUO) { // unforced IUO. if (isIUO) { if (Type Unwrapped = ExprType->getOptionalObjectType()) { - lookupVisibleMemberDecls(*this, Unwrapped, CurrDeclContext, + lookupVisibleMemberDecls(*this, Unwrapped, DotLoc, CurrDeclContext, IncludeInstanceMembers, /*includeDerivedRequirements*/ false, /*includeProtocolExtensionMembers*/ true); @@ -2289,7 +2289,8 @@ bool CompletionLookup::tryUnwrappedCompletions(Type ExprType, bool isIUO) { if (NumBytesToEraseForOptionalUnwrap <= CodeCompletionResult::MaxNumBytesToErase) { if (!tryTupleExprCompletions(Unwrapped)) { - lookupVisibleMemberDecls(*this, Unwrapped, CurrDeclContext, + lookupVisibleMemberDecls(*this, Unwrapped, DotLoc, + CurrDeclContext, IncludeInstanceMembers, /*includeDerivedRequirements*/ false, /*includeProtocolExtensionMembers*/ true); @@ -2370,7 +2371,7 @@ void CompletionLookup::getValueExprCompletions(Type ExprType, ValueDecl *VD) { // Don't check/return so we still add the members of Optional itself below tryUnwrappedCompletions(ExprType, isIUO); - lookupVisibleMemberDecls(*this, ExprType, CurrDeclContext, + lookupVisibleMemberDecls(*this, ExprType, DotLoc, CurrDeclContext, IncludeInstanceMembers, /*includeDerivedRequirements*/ false, /*includeProtocolExtensionMembers*/ true); @@ -2833,7 +2834,7 @@ void CompletionLookup::getUnresolvedMemberCompletions(Type T) { llvm::SaveAndRestore SaveLook(Kind, LookupKind::ValueExpr); llvm::SaveAndRestore SaveType(ExprType, baseType); llvm::SaveAndRestore SaveUnresolved(IsUnresolvedMember, true); - lookupVisibleMemberDecls(consumer, baseType, CurrDeclContext, + lookupVisibleMemberDecls(consumer, baseType, DotLoc, CurrDeclContext, /*includeInstanceMembers=*/false, /*includeDerivedRequirements*/ false, /*includeProtocolExtensionMembers*/ true); @@ -2847,7 +2848,7 @@ void CompletionLookup::getEnumElementPatternCompletions(Type T) { llvm::SaveAndRestore SaveLook(Kind, LookupKind::EnumElement); llvm::SaveAndRestore SaveType(ExprType, baseType); llvm::SaveAndRestore SaveUnresolved(IsUnresolvedMember, true); - lookupVisibleMemberDecls(*this, baseType, CurrDeclContext, + lookupVisibleMemberDecls(*this, baseType, DotLoc, CurrDeclContext, /*includeInstanceMembers=*/false, /*includeDerivedRequirements=*/false, /*includeProtocolExtensionMembers=*/true); @@ -2915,8 +2916,8 @@ void CompletionLookup::getTypeCompletions(Type BaseType) { Kind = LookupKind::Type; this->BaseType = BaseType; NeedLeadingDot = !HaveDot; - lookupVisibleMemberDecls(*this, MetatypeType::get(BaseType), CurrDeclContext, - IncludeInstanceMembers, + lookupVisibleMemberDecls(*this, MetatypeType::get(BaseType), DotLoc, + CurrDeclContext, IncludeInstanceMembers, /*includeDerivedRequirements*/ false, /*includeProtocolExtensionMembers*/ false); if (BaseType->isAnyExistentialType()) { @@ -2951,8 +2952,8 @@ void CompletionLookup::getGenericRequirementCompletions( Kind = LookupKind::GenericRequirement; this->BaseType = selfTy; NeedLeadingDot = false; - lookupVisibleMemberDecls(*this, MetatypeType::get(selfTy), CurrDeclContext, - IncludeInstanceMembers, + lookupVisibleMemberDecls(*this, MetatypeType::get(selfTy), DotLoc, + CurrDeclContext, IncludeInstanceMembers, /*includeDerivedRequirements*/ false, /*includeProtocolExtensionMembers*/ true); // We not only allow referencing nested types/typealiases directly, but also diff --git a/lib/IDE/CompletionOverrideLookup.cpp b/lib/IDE/CompletionOverrideLookup.cpp index 53320471bfbe7..8a97365271c7e 100644 --- a/lib/IDE/CompletionOverrideLookup.cpp +++ b/lib/IDE/CompletionOverrideLookup.cpp @@ -541,7 +541,7 @@ void CompletionOverrideLookup::getOverrideCompletions(SourceLoc Loc) { if (CurrTy && !CurrTy->is()) { // Look for overridable static members too. Type Meta = MetatypeType::get(CurrTy); - lookupVisibleMemberDecls(*this, Meta, CurrDeclContext, + lookupVisibleMemberDecls(*this, Meta, introducerLoc, CurrDeclContext, /*includeInstanceMembers=*/true, /*includeDerivedRequirements*/ true, /*includeProtocolExtensionMembers*/ false); diff --git a/lib/IDE/ConformingMethodList.cpp b/lib/IDE/ConformingMethodList.cpp index ed5fde99cead9..ef1d355695116 100644 --- a/lib/IDE/ConformingMethodList.cpp +++ b/lib/IDE/ConformingMethodList.cpp @@ -166,7 +166,8 @@ void ConformingMethodListCallbacks::getMatchingMethods( } LocalConsumer(CurDeclContext, T, expectedTypes, result); - lookupVisibleMemberDecls(LocalConsumer, MetatypeType::get(T), CurDeclContext, + lookupVisibleMemberDecls(LocalConsumer, MetatypeType::get(T), + Loc, CurDeclContext, /*includeInstanceMembers=*/false, /*includeDerivedRequirements*/false, /*includeProtocolExtensionMembers*/true); diff --git a/lib/IDE/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 51e1a39a0c5eb0731360b2037aaec385ec83010b 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. --- 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 393b4ceb956f91f02a10c0b671664313a6bb8563 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. --- 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 51aea7c64db31..5d3898d43283e 100644 --- a/include/swift/AST/NameLookup.h +++ b/include/swift/AST/NameLookup.h @@ -545,6 +545,15 @@ template void filterForDiscriminator(SmallVectorImpl &results, DebuggerClient *debugClient); +/// \returns The set of macro declarations with the given name that +/// fulfill any of the given macro roles. +SmallVector +lookupMacros(DeclContext *dc, DeclNameRef macroName, MacroRoles roles); + +/// \returns Whether the given source location is inside an attached +/// or freestanding macro argument. +bool isInMacroArgument(SourceFile *sourceFile, SourceLoc loc); + /// Call the given function body with each macro declaration and its associated /// role attribute for the given role. /// @@ -816,9 +825,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 66c3bd8a97657..ca2162d7e504e 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -1594,6 +1594,60 @@ static DeclName adjustLazyMacroExpansionNameKey( return name; } +SmallVector +namelookup::lookupMacros(DeclContext *dc, DeclNameRef macroName, + MacroRoles roles) { + SmallVector choices; + auto moduleScopeDC = dc->getModuleScopeContext(); + ASTContext &ctx = moduleScopeDC->getASTContext(); + + // Macro lookup should always exclude macro expansions; macro + // expansions cannot introduce new macro declarations. Note that + // the source location here doesn't matter. + UnqualifiedLookupDescriptor descriptor{ + macroName, moduleScopeDC, SourceLoc(), + UnqualifiedLookupFlags::ExcludeMacroExpansions + }; + + auto lookup = evaluateOrDefault( + ctx.evaluator, UnqualifiedLookupRequest{descriptor}, {}); + for (const auto &found : lookup.allResults()) { + if (auto macro = dyn_cast(found.getValueDecl())) { + auto candidateRoles = macro->getMacroRoles(); + if ((candidateRoles && roles.contains(candidateRoles)) || + // FIXME: `externalMacro` should have all roles. + macro->getBaseIdentifier().str() == "externalMacro") { + choices.push_back(macro); + } + } + } + return choices; +} + +bool +namelookup::isInMacroArgument(SourceFile *sourceFile, SourceLoc loc) { + bool inMacroArgument = false; + + ASTScope::lookupEnclosingMacroScope( + sourceFile, loc, + [&](auto potentialMacro) -> bool { + UnresolvedMacroReference macro(potentialMacro); + + if (macro.getFreestanding()) { + inMacroArgument = true; + } else if (auto *attr = macro.getAttr()) { + auto *moduleScope = sourceFile->getModuleScopeContext(); + auto results = lookupMacros(moduleScope, macro.getMacroName(), + getAttachedMacroRoles()); + inMacroArgument = !results.empty(); + } + + return inMacroArgument; + }); + + return inMacroArgument; +} + /// Call the given function body with each macro declaration and its associated /// role attribute for the given role. /// @@ -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 8286a65c3a1ec..1c71bf20a74de 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 0d039346f9589..b982f0436f629 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -1609,36 +1609,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 00be8a294574a..c7b0f454aca02 100644 --- a/lib/Sema/TypeCheckMacros.cpp +++ b/lib/Sema/TypeCheckMacros.cpp @@ -1520,7 +1520,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 7fe330049c3b4..22aed44dd31fc 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 2cc1204afe883939eeda628c773210b6c7267d51 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(). --- 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(