From e06d0b9357af1b5627e7f3135869f04d33eaad73 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 18 Dec 2024 15:04:16 -0800 Subject: [PATCH] Revert "[SwiftLexicalLookup] New unqualified lookup implementation validation" --- include/swift/AST/ASTBridging.h | 15 - include/swift/AST/ASTBridgingImpl.h | 9 - include/swift/AST/DiagnosticsCommon.def | 7 - include/swift/Basic/Features.def | 4 - include/swift/Bridging/ASTGen.h | 7 - lib/AST/ASTScope.cpp | 124 +--- lib/AST/FeatureSet.cpp | 1 - lib/ASTGen/Package.swift | 1 - lib/ASTGen/Sources/ASTGen/CMakeLists.txt | 2 - lib/ASTGen/Sources/ASTGen/LexicalLookup.swift | 640 ------------------ lib/CompilerSwiftSyntax/CMakeLists.txt | 1 - .../testGenericWhereClause.swift | 75 -- 12 files changed, 1 insertion(+), 885 deletions(-) delete mode 100644 lib/ASTGen/Sources/ASTGen/LexicalLookup.swift delete mode 100644 test/NameLookup/SwiftLexicalLookupValidation/testGenericWhereClause.swift diff --git a/include/swift/AST/ASTBridging.h b/include/swift/AST/ASTBridging.h index 056417cc5cc73..972b22ff99c0e 100644 --- a/include/swift/AST/ASTBridging.h +++ b/include/swift/AST/ASTBridging.h @@ -101,21 +101,6 @@ struct BridgedLocatedIdentifier { BridgedSourceLoc NameLoc; }; -struct BridgedConsumedLookupResult { - SWIFT_NAME("name") - BridgedIdentifier Name; - - SWIFT_NAME("nameLoc") - BridgedSourceLoc NameLoc; - - SWIFT_NAME("flag") - SwiftInt Flag; - - BRIDGED_INLINE BridgedConsumedLookupResult(swift::Identifier name, - swift::SourceLoc sourceLoc, - SwiftInt flag); -}; - class BridgedDeclBaseName { BridgedIdentifier Ident; diff --git a/include/swift/AST/ASTBridgingImpl.h b/include/swift/AST/ASTBridgingImpl.h index 735c0dd1314bb..c56e945cba64f 100644 --- a/include/swift/AST/ASTBridgingImpl.h +++ b/include/swift/AST/ASTBridgingImpl.h @@ -55,15 +55,6 @@ swift::DeclBaseName BridgedDeclBaseName::unbridged() const { return swift::DeclBaseName(Ident.unbridged()); } -//===----------------------------------------------------------------------===// -// MARK: BridgedDeclBaseName -//===----------------------------------------------------------------------===// - -BridgedConsumedLookupResult::BridgedConsumedLookupResult( - swift::Identifier name, swift::SourceLoc sourceLoc, SwiftInt flag) - : Name(BridgedIdentifier(name)), NameLoc(BridgedSourceLoc(sourceLoc)), - Flag(flag) {} - //===----------------------------------------------------------------------===// // MARK: BridgedDeclNameRef //===----------------------------------------------------------------------===// diff --git a/include/swift/AST/DiagnosticsCommon.def b/include/swift/AST/DiagnosticsCommon.def index 5df992c9551ea..f1ea5d7ca27fa 100644 --- a/include/swift/AST/DiagnosticsCommon.def +++ b/include/swift/AST/DiagnosticsCommon.def @@ -236,13 +236,6 @@ NOTE(in_macro_expansion,none, ERROR(macro_experimental,none, "%0 macros are an experimental feature that is not enabled %select{|(%1)}1", (StringRef, StringRef)) - -//------------------------------------------------------------------------------ -// MARK: lexical lookup diagnostics -//------------------------------------------------------------------------------ - -ERROR(lookup_outputs_dont_match,none, -"Unqualified lookup output from ASTScope and SwiftLexicalLookup don't match", ()) //------------------------------------------------------------------------------ // MARK: bridged diagnostics diff --git a/include/swift/Basic/Features.def b/include/swift/Basic/Features.def index d267efeae4e08..ff5c7053884ef 100644 --- a/include/swift/Basic/Features.def +++ b/include/swift/Basic/Features.def @@ -301,10 +301,6 @@ EXPERIMENTAL_FEATURE(ParserRoundTrip, false) /// Swift parser. EXPERIMENTAL_FEATURE(ParserValidation, false) -/// Whether to perform validation of the unqualified lookup produced by -/// ASTScope and SwiftLexicalLookup -EXPERIMENTAL_FEATURE(UnqualifiedLookupValidation, false) - /// Enables implicit some while also enabling existential `any` EXPERIMENTAL_FEATURE(ImplicitSome, false) diff --git a/include/swift/Bridging/ASTGen.h b/include/swift/Bridging/ASTGen.h index 50f4c8e310b5f..114af00a8f47c 100644 --- a/include/swift/Bridging/ASTGen.h +++ b/include/swift/Bridging/ASTGen.h @@ -98,13 +98,6 @@ intptr_t swift_ASTGen_configuredRegions( void swift_ASTGen_freeConfiguredRegions( BridgedIfConfigClauseRangeInfo *_Nullable regions, intptr_t numRegions); -bool swift_ASTGen_validateUnqualifiedLookup( - void *_Nonnull sourceFile, - BridgedASTContext astContext, - BridgedSourceLoc sourceLoc, - bool finishInSequentialScope, - BridgedArrayRef astScopeResultRef); - size_t swift_ASTGen_virtualFiles(void *_Nonnull sourceFile, BridgedVirtualFile *_Nullable *_Nonnull virtualFiles); diff --git a/lib/AST/ASTScope.cpp b/lib/AST/ASTScope.cpp index 20759284bb5e1..9a44b6fdaf86b 100644 --- a/lib/AST/ASTScope.cpp +++ b/lib/AST/ASTScope.cpp @@ -17,7 +17,6 @@ #include "swift/AST/ASTContext.h" #include "swift/AST/ASTWalker.h" -#include "swift/Bridging/ASTGen.h" #include "swift/AST/Decl.h" #include "swift/AST/Expr.h" #include "swift/AST/Initializer.h" @@ -40,104 +39,6 @@ using namespace ast_scope; #pragma mark ASTScope -class LoggingASTScopeDeclConsumer - : public namelookup::AbstractASTScopeDeclConsumer { -private: - const int shouldLookInMembers = 0b10; - namelookup::AbstractASTScopeDeclConsumer *originalConsumer; - -public: - mutable SmallVector recordedElements; - - LoggingASTScopeDeclConsumer( - namelookup::AbstractASTScopeDeclConsumer *consumer) - : originalConsumer(consumer) {} - - ~LoggingASTScopeDeclConsumer() = default; - - /// Called for every ValueDecl visible from the lookup. - /// - /// Takes an array in order to batch the consumption before setting - /// IndexOfFirstOuterResult when necessary. - /// - /// Additionally, each name is logged to `recordedElements` and - /// can be later used in validation of `SwiftLexicalLookup` result. - /// - /// \param baseDC either a type context or the local context of a - /// `self` parameter declaration. See LookupResult for a discussion - /// of type -vs- instance lookup results. - /// - /// \return true if the lookup should be stopped at this point. - bool consume(ArrayRef values, - NullablePtr baseDC = nullptr) override { - bool endOfLookup = originalConsumer->consume(values, baseDC); - - for (auto value : values) { - if (auto sourceLoc = value->getLoc()) { - recordedElements.push_back(BridgedConsumedLookupResult( - value->getBaseIdentifier(), sourceLoc, endOfLookup)); - } else { - // If sourceLoc is unavailable, use location of it's parent. - recordedElements.push_back(BridgedConsumedLookupResult( - value->getBaseIdentifier(), - value->getDeclContext()->getAsDecl()->getLoc(), endOfLookup)); - } - } - - return endOfLookup; - }; - - /// Look for members of a nominal type or extension scope. - /// - /// Each call is recorded in `recordedElements` with a special flag set. - /// It can be later used in validation of `SwiftLexicalLookup` result. - /// - /// \return true if the lookup should be stopped at this point. - bool lookInMembers(const DeclContext *scopeDC) const override { - bool endOfLookup = originalConsumer->lookInMembers(scopeDC); - - if (auto *extDecl = dyn_cast(scopeDC)) { - recordedElements.push_back(BridgedConsumedLookupResult( - Identifier(), extDecl->getExtendedTypeRepr()->getLoc(), - shouldLookInMembers + endOfLookup)); - } else { - recordedElements.push_back(BridgedConsumedLookupResult( - scopeDC->getSelfNominalTypeDecl()->getBaseIdentifier(), - scopeDC->getAsDecl()->getLoc(), shouldLookInMembers + endOfLookup)); - } - - return endOfLookup; - }; - - /// Called for local VarDecls that might not yet be in scope. - /// - /// Note that the set of VarDecls visited here are going to be a - /// superset of those visited in consume(). - bool consumePossiblyNotInScope(ArrayRef values) override { - bool result = originalConsumer->consumePossiblyNotInScope(values); - return result; - } - - /// Called right before looking at the parent scope of a BraceStmt. - /// - /// \return true if the lookup should be stopped at this point. - bool finishLookupInBraceStmt(BraceStmt *stmt) override { - return originalConsumer->finishLookupInBraceStmt(stmt); - } - -#ifndef NDEBUG - void startingNextLookupStep() override { - originalConsumer->startingNextLookupStep(); - } - void finishingLookup(std::string input) const override { - originalConsumer->finishingLookup(input); - } - bool isTargetLookup() const override { - return originalConsumer->isTargetLookup(); - } -#endif -}; - void ASTScope::unqualifiedLookup( SourceFile *SF, SourceLoc loc, namelookup::AbstractASTScopeDeclConsumer &consumer) { @@ -147,30 +48,7 @@ void ASTScope::unqualifiedLookup( if (auto *s = SF->getASTContext().Stats) ++s->getFrontendCounters().NumASTScopeLookups; - - // Perform validation of SwiftLexicalLookup if option - // Feature::UnqualifiedLookupValidation is enabled and lookup was not - // performed in a macro. - if (SF->getASTContext().LangOpts.hasFeature( - Feature::UnqualifiedLookupValidation) && - !SF->getEnclosingSourceFile()) { - LoggingASTScopeDeclConsumer loggingASTScopeDeclConsumer = - LoggingASTScopeDeclConsumer(&consumer); - - ASTScopeImpl::unqualifiedLookup(SF, loc, loggingASTScopeDeclConsumer); - - bool passed = swift_ASTGen_validateUnqualifiedLookup( - SF->getExportedSourceFile(), SF->getASTContext(), loc, - loggingASTScopeDeclConsumer.finishLookupInBraceStmt(nullptr), - BridgedArrayRef(loggingASTScopeDeclConsumer.recordedElements.data(), - loggingASTScopeDeclConsumer.recordedElements.size())); - - if (!passed) { - SF->getASTContext().Diags.diagnose(loc, diag::lookup_outputs_dont_match); - } - } else { - ASTScopeImpl::unqualifiedLookup(SF, loc, consumer); - } + ASTScopeImpl::unqualifiedLookup(SF, loc, consumer); } llvm::SmallVector ASTScope::lookupLabeledStmts( diff --git a/lib/AST/FeatureSet.cpp b/lib/AST/FeatureSet.cpp index 30f5e28b5816f..fb81bf781a739 100644 --- a/lib/AST/FeatureSet.cpp +++ b/lib/AST/FeatureSet.cpp @@ -103,7 +103,6 @@ UNINTERESTING_FEATURE(OpaqueTypeErasure) UNINTERESTING_FEATURE(PackageCMO) UNINTERESTING_FEATURE(ParserRoundTrip) UNINTERESTING_FEATURE(ParserValidation) -UNINTERESTING_FEATURE(UnqualifiedLookupValidation) UNINTERESTING_FEATURE(ImplicitSome) UNINTERESTING_FEATURE(ParserASTGen) UNINTERESTING_FEATURE(BuiltinMacros) diff --git a/lib/ASTGen/Package.swift b/lib/ASTGen/Package.swift index 1702924f49131..5061ffdd84f98 100644 --- a/lib/ASTGen/Package.swift +++ b/lib/ASTGen/Package.swift @@ -56,7 +56,6 @@ let package = Package( dependencies: [ .product(name: "SwiftDiagnostics", package: "swift-syntax"), .product(name: "SwiftIfConfig", package: "swift-syntax"), - .product(name: "SwiftLexicalLookup", package: "swift-syntax"), .product(name: "SwiftOperators", package: "swift-syntax"), .product(name: "SwiftParser", package: "swift-syntax"), .product(name: "SwiftParserDiagnostics", package: "swift-syntax"), diff --git a/lib/ASTGen/Sources/ASTGen/CMakeLists.txt b/lib/ASTGen/Sources/ASTGen/CMakeLists.txt index 45fd9b7701a12..a23742300d437 100644 --- a/lib/ASTGen/Sources/ASTGen/CMakeLists.txt +++ b/lib/ASTGen/Sources/ASTGen/CMakeLists.txt @@ -10,7 +10,6 @@ add_pure_swift_host_library(swiftASTGen STATIC CXX_INTEROP Exprs.swift Fingerprint.swift Generics.swift - LexicalLookup.swift Literals.swift ParameterClause.swift Patterns.swift @@ -27,7 +26,6 @@ add_pure_swift_host_library(swiftASTGen STATIC CXX_INTEROP _CompilerRegexParser _CompilerSwiftSyntax _CompilerSwiftIfConfig - _CompilerSwiftLexicalLookup _CompilerSwiftOperators _CompilerSwiftSyntaxBuilder _CompilerSwiftParser diff --git a/lib/ASTGen/Sources/ASTGen/LexicalLookup.swift b/lib/ASTGen/Sources/ASTGen/LexicalLookup.swift deleted file mode 100644 index 4dbc4df582d05..0000000000000 --- a/lib/ASTGen/Sources/ASTGen/LexicalLookup.swift +++ /dev/null @@ -1,640 +0,0 @@ -//===--- LexicalLookup.swift ----------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2022-2024 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -import ASTBridging -import BasicBridging -import SwiftIfConfig -@_spi(Experimental) import SwiftLexicalLookup -import SwiftSyntax - -private let rowCharWidth: Int = 30 - -/// This function validates output of SwiftLexicalLookup -/// against the output of `ASTScope` passed to `astScopeResultRef`. -/// -/// The function assigns specific flags to obtained names. The flags are applied in three phases: -/// - `ASTScope` name extraction - The names obtained from `astScopeResultRef` are -/// mapped to `ConsumedLookupResult` common representation. The names receive flags -/// independently from `SwiftLexicalLookup` results. -/// - `SwiftLexicalLookup` lookup - The names obtained from performing lookup with `SwiftLexicalLookup` are -/// mapped to `ConsumedLookupResult` common representation. The names receive flags -/// independently from `ASTScope` results. -/// - Flagging pass - The method iterates through both result arrays together and, taking into -/// account already applied flags and relationships between results, applies more flags to the results. -/// -/// Fully flagged results, are then fed to the name matching pass. Using associated names, positions and -/// flags, it asserts the equality of results and produces console output. -/// -/// Returns `true`, if the matching was successful and `false` otherwise. -/// Additionally, when matching fails, the function prints console output with the two results compared. -@_cdecl("swift_ASTGen_validateUnqualifiedLookup") -public func unqualifiedLookup( - sourceFilePtr: UnsafeMutableRawPointer, - astContext: BridgedASTContext, - lookupAt: BridgedSourceLoc, - finishInSequentialScope: Bool, - astScopeResultRef: BridgedArrayRef -) -> Bool { - // Obtain source file and lookup position - let sourceFile = sourceFilePtr.assumingMemoryBound(to: ExportedSourceFile.self) - guard let sourceFileSyntax = sourceFile.pointee.syntax.as(SourceFileSyntax.self) else { - print("Could not cast exported source file to SourceFileSyntax") - return false - } - let sourceLocationConverter = sourceFile.pointee.sourceLocationConverter - let configuredRegions = sourceFile.pointee.configuredRegions(astContext: astContext) - - guard let lookupPosition = sourceFile.pointee.position(of: lookupAt), - let lookupToken = sourceFileSyntax.token(at: lookupPosition) - else { - print("Could not determine lookup position") - return false - } - - // Map AST result - let astResults = astConsumedResults( - sourceFile: sourceFile, - astScopeResultRef: astScopeResultRef - ) - - // Map SLL result - let sllResults = sllConsumedResults( - lookupToken: lookupToken, - finishInSequentialScope: finishInSequentialScope, - configuredRegions: configuredRegions - ) - - // Add header to the output - var consoleOutput = - "-----> Lookup started at: \(sourceLocationConverter.location(for: lookupPosition).lineWithColumn) (\"\(lookupToken.text)\") finishInSequentialScope: \(finishInSequentialScope)\n" - consoleOutput += - " |" + "ASTScope".addPaddingUpTo(characters: rowCharWidth) + "|" - + "SwiftLexicalLookup".addPaddingUpTo(characters: rowCharWidth) + "\n" - - // Flagging pass - flaggingPass( - astResults: astResults, - sllResults: sllResults, - sourceFileSyntax: sourceFileSyntax, - lookupPosition: lookupPosition - ) - - // Matching pass - let passed = matchingPass( - astResults: astResults, - sllResults: sllResults, - sourceLocationConverter: sourceLocationConverter, - consoleOutput: &consoleOutput - ) - - // Output - if !passed { - print(consoleOutput) - } - - return passed -} - -/// Check if the name at `namePosition`, was improperly introduced -/// by ASTScope (in the same declaration as lookup). -private func isInvalidFirstNameInDeclarationIntroduction( - sourceFile: SourceFileSyntax, - lookupPosition: AbsolutePosition, - namePosition: AbsolutePosition -) -> Bool { - func firstAncestorOfKind( - of syntax: SyntaxProtocol?, - kinds: [SyntaxProtocol.Type] - ) -> SyntaxProtocol? { - guard let syntax else { return nil } - - for kind in kinds { - if syntax.is(kind) { - return syntax - } - } - - return firstAncestorOfKind(of: syntax.parent, kinds: kinds) - } - - let originToken = sourceFile.token(at: lookupPosition) - let firstNameToken = sourceFile.token(at: namePosition) - - let commonAncestors: [SyntaxProtocol.Type] = [ - SwitchCaseSyntax.self, - ClosureExprSyntax.self, - AccessorDeclSyntax.self, - AccessorBlockSyntax.self, - ForStmtSyntax.self, - PatternBindingSyntax.self, - ] - - let originAncestor = firstAncestorOfKind( - of: originToken, - kinds: commonAncestors - ) - - let firstNameAncestor = firstAncestorOfKind( - of: firstNameToken, - kinds: commonAncestors - ) - - guard let originAncestor, - let firstNameAncestor, - originAncestor.kind == firstNameAncestor.kind - else { return false } - - return originAncestor.kind == .patternBinding && originAncestor.id == firstNameAncestor.id -} - -/// Returns consumed `ASTScope` results from the -/// given `astScopeResultRef`. Introduces appropriate flags. -private func astConsumedResults( - sourceFile: UnsafePointer, - astScopeResultRef: BridgedArrayRef -) -> [ConsumedLookupResult] { - let pointer = astScopeResultRef.data?.assumingMemoryBound(to: BridgedConsumedLookupResult.self) - let count = astScopeResultRef.count - - let astScopeResultArray = Array(UnsafeBufferPointer(start: pointer, count: count)) - - return astScopeResultArray.compactMap { bridgedResult in - let identifierPointer = bridgedResult.name.raw?.assumingMemoryBound(to: CChar.self) - - guard let astResultPosition = sourceFile.pointee.position(of: bridgedResult.nameLoc) else { - print("One of the results, doesn't have a position") - return nil - } - - let consumedResult = ConsumedLookupResult( - rawName: identifierPointer == nil ? "" : String(cString: identifierPointer!), - position: astResultPosition, - flags: ConsumedLookupResultFlag(rawValue: bridgedResult.flag) - ) - - // If the name doesn't have any flags and - // the name is empty, it should be omitted. - if consumedResult.flags.isEmpty && consumedResult.name.isEmpty { - consumedResult.flags.insert(.shouldBeOmitted) - } - - return consumedResult - } -} - -/// Performs and returns `SwiftLexicalLookup` lookup and returns -/// the results an array of `ConsumedLookupResult`. Introduces appropriate flags. -private func sllConsumedResults( - lookupToken: TokenSyntax, - finishInSequentialScope: Bool, - configuredRegions: ConfiguredRegions -) -> [ConsumedLookupResult] { - let resultsWithoutMacroReordering = lookupToken.lookup( - nil, - with: LookupConfig(finishInSequentialScope: finishInSequentialScope, configuredRegions: configuredRegions) - ) - - // Early reordering of macro declaration parameters with its generic parameters. - var results: [LookupResult] = [] - var previousMacroResult: LookupResult? - - for result in resultsWithoutMacroReordering { - if let unwrappedMacroResult = previousMacroResult, - result.scope.is(GenericParameterClauseSyntax.self) - { - results += [result, unwrappedMacroResult] - previousMacroResult = nil - continue - } else if let unwrappedMacroResult = previousMacroResult { - results.append(unwrappedMacroResult) - previousMacroResult = nil - } - - if result.scope.is(MacroDeclSyntax.self) { - previousMacroResult = result - } else { - results.append(result) - } - } - - if let previousMacroResult { - results.append(previousMacroResult) - } - - return results.flatMap { result in - switch result { - case .lookInMembers(let lookInMembers): - return [ - ConsumedLookupResult( - rawName: "", - position: lookInMembers.lookupMembersPosition, - flags: .shouldLookInMembers - ) - ] - case .lookInGenericParametersOfExtendedType(let extensionDecl): - return [ - ConsumedLookupResult( - rawName: "", - position: extensionDecl.extensionKeyword.positionAfterSkippingLeadingTrivia, - flags: .ignoreNextFromHere - ) - ] - case .mightIntroduceDollarIdentifiers(let closure): - return [ - ConsumedLookupResult( - rawName: "", - position: closure.positionAfterSkippingLeadingTrivia, - flags: .ignoreNextFromHere - ) - ] - default: - if let parent = result.scope.parent, result.scope.is(GenericParameterClauseSyntax.self) { - if let parentFunctionDecl = parent.as(FunctionDeclSyntax.self), - parentFunctionDecl.attributes.range.contains(lookupToken.position) - { - // If lookup started from inside function attributes, don't reverse. - return result.names.map { name in - ConsumedLookupResult(rawName: name.identifier?.name ?? "", position: name.position, flags: []) - } - } else if parent.is(FunctionDeclSyntax.self) || parent.is(SubscriptDeclSyntax.self) - || result.scope.range.contains(lookupToken.position) - { - // If a result from function generic parameter clause or lookup started within it, reverse introduced names. - return result.names.reversed().map { name in - ConsumedLookupResult( - rawName: name.identifier?.name ?? "", - position: name.position, - flags: .placementRearranged - ) - } - } else if let nominalTypeScope = Syntax(parent).asProtocol(SyntaxProtocol.self) as? NominalTypeDeclSyntax, - nominalTypeScope.inheritanceClause?.range.contains(lookupToken.position) ?? false - { - // If lookup started from nominal type inheritance clause, reverse introduced names. - return result.names.reversed().map { name in - ConsumedLookupResult( - rawName: name.identifier?.name ?? "", - position: name.position, - flags: .placementRearranged - ) - } - } else if let initializerDecl = parent.as(InitializerDeclSyntax.self), - initializerDecl.range.contains(lookupToken.position) - { - // If lookup from inside the parent initializer decl, reverse introduced names. - return result.names.reversed().map { name in - ConsumedLookupResult( - rawName: name.identifier?.name ?? "", - position: name.position, - flags: .placementRearranged - ) - } - } else if let parentTypeAlias = parent.as(TypeAliasDeclSyntax.self), - parentTypeAlias.initializer.range.contains(lookupToken.position) - { - // If lookup started from inside type alias initializer, reverse introduced names. - return result.names.reversed().map { name in - ConsumedLookupResult( - rawName: name.identifier?.name ?? "", - position: name.position, - flags: .placementRearranged - ) - } - } - - // No flags or reorderings to perform. - return result.names.map { name in - ConsumedLookupResult(rawName: name.identifier?.name ?? "", position: name.position, flags: []) - } - } else { - return result.names.map { name in - // If a Self name not from protocol declaration, should be omitted if no match is found. - let shouldBeOmitted = name.identifier?.name == "Self" ? !result.scope.is(ProtocolDeclSyntax.self) : false - - return ConsumedLookupResult( - rawName: name.identifier?.name ?? "", - position: name.position, - flags: shouldBeOmitted ? [.shouldBeOptionallyOmitted] : [] - ) - } - } - } - } -} - -/// Adds all appropriate flags to `astResults` and `sllResults`. -private func flaggingPass( - astResults: [ConsumedLookupResult], - sllResults: [ConsumedLookupResult], - sourceFileSyntax: SourceFileSyntax, - lookupPosition: AbsolutePosition -) { - var i = 0 - var astOffset = 0 - var sllOffset = 0 - var encounteredASTNames = Set() - var ignoreAt: AbsolutePosition? - var wasLookupStopped = false - - while i < max(astResults.count, sllResults.count) { - var astResult: ConsumedLookupResult? - - if astOffset + i < astResults.count { - astResult = astResults[astOffset + i] - - // Here only to not have to perform force unwraps later. - guard let astResult else { break } - - // Check if lookup was stopped earlier. If so, flag this result with lookupStopped. - if wasLookupStopped { - astResult.flags.insert(.lookupStopped) - } - - // Check if this is the end of ast lookup. If so, set wasLookupStopped to true. - if astResult.isTheEndOfLookup { - wasLookupStopped = true - } - - // Check if this is not the first encounter of this ast name. If so, should be omitted. - if !astResult.shouldLookInMembers { - let isFirstEncounter = !encounteredASTNames.contains(astResult) - - if !isFirstEncounter { - astResult.flags.insert(.shouldBeOmitted) - } - } - - // Check if names are being currently ignored from at this position. If so, should be omitted. - if astResult.position == ignoreAt { - astResult.flags.insert(.shouldBeOmitted) - } - - // Check if this is an invalid introduction within the same declaration. If so, should be omitted. - if isInvalidFirstNameInDeclarationIntroduction( - sourceFile: sourceFileSyntax, - lookupPosition: lookupPosition, - namePosition: astResult.position - ) && astResult.name != "self" { - astResult.flags.insert(.shouldBeOmitted) - } - - // Check if this name should be omitted. If so, continue the loop and add one to offset. - if astResult.shouldBeOmitted { - astOffset += 1 - continue - } - } - - if i + sllOffset < sllResults.count { - let sllResult = sllResults[i + sllOffset] - - // Check if lookup was stopped earlier. If so, flag this result with lookupStopped. - if wasLookupStopped && !(astResult?.isTheEndOfLookup ?? false) { - sllResult.flags.insert(.lookupStopped) - } - - if sllResult.shouldBeOptionallyOmitted { - if let astResult, - astResult.name == sllResult.name - { - sllResult.flags.remove(.shouldBeOptionallyOmitted) - } else { - sllResult.flags.insert(.shouldBeOmitted) - } - } - - // Check if next results at this position should be ignored. If so, set ignoreAt and omit this name. - if sllResult.ignoreNextFromHere && sllResult.position != ignoreAt { - ignoreAt = sllResult.position - sllResult.flags.insert(.shouldBeOmitted) - } - - // Check if this name should be omitted. If so, continue the loop and add one to offset. - if sllResult.shouldBeOmitted { - sllOffset += 1 - continue - } - } - - if let astResult { - encounteredASTNames.insert(astResult) - } - - i += 1 - } -} - -/// Tries to match both results taking into account previously set -/// flags. Returns whether the test validation succeeded. -private func matchingPass( - astResults: [ConsumedLookupResult], - sllResults: [ConsumedLookupResult], - sourceLocationConverter: SourceLocationConverter, - consoleOutput: inout String -) -> Bool { - var i = 0 - var astOffset = 0 - var sllOffset = 0 - var passed = true - - while i < max(astResults.count, sllResults.count) { - var prefix = "" - var astResultStr = "" - var sllResultStr = "" - - var astResult: ConsumedLookupResult? - - if astOffset + i < astResults.count { - astResult = astResults[astOffset + i] - - guard let astResult else { break } - - if astResult.shouldBeOmitted { - consoleOutput += - "> ℹ️ | Omitted ASTScope name: \(astResult.consoleLogStr(sourceLocationConverter: sourceLocationConverter))\n" - astOffset += 1 - continue - } - - astResultStr += astResult.consoleLogStr(sourceLocationConverter: sourceLocationConverter) - } else { - astResultStr = "-----" - } - - var sllResult: ConsumedLookupResult? - - if i + sllOffset < sllResults.count { - sllResult = sllResults[i + sllOffset] - - guard let sllResult else { break } - - if sllResult.shouldBeOmitted { - consoleOutput += - "> ℹ️ | Omitted SwiftLexicalLookup name: \(sllResult.consoleLogStr(sourceLocationConverter: sourceLocationConverter))\n" - sllOffset += 1 - continue - } - - sllResultStr = sllResult.consoleLogStr(sourceLocationConverter: sourceLocationConverter) - } else { - sllResultStr = "-----" - } - - i += 1 - - guard astResult != nil || sllResult != nil else { continue } - - if let astResult, let sllResult { - if (astResult.position == sllResult.position && astResult.name == sllResult.name) { - prefix = "✅" - } else if astResult.lookupStopped || sllResult.lookupStopped { - prefix = "⏩" - } else if astResult.position == sllResult.position || astResult.name == sllResult.name { - prefix = "⚠️" - passed = false - } else { - prefix = "❌" - passed = false - } - } else if (astResult?.lookupStopped ?? false) || (sllResult?.lookupStopped ?? false) { - prefix = "⏩" - } else { - prefix = "❌" - passed = false - } - - consoleOutput += - "> \(prefix) |\(astResultStr.addPaddingUpTo(characters: rowCharWidth))|\(sllResultStr.addPaddingUpTo(characters: rowCharWidth))" - - consoleOutput += "\n" - } - - return passed -} - -/// Simple representation of lookup result. -/// Contains flags that indicate additional behaviour. -private class ConsumedLookupResult: Hashable { - var rawName: String - var position: AbsolutePosition - var flags: ConsumedLookupResultFlag - - init( - rawName: String, - position: AbsolutePosition, - flags: ConsumedLookupResultFlag - ) { - self.rawName = rawName - self.position = position - self.flags = flags - } - - var name: String { - shouldLookInMembers ? "" : rawName - } - - var isTheEndOfLookup: Bool { - flags.contains(.endOfLookup) - } - - var shouldLookInMembers: Bool { - flags.contains(.shouldLookInMembers) - } - - var resultPlacementRearranged: Bool { - flags.contains(.placementRearranged) - } - - var shouldBeOmitted: Bool { - flags.contains(.shouldBeOmitted) - } - - var shouldBeOptionallyOmitted: Bool { - flags.contains(.shouldBeOptionallyOmitted) - } - - var ignoreNextFromHere: Bool { - flags.contains(.ignoreNextFromHere) - } - - var lookupStopped: Bool { - flags.contains(.lookupStopped) - } - - func consoleLogStr(sourceLocationConverter: SourceLocationConverter) -> String { - (isTheEndOfLookup ? "End here: " : "") + (resultPlacementRearranged ? "↕️ " : "") - + (ignoreNextFromHere ? "Ignore next from: " : "") + (shouldLookInMembers ? "Look memb: " : "\(name) ") - + sourceLocationConverter.location(for: position).lineWithColumn - } - - static func == (lhs: ConsumedLookupResult, rhs: ConsumedLookupResult) -> Bool { - return lhs.rawName == rhs.rawName && lhs.position == rhs.position && lhs.flags == rhs.flags - } - - func hash(into hasher: inout Hasher) { - hasher.combine(rawName) - hasher.combine(position) - hasher.combine(flags) - } -} - -/// Determine behaviour during matching pass. -struct ConsumedLookupResultFlag: OptionSet, Hashable { - let rawValue: Int - - /// Indicates lookup ended at this name. Continue with - /// other names without matching and mark them as skipped. - static let endOfLookup = ConsumedLookupResultFlag(rawValue: 1 << 0) - /// This name prompts client to look in members of associated scope. - static let shouldLookInMembers = ConsumedLookupResultFlag(rawValue: 1 << 1) - /// The original position in result of this name - /// might be different than displayed. - static let placementRearranged = ConsumedLookupResultFlag(rawValue: 1 << 2) - /// The name should be ignored. - static let shouldBeOmitted = ConsumedLookupResultFlag(rawValue: 1 << 3) - /// If no match is found, this name should be ignored. - static let shouldBeOptionallyOmitted = ConsumedLookupResultFlag(rawValue: 1 << 4) - /// Means that one of the previous - /// names indicated the end of lookup. - static let lookupStopped = ConsumedLookupResultFlag(rawValue: 1 << 5) - /// Next names from associated position should be omitted. - /// Filtering is applied until then next name of this kind is found and - /// position used for ignoring is updated. - static let ignoreNextFromHere = ConsumedLookupResultFlag(rawValue: 1 << 6) -} - -extension SourceLocation { - fileprivate var lineWithColumn: String { - return "\(line):\(column)" - } -} - -extension String { - fileprivate func addPaddingUpTo(characters charCount: Int) -> String { - guard self.count < charCount else { return self } - - let lengthDifference = charCount - self.count - - var leftPad = "" - var rightPad = "" - - for _ in 0..<(lengthDifference / 2) { - leftPad += " " - } - - for _ in 0..<((lengthDifference + 1) / 2) { - rightPad += " " - } - - return leftPad + self + rightPad - } -} diff --git a/lib/CompilerSwiftSyntax/CMakeLists.txt b/lib/CompilerSwiftSyntax/CMakeLists.txt index 06b055fd0474f..849cf90fee0c7 100644 --- a/lib/CompilerSwiftSyntax/CMakeLists.txt +++ b/lib/CompilerSwiftSyntax/CMakeLists.txt @@ -35,7 +35,6 @@ includeSwiftSyntax() set(compiler_swiftsyntax_libs _CompilerSwiftSyntax _CompilerSwiftIfConfig - _CompilerSwiftLexicalLookup _CompilerSwiftOperators _CompilerSwiftSyntaxBuilder _CompilerSwiftParser diff --git a/test/NameLookup/SwiftLexicalLookupValidation/testGenericWhereClause.swift b/test/NameLookup/SwiftLexicalLookupValidation/testGenericWhereClause.swift deleted file mode 100644 index 649520bd8da55..0000000000000 --- a/test/NameLookup/SwiftLexicalLookupValidation/testGenericWhereClause.swift +++ /dev/null @@ -1,75 +0,0 @@ -// REQUIRES: swift_feature_UnqualifiedLookupValidation -// -// RUN: %target-typecheck-verify-swift -enable-experimental-feature UnqualifiedLookupValidation - -protocol P1 { - associatedtype A - func f() -> A -} - -protocol P2 { - associatedtype A: P2 - associatedtype B: P2 where Self.A.A == Self.B.A -} - -protocol P3 { - associatedtype A: P3 -} - -struct Basic: P1 { - typealias A = Int - func f() -> Int { fatalError() } -} - -struct Recur: P2 { - typealias A = Recur - typealias B = Recur -} - -struct NonRecur: P2 { - typealias A = Recur - typealias B = Recur -} - -struct Generic {} - -class Super {} - -extension Super: P2 where T: P2, U: P2 { - typealias A = T - typealias B = T - - func foo() -> Int { fatalError() } -} - -class Sub: Super {} - -struct RecurGeneric: P3 { - typealias A = RecurGeneric -} - -struct Specialize: P3 { - typealias A = RecurGeneric -} - -protocol P48a { associatedtype A = Int } -protocol P48b { associatedtype B } -protocol P48c: P48a, P48b where A == B {} - -public extension Array where Element == Int { - mutating func foo( - at index: Int, - byCalling closure: (inout Element) -> Void - ) where Element: Differentiable { // expected-error{{cannot find type 'Differentiable' in scope}} - closure(&self[index]) - } -} - -public extension Array { - mutating func bar( - at index: Int, - byCalling closure:(inout Element) -> Void - ) where Element: Differentiable { // expected-error{{cannot find type 'Differentiable' in scope}} - closure(&self[index]) - } -}